#!/usr/bin/env php E4)vendor/cilex/cilex/src/Cilex/Compiler.phpe BWeٱ˶9vendor/cilex/cilex/src/Cilex/ServiceProviderInterface.phpQ BWQ4u@vendor/cilex/cilex/src/Cilex/Provider/MonologServiceProvider.php BWf\cI?vendor/cilex/cilex/src/Cilex/Provider/ConfigServiceProvider.php BW D귶Avendor/cilex/cilex/src/Cilex/Provider/DoctrineServiceProvider.phpj BWj]*'Bvendor/cilex/cilex/src/Cilex/Provider/ValidatorServiceProvider.php BW`5vendor/cilex/cilex/src/Cilex/Command/GreetCommand.php BW^8vendor/cilex/cilex/src/Cilex/Command/DemoInfoCommand.php BWsCY0vendor/cilex/cilex/src/Cilex/Command/Command.php BW>G,vendor/cilex/cilex/src/Cilex/Application.php BW D^vendor/cilex/console-service-provider/src/Cilex/Provider/Console/ContainerAwareApplication.php BWQ[vendor/cilex/console-service-provider/src/Cilex/Provider/Console/ConsoleServiceProvider.php BWl7ivendor/cilex/console-service-provider/src/Cilex/Provider/Console/Adapter/Silex/ConsoleServiceProvider.php] BW]e_vendor/cilex/console-service-provider/src/Cilex/Provider/Console/BaseConsoleServiceProvider.php BWeevendor/composer/ClassLoader.php0 BW0]!vendor/composer/autoload_psr4.php BWyJ%vendor/composer/autoload_classmap.phpJ BWJ ~"vendor/composer/autoload_files.php! BW!Ɲʶ'vendor/composer/autoload_namespaces.php BW X&?vendor/composer/21b04df9/symfony-finder-203a10f/SplFileInfo.php  BW s18vendor/composer/21b04df9/symfony-finder-203a10f/Glob.php_ BW_ jCvendor/composer/21b04df9/symfony-finder-203a10f/Expression/Glob.php BWZ~Mvendor/composer/21b04df9/symfony-finder-203a10f/Expression/ValueInterface.phpH BWH"Ivendor/composer/21b04df9/symfony-finder-203a10f/Expression/Expression.php% BW% KLDvendor/composer/21b04df9/symfony-finder-203a10f/Expression/Regex.php BW;A?vendor/composer/21b04df9/symfony-finder-203a10f/Shell/Shell.php BWqAvendor/composer/21b04df9/symfony-finder-203a10f/Shell/Command.php BW_LFMvendor/composer/21b04df9/symfony-finder-203a10f/Comparator/DateComparator.php BW 'eIvendor/composer/21b04df9/symfony-finder-203a10f/Comparator/Comparator.php BWOvendor/composer/21b04df9/symfony-finder-203a10f/Comparator/NumberComparator.php BW ldJUvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/DepthRangeFilterIterator.php BW-,Nvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/FilePathsIterator.php BW ׷]Kvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/FilterIterator.php BW,GWvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/MultiplePcreFilterIterator.php BWW)<Ovendor/composer/21b04df9/symfony-finder-203a10f/Iterator/PathFilterIterator.php BWWe,Svendor/composer/21b04df9/symfony-finder-203a10f/Iterator/FilenameFilterIterator.php BWJcTvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/SizeRangeFilterIterator.php BWMvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/SortableIterator.php BW peVvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/FilecontentFilterIterator.php BW$lTvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/DateRangeFilterIterator.php BW'QSvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/FileTypeFilterIterator.phpY BWY]%[vendor/composer/21b04df9/symfony-finder-203a10f/Iterator/ExcludeDirectoryFilterIterator.php BW JQvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/CustomFilterIterator.php BWЧWvendor/composer/21b04df9/symfony-finder-203a10f/Iterator/RecursiveDirectoryIterator.php BW '_:vendor/composer/21b04df9/symfony-finder-203a10f/Finder.phpU BWU6ivKvendor/composer/21b04df9/symfony-finder-203a10f/Adapter/AbstractAdapter.php BW=ĶLvendor/composer/21b04df9/symfony-finder-203a10f/Adapter/AdapterInterface.php BW jJvendor/composer/21b04df9/symfony-finder-203a10f/Adapter/GnuFindAdapter.php BW Fvendor/composer/21b04df9/symfony-finder-203a10f/Adapter/PhpAdapter.php{ BW{ 9!2Ovendor/composer/21b04df9/symfony-finder-203a10f/Adapter/AbstractFindAdapter.php) BW) CJvendor/composer/21b04df9/symfony-finder-203a10f/Adapter/BsdFindAdapter.php BW kASvendor/composer/21b04df9/symfony-finder-203a10f/Exception/AccessDeniedException.php BWcW޶Pvendor/composer/21b04df9/symfony-finder-203a10f/Exception/ExceptionInterface.php BW7[vendor/composer/21b04df9/symfony-finder-203a10f/Exception/OperationNotPermitedException.php BWPUvendor/composer/21b04df9/symfony-finder-203a10f/Exception/AdapterFailureException.php BW>@Zvendor/composer/21b04df9/symfony-finder-203a10f/Exception/ShellCommandFailureException.php9 BW9!vendor/composer/autoload_real.php BW:T?vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Xml/HasXPath.php BWvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Description.php BWr|sp:vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matcher.php[ BW[@vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/MatcherAssert.php; BW; =wPvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsEmptyTraversable.phpe BWeSvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsTraversableWithSize.php BW|/NBvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseDescription.phpk BWk OBvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/NullDescription.php BWRAvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/AssertionError.phpw BWwF4Ovendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Internal/SelfDescribingValue.php BW<5;vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Set.phph BWh B{>vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsSame.phpF BWF7Cvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/HasToString.php BWĶDvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsInstanceOf.php BWUң?vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsEqual.phpC BWCb =vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNot.php: BW:Cvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/DescribedAs.php9 BW9T@Nvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsCollectionContaining.phpl BWl&w=vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Every.php: BW:' Cvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsIdentical.php BWn1Kvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/ShortcutCombination.php BW"'QBvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsAnything.phpk BWkGY:vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Is.phpK BWK+M{>vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNull.php BW._Ivendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/CombinableMatcher.php BWF=vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AnyOf.php BWZb.=vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AllOf.php BW3j<@vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsTypeOf.php BWٞDvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/DiagnosingMatcher.php[ BW[Byu>vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseMatcher.php BWAvBvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeMatcher.phpf BWf MDvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/StringDescription.phpc BWcնAvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/FeatureMatcher.php BWZW;vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matchers.phpJ BWJv67vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Util.php BW (Rvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInOrder.phpp BWpsLvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/SeriesMatchingOnce.php, BW,"lAvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArray.php BW t Kvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContaining.php BWhNvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKey.php BW21XWvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKeyValuePair.php BW! Uvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInAnyOrder.php BWΆFvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/MatchingOnce.phpV BWVQ*Ivendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayWithSize.php BW`Avendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/SelfDescribing.php BW̥hLvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeDiagnosingMatcher.phpI BWI~2Lvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/OrderingComparison.phpe BWe Cvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/IsCloseTo.php BW ׳i@vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsDouble.php+ BW+Bvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsCallable.php8 BW8_LAvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsNumeric.php BWku"˶@vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsObject.php BW_O橶Bvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsResource.php BWYˌ@vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsString.php BW:aAvendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsBoolean.php BW!u?vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsArray.php BW@Avendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsInteger.php BWȎpҶ@vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsScalar.php@ BW@2vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest.phpT BWT&=;vendor/hamcrest/hamcrest-php/generator/StaticMethodFile.php BWSȴ8vendor/hamcrest/hamcrest-php/generator/FactoryMethod.php BWD.G=vendor/hamcrest/hamcrest-php/generator/GlobalFunctionFile.php BWu;vendor/hamcrest/hamcrest-php/generator/FactoryGenerator.php BW G7vendor/hamcrest/hamcrest-php/generator/FactoryClass.php BW;.vendor/hamcrest/hamcrest-php/generator/run.php; BW;c]W;vendor/hamcrest/hamcrest-php/generator/FactoryParameter.php BWsT6vendor/hamcrest/hamcrest-php/generator/FactoryFile.php BW g)6vendor/hamcrest/hamcrest-php/generator/FactoryCall.phpc BWck33vendor/herrera-io/phar-update/src/lib/constants.php BW<Evendor/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Manager.php BW )]Fvendor/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Manifest.php( BW(  :Zvendor/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Exception/ExceptionInterface.php BWCEdQvendor/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Exception/Exception.php BW&<Ѷ`vendor/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Exception/InvalidArgumentException.php BW}n폶Vvendor/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Exception/LogicException.php BWöUvendor/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Exception/FileException.php BW'Dvendor/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Update.php BW-!/vendor/herrera-io/json/src/lib/json_version.php BW԰mb4vendor/herrera-io/json/src/lib/Herrera/Json/Json.phpM BWMLvendor/herrera-io/json/src/lib/Herrera/Json/Exception/ExceptionInterface.php BWsnֶCvendor/herrera-io/json/src/lib/Herrera/Json/Exception/Exception.php BWp7>Gvendor/herrera-io/json/src/lib/Herrera/Json/Exception/FileException.php BW"TGvendor/herrera-io/json/src/lib/Herrera/Json/Exception/JsonException.php BW`0vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.phpf BWf!(s4vendor/seld/jsonlint/src/Seld/JsonLint/Undefined.php BWg;vendor/seld/jsonlint/src/Seld/JsonLint/ParsingException.php0 BW0K粶5vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.phpKN BWKN,!Rvendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php BWڜ!Xvendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php BWZQyGvendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php BW`Rvendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php BW _WTvendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php\ BW\{PDvendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php BWCvendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.phpr BWr)?vendor/justinrainbow/json-schema/src/JsonSchema/RefResolver.php BW6Pvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php7 BW737ƶNvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php+ BW+בPvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php> BW>_Svendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php) BW){ZNvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php BW[Pvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.phpm BWmؿȟTvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php BWwl|Svendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.phpo BWo)03Pvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php BW hE-Jvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php  BW 0(zPvendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php  BW ~4=vendor/justinrainbow/json-schema/src/JsonSchema/Validator.php BWgpWvendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpT BWTFVvendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.phpZ BWZgSvendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php BWĭ2Rvendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.phpJ BWJY9]vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php[ BW[)bζWvendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php\ BW\iR9vendor/kherge/version/src/lib/KevinGH/Version/Version.php+( BW+(|Jvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php BW X\Mvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php BW tPvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php!0 BW!0;~Lvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php BW%*S+Svendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php BWMUvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.phpj BWj6Qvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php BW ,d[vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.phpJ BWJ ATvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php BWOvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php' BW' e?gٶIvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php BW2Fvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php BW ޶Vvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.phpI BWInTHvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php BW) Svendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php BW`ۖIvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.phpt BWt 9 Kvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php BW;Rvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php BWW hOvendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php" BW"Avendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php BWϥy %vendor/erusev/parsedown/Parsedown.php BWrC3vendor/jms/metadata/src/Metadata/MethodMetadata.php BWo1vendor/jms/metadata/src/Metadata/NullMetadata.php BW m-;vendor/jms/metadata/src/Metadata/MergeableClassMetadata.phpE BWEQt,vendor/jms/metadata/src/Metadata/Version.php BW;vendor/jms/metadata/src/Metadata/ClassHierarchyMetadata.php BW*2vendor/jms/metadata/src/Metadata/ClassMetadata.php BW O=vendor/jms/metadata/src/Metadata/MetadataFactoryInterface.phpB BWBڌT4vendor/jms/metadata/src/Metadata/MetadataFactory.phpI BWI?fg5vendor/jms/metadata/src/Metadata/PropertyMetadata.php BWEvendor/jms/metadata/src/Metadata/AdvancedMetadataFactoryInterface.php? BW?BK)<=vendor/jms/metadata/src/Metadata/Driver/LazyLoadingDriver.phpH BWH1˶7vendor/jms/metadata/src/Metadata/Driver/DriverChain.php BWR@vendor/jms/metadata/src/Metadata/Driver/FileLocatorInterface.php BWځ7vendor/jms/metadata/src/Metadata/Driver/FileLocator.php BW6>vendor/jms/metadata/src/Metadata/Driver/AbstractFileDriver.php BWxQƶHvendor/jms/metadata/src/Metadata/Driver/AdvancedFileLocatorInterface.php BW?Cvendor/jms/metadata/src/Metadata/Driver/AdvancedDriverInterface.php BWT;vendor/jms/metadata/src/Metadata/Driver/DriverInterface.phpW BWWsgA9vendor/jms/metadata/src/Metadata/Cache/CacheInterface.php BWdxm;4vendor/jms/metadata/src/Metadata/Cache/FileCache.php* BW* 5{?vendor/jms/metadata/src/Metadata/Cache/DoctrineCacheAdapter.php BW4޶7vendor/jms/metadata/src/Metadata/MergeableInterface.php BWʶ4vendor/jms/parser-lib/src/JMS/Parser/SimpleLexer.php& BW&qs=vendor/jms/parser-lib/src/JMS/Parser/SyntaxErrorException.phpd BWd6vendor/jms/parser-lib/src/JMS/Parser/AbstractLexer.php BW# 87vendor/jms/parser-lib/src/JMS/Parser/AbstractParser.phpJ BWJ.^Mvendor/jms/serializer/src/JMS/Serializer/Metadata/VirtualPropertyMetadata.php7 BW7 H6׶Cvendor/jms/serializer/src/JMS/Serializer/Metadata/ClassMetadata.php# BW#nFvendor/jms/serializer/src/JMS/Serializer/Metadata/PropertyMetadata.php BWN,Mvendor/jms/serializer/src/JMS/Serializer/Metadata/Driver/AnnotationDriver.php$ BW$wHFvendor/jms/serializer/src/JMS/Serializer/Metadata/Driver/XmlDriver.phpq- BWq-.ɵOvendor/jms/serializer/src/JMS/Serializer/Metadata/Driver/DoctrineTypeDriver.php- BW-Gvendor/jms/serializer/src/JMS/Serializer/Metadata/Driver/YamlDriver.php( BW(ꃶFvendor/jms/serializer/src/JMS/Serializer/Metadata/Driver/PhpDriver.php BWXѶLvendor/jms/serializer/src/JMS/Serializer/Metadata/StaticPropertyMetadata.php0 BW0 ([Evendor/jms/serializer/src/JMS/Serializer/JsonSerializationVisitor.php BW7iCvendor/jms/serializer/src/JMS/Serializer/DeserializationContext.php BWs7vendor/jms/serializer/src/JMS/Serializer/Serializer.php BW0Uvendor/jms/serializer/src/JMS/Serializer/EventDispatcher/EventDispatcherInterface.php' BW'gǾNvendor/jms/serializer/src/JMS/Serializer/EventDispatcher/PreSerializeEvent.php BWoDUvendor/jms/serializer/src/JMS/Serializer/EventDispatcher/EventSubscriberInterface.php BW _vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/Subscriber/DoctrineProxySubscriber.php8 BW8ybvendor/jms/serializer/src/JMS/Serializer/EventDispatcher/Subscriber/SymfonyValidatorSubscriber.phpN BWNyk-Bvendor/jms/serializer/src/JMS/Serializer/EventDispatcher/Event.php{ BW{4겶Cvendor/jms/serializer/src/JMS/Serializer/EventDispatcher/Events.php BWePvendor/jms/serializer/src/JMS/Serializer/EventDispatcher/PreDeserializeEvent.php BW{ͶPvendor/jms/serializer/src/JMS/Serializer/EventDispatcher/LazyEventDispatcher.php BWHvendor/jms/serializer/src/JMS/Serializer/EventDispatcher/ObjectEvent.php BW$ Lvendor/jms/serializer/src/JMS/Serializer/EventDispatcher/EventDispatcher.php BWН=vendor/jms/serializer/src/JMS/Serializer/Annotation/Since.php BW{Gvendor/jms/serializer/src/JMS/Serializer/Annotation/VirtualProperty.php' BW'$֋)Gvendor/jms/serializer/src/JMS/Serializer/Annotation/HandlerCallback.php BW|TRDvendor/jms/serializer/src/JMS/Serializer/Annotation/PreSerialize.php  BW m;=vendor/jms/serializer/src/JMS/Serializer/Annotation/Until.php BWߋ?vendor/jms/serializer/src/JMS/Serializer/Annotation/Exclude.php BW}\>vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlMap.phpO BWOͅ?vendor/jms/serializer/src/JMS/Serializer/Annotation/Version.php BW,Gvendor/jms/serializer/src/JMS/Serializer/Annotation/PostDeserialize.php BW|Hvendor/jms/serializer/src/JMS/Serializer/Annotation/XmlKeyValuePairs.php BW@A\n>vendor/jms/serializer/src/JMS/Serializer/Annotation/Groups.php/ BW/yy<vendor/jms/serializer/src/JMS/Serializer/Annotation/Type.php8 BW8cG>vendor/jms/serializer/src/JMS/Serializer/Annotation/Expose.php BWrFEvendor/jms/serializer/src/JMS/Serializer/Annotation/XmlCollection.phpE BWEL@vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlValue.php BWKtEvendor/jms/serializer/src/JMS/Serializer/Annotation/PostSerialize.php BW+kBvendor/jms/serializer/src/JMS/Serializer/Annotation/AccessType.phpv BWvLQ=>vendor/jms/serializer/src/JMS/Serializer/Annotation/Inline.php BW07'?vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlList.php  BW @vendor/jms/serializer/src/JMS/Serializer/Annotation/Accessor.php BW6Evendor/jms/serializer/src/JMS/Serializer/Annotation/Discriminator.php BWQĖ>?vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlRoot.php, BW,T۳Gvendor/jms/serializer/src/JMS/Serializer/Annotation/ExclusionPolicy.php BW"t=Evendor/jms/serializer/src/JMS/Serializer/Annotation/AccessorOrder.php BWzWFvendor/jms/serializer/src/JMS/Serializer/Annotation/SerializedName.php& BW& (@vendor/jms/serializer/src/JMS/Serializer/Annotation/ReadOnly.php BW[~Gvendor/jms/serializer/src/JMS/Serializer/Annotation/XmlAttributeMap.php BWA }@Dvendor/jms/serializer/src/JMS/Serializer/Annotation/XmlAttribute.php BW>4vendor/jms/serializer/src/JMS/Serializer/Context.php> BW>1X{Gvendor/jms/serializer/src/JMS/Serializer/JsonDeserializationVisitor.php BWCm8vendor/jms/serializer/src/JMS/Serializer/Util/Writer.phpl BWl bF6Jvendor/jms/serializer/src/JMS/Serializer/GenericDeserializationVisitor.phpe BWe<<vendor/jms/serializer/src/JMS/Serializer/AbstractVisitor.phpb BWb+Avendor/jms/serializer/src/JMS/Serializer/SerializationContext.php= BW= RМ@vendor/jms/serializer/src/JMS/Serializer/SerializerInterface.php BWS"Kvendor/jms/serializer/src/JMS/Serializer/Naming/CamelCaseNamingStrategy.php BW{"hTvendor/jms/serializer/src/JMS/Serializer/Naming/SerializedNameAnnotationStrategy.phpZ BWZqGvendor/jms/serializer/src/JMS/Serializer/Naming/CacheNamingStrategy.php BWOF޶Svendor/jms/serializer/src/JMS/Serializer/Naming/PropertyNamingStrategyInterface.php BW_"\Svendor/jms/serializer/src/JMS/Serializer/Naming/IdenticalPropertyNamingStrategy.php BW:OHvendor/jms/serializer/src/JMS/Serializer/GenericSerializationVisitor.php BW->vendor/jms/serializer/src/JMS/Serializer/SerializerBuilder.phpg1 BWg1GPDvendor/jms/serializer/src/JMS/Serializer/Handler/HandlerRegistry.php BW %Kvendor/jms/serializer/src/JMS/Serializer/Handler/ArrayCollectionHandler.php BW ޘ@vendor/jms/serializer/src/JMS/Serializer/Handler/DateHandler.php BWlcEvendor/jms/serializer/src/JMS/Serializer/Handler/FormErrorHandler.phpo BWoVoԦOvendor/jms/serializer/src/JMS/Serializer/Handler/ConstraintViolationHandler.phpT BWT"3Pvendor/jms/serializer/src/JMS/Serializer/Handler/SubscribingHandlerInterface.php# BW#A.Mvendor/jms/serializer/src/JMS/Serializer/Handler/HandlerRegistryInterface.phpz BWzqOkܶHvendor/jms/serializer/src/JMS/Serializer/Handler/LazyHandlerRegistry.php BW&0Ivendor/jms/serializer/src/JMS/Serializer/Handler/PhpCollectionHandler.php/ BW/ yJlNvendor/jms/serializer/src/JMS/Serializer/Exclusion/GroupsExclusionStrategy.php BWtG~ Qvendor/jms/serializer/src/JMS/Serializer/Exclusion/ExclusionStrategyInterface.php BW~/ܶOvendor/jms/serializer/src/JMS/Serializer/Exclusion/VersionExclusionStrategy.php= BW=ʾRPvendor/jms/serializer/src/JMS/Serializer/Exclusion/DisjunctExclusionStrategy.php BW E#Dvendor/jms/serializer/src/JMS/Serializer/XmlSerializationVisitor.php) BW)uzjEvendor/jms/serializer/src/JMS/Serializer/Twig/SerializerExtension.php BWplEvendor/jms/serializer/src/JMS/Serializer/YamlSerializationVisitor.php BW]Fvendor/jms/serializer/src/JMS/Serializer/XmlDeserializationVisitor.php]% BW]%ն;vendor/jms/serializer/src/JMS/Serializer/GraphNavigator.phpE3 BWE3oTPvendor/jms/serializer/src/JMS/Serializer/Exception/ValidationFailedException.phpJ BWJt5@vendor/jms/serializer/src/JMS/Serializer/Exception/Exception.php! BW!ǪHvendor/jms/serializer/src/JMS/Serializer/Exception/XmlErrorException.php BWՐQvendor/jms/serializer/src/JMS/Serializer/Exception/UnsupportedFormatException.php BWțK0Ovendor/jms/serializer/src/JMS/Serializer/Exception/InvalidArgumentException.phpm BWmFQEvendor/jms/serializer/src/JMS/Serializer/Exception/LogicException.phpO BWO[,Gvendor/jms/serializer/src/JMS/Serializer/Exception/RuntimeException.phpU BWUeV=vendor/jms/serializer/src/JMS/Serializer/VisitorInterface.php BW ^Svendor/jms/serializer/src/JMS/Serializer/Construction/DoctrineObjectConstructor.php BW Tvendor/jms/serializer/src/JMS/Serializer/Construction/ObjectConstructorInterface.php BWYlVvendor/jms/serializer/src/JMS/Serializer/Construction/UnserializeObjectConstructor.php BW5t7vendor/jms/serializer/src/JMS/Serializer/TypeParser.php BW Ѷ-vendor/monolog/monolog/src/Monolog/Logger.phpJ BWJr߶=vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php BW6ڌ=vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php BW ~L^@vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php BW-}Gvendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php BWkwCvendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php> BW>)V+=vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php~ BW~ Gvendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php BW =vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php4 BW4iGEvendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php BWaoODIvendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php BW@:vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php BW">vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.phpa BWa=H錶Dvendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php BW3 =vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.phpZ BWZKEEvendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php BW~<vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php" BW"iFCvendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.phpg BWgwU<;vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php:# BW:#!ODvendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php BW >vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php BW;}?vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php# BW# 3ֶBvendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.phpV BWVŶ?vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php BWpٶ>vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.phpL BWL U߶Fvendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php? BW?x籶>vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php BW m=vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php BW  9vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php BW<|Hvendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php BWo@<vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.phpl BWl oZvendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php BWV vܶYvendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php BWS\vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php BWoV>vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.phpl BWl!wDvendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php6 BW6 <vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php; BW; W߶<vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.phpI BWIn>vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.phpp BWpꖛ?Bvendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.phpy BWykM;vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php BWl.帶?vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php BWgiHvendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php BW]:vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php BW9;vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.phpT BWTdAvendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.phpv BWv }7~>vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.phpr BWr Y=vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php BWc#>vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php BWfp8vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php BW?vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php% BW% :vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php- BW-ꔘC:vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php BWuf;vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.phpF BWFLKn@vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.phpA BWAgBvendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php BWfǶAvendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php BWR޽@vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php' BW'ns|ʶ<vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php BWi'E<vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php8 BW8eO=vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.phpF BWF/g;vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.phpI BWI nLCvendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.phpY BWY =vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php; BW;aw#=vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.phpk( BWk(ֿ:vendor/monolog/monolog/src/Monolog/Handler/MailHandler.phpV BWVYyW:vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php BW3vendor/monolog/monolog/src/Monolog/ErrorHandler.php BWF* @vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php BW^>vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php@ BW@NBvendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php BW JEvendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php BW:@vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php* BW*wAvendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php BW Y\Avendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.phpF BWF{lCvendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php BW;`aiBvendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php BW }*3Cvendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php BWWܑ>vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php BW¨DBvendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php BW.hݶDvendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.phpf" BWf"#1>vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php BWH6Bvendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php- BW-/vendor/monolog/monolog/src/Monolog/Registry.php BWն=vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php< BW<!S(̶;vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php> BW>wABvendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php BWĝi<vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php BWw5vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.phpH BWH/5vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php BWHsͶ4vendor/nikic/php-parser/lib/PhpParser/Node/Param.php BWZ3vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.phpk BWkD3vendor/nikic/php-parser/lib/PhpParser/Node/Expr.phpk BWkPp@:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php BWjGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.phpx BWx*Cvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.phpt BWt&Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.phpw BWw!@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.phpq BWqZI@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.phpq BWqxEֶFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.phpw BWw!Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.phpx BWxu0FAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.phpr BWr[Wr Bvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.phps BWsGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.phpx BWx2ֶ@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.phpq BWq:@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.phpq BWqyGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.phpx BWxH遶Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.phpx BWx(|DGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.phpx BWxJ@Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.phpw BWwm@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.phpq BWqpFvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.phpw BWwI Dvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.phpu BWu ˶Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.phpx BWxAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.phpr BWrpGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.phpx BWxL|,Bvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.phps BWs҆ Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.phpx BWx}Evendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.phpv BWv<Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.phpw BWw2Fvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.phpw BWw@Bvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.phps BWs€VKvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php| BW|LwuEvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.phpw BWwW|]Gvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.phpx BWx@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.phpq BWqc]@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.phpq BWq2+lIvendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.phpz BWzC::;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.phpv BWv" k^?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php BW]=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php. BW. >vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php BW Cvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php BWgɶ>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php> BW> p<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php BW>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php, BW,:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php BWzpGvendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php BWK;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php BWW8vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php[ BW[uF>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php BW9߶@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.phpj BWjj*?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.phph BWhb!@vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.phpj BWj>JW>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.phph BWh8g ?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.phph BWh=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.phpg BWg6?vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.phpi BWiۯڶ>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php BW/<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php1 BW1w=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php* BW**v9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.phpP BWPH#=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.phpn BWnLAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php& BW&#H/¶9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php BW(ޱAvendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php BWt=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.phpE BWE:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php BW :vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php< BW<yu:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php BW<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php+ BW+#>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php BW8 Avendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php BWޖ;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php BWjȶ:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php BWY<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php  BW u:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php BWZq>vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php BW b:vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php BW]PU;vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php BWl8vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php BW%W9vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php9 BW9#+":vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php BWLͶ=vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.phpE BWE٪<vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php BW|(n7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php# BW#8ڶ;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.phpN BWN8:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php: BW:;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php? BW?:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php. BW.PD=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php~ BW~+,J?vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.phpe BWe ͻ8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.phpG BWG|C8vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php! BW!fg=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php BWX ;<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.phpM BWMEI9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php( BW(r9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php BW0Ӷ9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php/ BW/'6ܶ7vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php BWs<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php BW5ֶ;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.phpA BWA I'D<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php BW5=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.phpu BWuWڳ>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php^ BW^d:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.phpT BWT<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php$ BW$˗:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php} BW}:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.phpT BWTkѶ:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.phpE BWE';vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php BW7>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php} BW}ZPDvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php BW1;vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php BW(H-:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php' BW'ΰ8ֶ@vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php BWY:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.phpZ BWZXö>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php BWZKBvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php BWo>vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.phpz BWzY>=vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php` BW`OqIFvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php BW݄嘶9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php. BW.ԫ<vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.phpt BWtG9vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php BWjиQvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.phpk BWk&6'Lvendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php BW hH:vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php BW?=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php BW kE@vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php4 BW4o =vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php BWvy%>vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php; BW;)@Gvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php BW-(+<Jvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php BWBEvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php BWMGvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php BWDvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php BW}uGvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php BWEvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php BWJVKvendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php BW"8F=vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php BWwMG2vendor/nikic/php-parser/lib/PhpParser/Node/Arg.php BWi3vendor/nikic/php-parser/lib/PhpParser/Node/Name.php BW1Ѷ4vendor/nikic/php-parser/lib/PhpParser/Serializer.php BW{6vendor/nikic/php-parser/lib/PhpParser/Unserializer.php  BW v߶@vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php BWj9vendor/nikic/php-parser/lib/PhpParser/BuilderAbstract.phpM BWMo#/vendor/nikic/php-parser/lib/PhpParser/Error.php BW4sB8vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.phpu BWu }/vendor/nikic/php-parser/lib/PhpParser/Lexer.php* BW*eRXBvendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php* BW*읶7vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.phpa BWa>O5vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.phpM BWMMӶ8vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php BW P;vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php BW6vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php BW-;:vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php BW Y8vendor/nikic/php-parser/lib/PhpParser/Builder/Method.phpU BWU Ϧ>vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php BWU޶8vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php BWo<vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php BW#Զ=vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php BW3a7vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php BW7CEǶ<vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php BW@/0vendor/nikic/php-parser/lib/PhpParser/Parser.php8 BW8D4vendor/nikic/php-parser/lib/PhpParser/Autoloader.php? BW?x1vendor/nikic/php-parser/lib/PhpParser/Comment.php BWt65vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.php BW%(:vendor/nikic/php-parser/lib/PhpParser/Unserializer/XML.php8 BW8}Ϳ9vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php\# BW\#\ֶ8vendor/nikic/php-parser/lib/PhpParser/Serializer/XML.phpC BWC yʲS.vendor/nikic/php-parser/lib/PhpParser/Node.php BW %1vendor/nikic/php-parser/lib/PhpParser/Builder.php BWD\4vendor/nikic/php-parser/lib/PhpParser/NodeDumper.phpt BWth{6vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php BW pP8vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.phpK BWK&/@vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.phpFp BWFp?vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php( BW(-)vendor/nikic/php-parser/lib/bootstrap.php BW]1vendor/nikic/php-parser/grammar/rebuildParser.php BW#ۄH+vendor/nikic/php-parser/grammar/analyze.php BW Jvendor/phpcollection/phpcollection/src/PhpCollection/SequenceInterface.phpd BWdAvendor/phpcollection/phpcollection/src/PhpCollection/Sequence.php^ BW^iUEvendor/phpcollection/phpcollection/src/PhpCollection/MapInterface.phpv BWvXZWgIvendor/phpcollection/phpcollection/src/PhpCollection/AbstractSequence.php BWR׶Jvendor/phpcollection/phpcollection/src/PhpCollection/SortableInterface.phpD BWDhK-JDvendor/phpcollection/phpcollection/src/PhpCollection/AbstractMap.phpU BWUȰLvendor/phpcollection/phpcollection/src/PhpCollection/CollectionInterface.php BW<vendor/phpcollection/phpcollection/src/PhpCollection/Map.php2 BW2#bGvendor/phpcollection/phpcollection/src/PhpCollection/SortedSequence.php BW =?Kvendor/phpcollection/phpcollection/src/PhpCollection/AbstractCollection.php= BW=OTvendor/phpdocumentor/fileset/src/phpDocumentor/Fileset/Collection/IgnorePatterns.php7 BW7UP?vendor/phpdocumentor/fileset/src/phpDocumentor/Fileset/File.php BWKͶEvendor/phpdocumentor/fileset/src/phpDocumentor/Fileset/Collection.php" BW"|iYFvendor/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Exception.php BWmFvendor/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Attribute.phpB BWB BW Avendor/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Edge.php BWlwAvendor/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Node.php BWLȶBvendor/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Graph.php) BW)GjNvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/PrettyPrinter.php BW3ضOvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector.php+ BW+ S9xJvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Exception.phpR BWR:Nvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/FileReflector.phpC BWCO-Jvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Traverser.phpY BWY +Rvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/FunctionReflector.php BWOvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/TraitReflector.php BWxζFvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Lexer.php; BW;Up{=avendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector/PropertyReflector.php BW ;_vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector/MethodReflector.php BWFhavendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector/ConstantReflector.php) BW)PQRvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ConstantReflector.php; BW;G0Tbvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Event/PostDocBlockExtractionEvent.phpB BWBS!']vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Event/ExportDocBlockTagEvent.php BWUQdvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/FunctionReflector/ArgumentReflector.phpE BWE2!Svendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/InterfaceReflector.php. BW. 恡Svendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ReflectionAbstract.php BWZeYvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Exception/UnparsableFile.php BW nYvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Exception/UnreadableFile.php BW0!Qvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/IncludeReflector.phpm BWm2nNvendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/BaseReflector.php BWZJ]vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Serializer.php BWrж^vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Description.php BWԲضZvendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Context.php5 BW5l.%gvendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/PropertyWriteTag.php] BW]Rp_vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ParamTag.phpH BWH  fvendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/PropertyReadTag.php[ BW[< =bvendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/PropertyTag.phpO BWO#m^vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/UsesTag.phpE BWE.˶]vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/SeeTag.php BWi?$dvendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/DeprecatedTag.php BWK ^vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/LinkTag.phpL BWLF`vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ReturnTag.php BWpS`vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/MethodTag.php~ BW~!kͶ`vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/SourceTag.php BW n*`vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/CoversTag.phpI BWI9{]vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/VarTag.phpE BWEͶavendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ExampleTag.php BW avendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/VersionTag.phpx BWx Eƶ_vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/SinceTag.php| BW|tR`vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ThrowsTag.phpL BWL"`vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/AuthorTag.phpM BWM 1Vvendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag.php( BW(E6 bvendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Type/Collection.php BW+=4[vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Location.phpq BWqu/Rvendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock.phpc6 BWc6q1vendor/phpoption/phpoption/src/PhpOption/Some.php~ BW~ ϕ 1vendor/phpoption/phpoption/src/PhpOption/None.php BW hi3vendor/phpoption/phpoption/src/PhpOption/Option.php*+ BW*+6h7vendor/phpoption/phpoption/src/PhpOption/LazyOption.php BWb#vendor/pimple/pimple/lib/Pimple.php BWr\Ȭ/vendor/psr/log/Psr/Log/LoggerAwareInterface.php  BW SjT&vendor/psr/log/Psr/Log/LoggerTrait.php BW =+vendor/psr/log/Psr/Log/LoggerAwareTrait.php_ BW_b޶)vendor/psr/log/Psr/Log/AbstractLogger.php BW ,3vendor/psr/log/Psr/Log/InvalidArgumentException.php` BW` X1%vendor/psr/log/Psr/Log/NullLogger.php BW>#vendor/psr/log/Psr/Log/LogLevel.php8 BW8l$ӥ*vendor/psr/log/Psr/Log/LoggerInterface.php BW bEvendor/symfony/filesystem/Symfony/Component/Filesystem/Filesystem.phpC BWCPvendor/symfony/filesystem/Symfony/Component/Filesystem/Exception/IOException.php BW=鮶Wvendor/symfony/filesystem/Symfony/Component/Filesystem/Exception/ExceptionInterface.php BWev\vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerAware.phpi BWiuWvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Reference.php' BW'{P^vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/SimpleXMLElement.php BW iͶ^vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerBuilder.phpք BWքhwvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.php BWa"avendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/Extension.php BWqvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/PrependExtensionInterface.phpM BWMCojvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php BWDSضavendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerAwareTrait.php BWH 8Svendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Alias.php BW$ \vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ScopeInterface.php BW_JWvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Parameter.php BWF"Vvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Variable.php9 BW93Svendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Scope.phpm BWm,xXvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Definition.php;B BW;Bq@zdvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/DumperInterface.php BW}^vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php BWtXbl_vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php& BW&[vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/Dumper.php+ BW+N/cvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php?' BW?'ߞζ^vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/XmlDumper.phpX. BWX.-/Wvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Container.phpG BWGhvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ExpressionLanguageProvider.php( BW( Cavendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/DefinitionDecorator.php BW\|pvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php BW m;mvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.php BWgQgvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php^ BW^ ;*}fvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/TaggedContainerInterface.php BWnvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/IntrospectableContainerInterface.php4 BW4ӣՓ|vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.phpn BWnzvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.phpJ BWJܶqvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php BWlvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php BWF#+۶evendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerAwareInterface.php BWq8Irvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ParameterNotFoundException.php BW \ jvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ExceptionInterface.php BW9yvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.php BW]wvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php BWzpvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/InvalidArgumentException.php BWfvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/LogicException.php BWl.pvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php BW nvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php BWI_hvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/RuntimeException.php BW +{vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.php BWqBwvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php BW= Զnvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php BW O,lvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php BW{pvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php BW s_vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/Compiler.php5 BW5 Gpvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php5 BW5{X0nvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.php BWEŶovendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php BWStvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php& BW&ܧlvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php& BW& euvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php BW'uvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.phpg BWg ¶cvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php" BW"wvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php BW |4qvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php BWdkvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php BWҶgvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php BWavendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/PassConfig.php BWs ^svendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php BW :"orvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php BW Cipvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php BWsvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php BWu`rvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php BWfavvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php< BW<5Zsvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php BW2rvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php* BW* UƼyvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.phpF BWFL׶lvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CompilerPassInterface.php BW`6R`vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ExpressionLanguage.php BW`vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerInterface.php BW>_vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/FileLoader.php, BW,[@bvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.phpPJ BWPJ^Qcvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php5 BW5bvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php BW!"Ҷbvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/ClosureLoader.php BWבbvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/IniFileLoader.php BWO<Bvendor/symfony/console/Symfony/Component/Console/ConsoleEvents.php7 BW7ERvendor/symfony/console/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php/ BW/+Svendor/symfony/console/Symfony/Component/Console/Descriptor/DescriptorInterface.php BWJZ0<Vvendor/symfony/console/Symfony/Component/Console/Descriptor/ApplicationDescription.php BW)ŶJvendor/symfony/console/Symfony/Component/Console/Descriptor/Descriptor.php BW 8{"$Nvendor/symfony/console/Symfony/Component/Console/Descriptor/TextDescriptor.php# BW#!϶Mvendor/symfony/console/Symfony/Component/Console/Descriptor/XmlDescriptor.php& BW&M1QNvendor/symfony/console/Symfony/Component/Console/Descriptor/JsonDescriptor.php- BW-TJvendor/symfony/console/Symfony/Component/Console/Output/BufferedOutput.phph BWht|X4Kvendor/symfony/console/Symfony/Component/Console/Output/OutputInterface.php! BW! G-gFvendor/symfony/console/Symfony/Component/Console/Output/NullOutput.php BW8Rvendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutputInterface.phpK BWK0Hvendor/symfony/console/Symfony/Component/Console/Output/StreamOutput.php BW MHIvendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php^ BW^@RCBvendor/symfony/console/Symfony/Component/Console/Output/Output.php9 BW9Ivendor/symfony/console/Symfony/Component/Console/Logger/ConsoleLogger.php BWC%6Nvendor/symfony/console/Symfony/Component/Console/Input/InputAwareInterface.php^ BW^9Kh@vendor/symfony/console/Symfony/Component/Console/Input/Input.php BWJvendor/symfony/console/Symfony/Component/Console/Input/InputDefinition.phpu/ BWu/#xEvendor/symfony/console/Symfony/Component/Console/Input/ArrayInput.phpK BWKHvendor/symfony/console/Symfony/Component/Console/Input/InputArgument.php BW wIvendor/symfony/console/Symfony/Component/Console/Input/InputInterface.php BW)Dvendor/symfony/console/Symfony/Component/Console/Input/ArgvInput.php) BW)_UFvendor/symfony/console/Symfony/Component/Console/Input/InputOption.php: BW:{PFvendor/symfony/console/Symfony/Component/Console/Input/StringInput.php BW II Lvendor/symfony/console/Symfony/Component/Console/Question/ChoiceQuestion.php$ BW$ͰRvendor/symfony/console/Symfony/Component/Console/Question/ConfirmationQuestion.php$ BW$弸!Fvendor/symfony/console/Symfony/Component/Console/Question/Question.phpl BWlA<Pvendor/symfony/console/Symfony/Component/Console/Event/ConsoleExceptionEvent.php= BW=ŶNvendor/symfony/console/Symfony/Component/Console/Event/ConsoleCommandEvent.php8 BW8 j"Gvendor/symfony/console/Symfony/Component/Console/Event/ConsoleEvent.php BW Pvendor/symfony/console/Symfony/Component/Console/Event/ConsoleTerminateEvent.php BW{eIvendor/symfony/console/Symfony/Component/Console/Tester/CommandTester.phpK BWKtIMvendor/symfony/console/Symfony/Component/Console/Tester/ApplicationTester.php[ BW[ /IDvendor/symfony/console/Symfony/Component/Console/Command/Command.phpE BWED@Hvendor/symfony/console/Symfony/Component/Console/Command/HelpCommand.phpb BWb "$Hvendor/symfony/console/Symfony/Component/Console/Command/ListCommand.php BW ["Lvendor/symfony/console/Symfony/Component/Console/Helper/InputAwareHelper.php BW˶Gvendor/symfony/console/Symfony/Component/Console/Helper/TableHelper.php BWIvendor/symfony/console/Symfony/Component/Console/Helper/ProcessHelper.php BW*E0Hvendor/symfony/console/Symfony/Component/Console/Helper/DialogHelper.php@ BW@ IPvendor/symfony/console/Symfony/Component/Console/Helper/DebugFormatterHelper.phpS BWS=ƶJvendor/symfony/console/Symfony/Component/Console/Helper/ProgressHelper.php// BW// rFvendor/symfony/console/Symfony/Component/Console/Helper/TableStyle.phpO BWO^xҶKvendor/symfony/console/Symfony/Component/Console/Helper/HelperInterface.php BWz׶Avendor/symfony/console/Symfony/Component/Console/Helper/Table.phpm( BWm('Bvendor/symfony/console/Symfony/Component/Console/Helper/Helper.phpL BWL du ZJvendor/symfony/console/Symfony/Component/Console/Helper/QuestionHelper.php@1 BW@1;Lvendor/symfony/console/Symfony/Component/Console/Helper/DescriptorHelper.php BW 9u:Gvendor/symfony/console/Symfony/Component/Console/Helper/ProgressBar.phpB BWBz=߶Kvendor/symfony/console/Symfony/Component/Console/Helper/FormatterHelper.php BW "*Jvendor/symfony/console/Symfony/Component/Console/Helper/TableSeparator.php BWn Evendor/symfony/console/Symfony/Component/Console/Helper/HelperSet.php BW ݖ@vendor/symfony/console/Symfony/Component/Console/Application.php BWQӶ:vendor/symfony/console/Symfony/Component/Console/Shell.php BWքXvendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php BW 9B۶Wvendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterInterface.php BWzNvendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php9 BW9\vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php BW5Svendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyle.php BWÒNfvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/SerializedParsedExpression.phpe BWe,ovendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/ExpressionFunctionProviderInterface.php BWU Tvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Compiler.php BW ^~^Wvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/SyntaxError.php BWݸYvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/NameNode.php BWz\vendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php BW icZvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/UnaryNode.php BW@^vendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/ArgumentsNode.php BWe7]vendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/FunctionNode.php BW#M]vendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/ConstantNode.php BW. HPZvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/ArrayNode.php BW]o[Uvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/Node.php BWbٶ`vendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/ConditionalNode.php BWc#[vendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/BinaryNode.phpD BWD\vendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/ParsedExpression.phpv BWvݾöqvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Resources/bin/generate_operator_regex.phpU BWUQvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Lexer.php  BW 8lvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/ParserCache/ParserCacheInterface.php BWӶ[hvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/ParserCache/ArrayParserCache.phpN BWN?4Rvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Parser.php> BW>߶Wvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/TokenStream.phpi BWi6y^vendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/ExpressionFunction.php BW`|<ĶQvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Token.phpy BWyd!Vvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/Expression.php BW)^vendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php BW ׶Hvendor/symfony/process/Symfony/Component/Process/PhpExecutableFinder.phpk BWk Evendor/symfony/process/Symfony/Component/Process/ExecutableFinder.php BW uf<vendor/symfony/process/Symfony/Component/Process/Process.phpb BWbK}Avendor/symfony/process/Symfony/Component/Process/ProcessUtils.php< BW< Hf?vendor/symfony/process/Symfony/Component/Process/PhpProcess.php BWdXIvendor/symfony/process/Symfony/Component/Process/Pipes/PipesInterface.phpw BWwX]Hvendor/symfony/process/Symfony/Component/Process/Pipes/AbstractPipes.phpN BWN6ryGvendor/symfony/process/Symfony/Component/Process/Pipes/WindowsPipes.php6 BW6CfTCDvendor/symfony/process/Symfony/Component/Process/Pipes/UnixPipes.php BWzWvendor/symfony/process/Symfony/Component/Process/Exception/ProcessTimedOutException.php{ BW{2Qvendor/symfony/process/Symfony/Component/Process/Exception/ExceptionInterface.php BW<Wvendor/symfony/process/Symfony/Component/Process/Exception/InvalidArgumentException.php BW˅Mvendor/symfony/process/Symfony/Component/Process/Exception/LogicException.php BWWOvendor/symfony/process/Symfony/Component/Process/Exception/RuntimeException.php BW>HUvendor/symfony/process/Symfony/Component/Process/Exception/ProcessFailedException.phpE BWEkҐCvendor/symfony/process/Symfony/Component/Process/ProcessBuilder.php BW4YRvendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/GenericEvent.php? BW?m|^vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcherInterface.php BW "cvendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php BW56^vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventSubscriberInterface.php- BW-/^vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php BWOhKvendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Event.php BW f mdvendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php!( BW!(PX̶mvendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php# BW#Ӗc[vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/WrappedListener.php BWM} ovendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php BW ǶUvendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php BWR>vendor/symfony/finder/Symfony/Component/Finder/SplFileInfo.php  BW s17vendor/symfony/finder/Symfony/Component/Finder/Glob.php_ BW_ jBvendor/symfony/finder/Symfony/Component/Finder/Expression/Glob.php BWZ~Lvendor/symfony/finder/Symfony/Component/Finder/Expression/ValueInterface.phpH BWH"Hvendor/symfony/finder/Symfony/Component/Finder/Expression/Expression.php% BW% KLCvendor/symfony/finder/Symfony/Component/Finder/Expression/Regex.php BW;A>vendor/symfony/finder/Symfony/Component/Finder/Shell/Shell.php BWq@vendor/symfony/finder/Symfony/Component/Finder/Shell/Command.php BW_LFLvendor/symfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php BW 'eHvendor/symfony/finder/Symfony/Component/Finder/Comparator/Comparator.php BWNvendor/symfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php BW ldJTvendor/symfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php BW-,Mvendor/symfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php BW ׷]Jvendor/symfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php BW,GVvendor/symfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php BWW)<Nvendor/symfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php BWWe,Rvendor/symfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php BWJcSvendor/symfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php BWLvendor/symfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.php BW peUvendor/symfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php BW$lSvendor/symfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php BW'QRvendor/symfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpY BWY]%Zvendor/symfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php BW JPvendor/symfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php BWЧVvendor/symfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php BW '_9vendor/symfony/finder/Symfony/Component/Finder/Finder.phpU BWU6ivJvendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php BW=ĶKvendor/symfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php BW jIvendor/symfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php BW Evendor/symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php{ BW{ 9!2Nvendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php) BW) CIvendor/symfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php BW kARvendor/symfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php BWcW޶Ovendor/symfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php BW7Zvendor/symfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.php BWPTvendor/symfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php BW>@Yvendor/symfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php9 BW93vendor/symfony/yaml/Symfony/Component/Yaml/Yaml.php BW G5vendor/symfony/yaml/Symfony/Component/Yaml/Parser.phph BWh.5vendor/symfony/yaml/Symfony/Component/Yaml/Dumper.php BW lD5vendor/symfony/yaml/Symfony/Component/Yaml/Inline.phpbM BWbMoܗ8vendor/symfony/yaml/Symfony/Component/Yaml/Unescaper.php BW 6Kvendor/symfony/yaml/Symfony/Component/Yaml/Exception/ExceptionInterface.php BW+lFvendor/symfony/yaml/Symfony/Component/Yaml/Exception/DumpException.php BWؙ՚Gvendor/symfony/yaml/Symfony/Component/Yaml/Exception/ParseException.php BW79Ivendor/symfony/yaml/Symfony/Component/Yaml/Exception/RuntimeException.php BW|-6vendor/symfony/yaml/Symfony/Component/Yaml/Escaper.php BWKLvendor/symfony/class-loader/Symfony/Component/ClassLoader/ApcClassLoader.php BWIvendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassLoader.php BW;zUvendor/symfony/class-loader/Symfony/Component/ClassLoader/ApcUniversalClassLoader.phpJ BWJ a8ͶOvendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassMapGenerator.php3 BW3źQvendor/symfony/class-loader/Symfony/Component/ClassLoader/WinCacheClassLoader.php BWoeWvendor/symfony/class-loader/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php BWMvendor/symfony/class-loader/Symfony/Component/ClassLoader/Psr4ClassLoader.phpm BWmuTOvendor/symfony/class-loader/Symfony/Component/ClassLoader/XcacheClassLoader.php BWgSvendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassCollectionLoader.phpN. BWN.Rvendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php" BW"Lvendor/symfony/class-loader/Symfony/Component/ClassLoader/MapClassLoader.php BW34Nvendor/symfony/class-loader/Symfony/Component/ClassLoader/DebugClassLoader.php BW 6tOvendor/symfony/translation/Symfony/Component/Translation/IdentityTranslator.php BW2Uvendor/symfony/translation/Symfony/Component/Translation/Writer/TranslationWriter.php} BW}P?Ovendor/symfony/translation/Symfony/Component/Translation/PluralizationRules.php BWwYvendor/symfony/translation/Symfony/Component/Translation/Extractor/ExtractorInterface.php BWArPUvendor/symfony/translation/Symfony/Component/Translation/Extractor/ChainExtractor.php BWPvendor/symfony/translation/Symfony/Component/Translation/TranslatorInterface.phpI BWIMvendor/symfony/translation/Symfony/Component/Translation/MessageCatalogue.php BWy4Lvendor/symfony/translation/Symfony/Component/Translation/MessageSelector.php+ BW+ Vvendor/symfony/translation/Symfony/Component/Translation/MessageCatalogueInterface.php BWֶPvendor/symfony/translation/Symfony/Component/Translation/Dumper/PoFileDumper.php BWPycSvendor/symfony/translation/Symfony/Component/Translation/Dumper/DumperInterface.php* BW*<Qvendor/symfony/translation/Symfony/Component/Translation/Dumper/IniFileDumper.php BW&XQvendor/symfony/translation/Symfony/Component/Translation/Dumper/PhpFileDumper.phpL BWL! 0Tvendor/symfony/translation/Symfony/Component/Translation/Dumper/IcuResFileDumper.php BWM Qvendor/symfony/translation/Symfony/Component/Translation/Dumper/CsvFileDumper.php BWoBͶRvendor/symfony/translation/Symfony/Component/Translation/Dumper/YamlFileDumper.php6 BW6Svendor/symfony/translation/Symfony/Component/Translation/Dumper/XliffFileDumper.php BW<̧Nvendor/symfony/translation/Symfony/Component/Translation/Dumper/FileDumper.php[ BW[2Pvendor/symfony/translation/Symfony/Component/Translation/Dumper/QtFileDumper.phpG BWG>{Pvendor/symfony/translation/Symfony/Component/Translation/Dumper/MoFileDumper.phpA BWA ׶Gvendor/symfony/translation/Symfony/Component/Translation/Translator.php BWU<Yvendor/symfony/translation/Symfony/Component/Translation/Catalogue/OperationInterface.php  BW Y[Xvendor/symfony/translation/Symfony/Component/Translation/Catalogue/AbstractOperation.php BW fbTvendor/symfony/translation/Symfony/Component/Translation/Catalogue/DiffOperation.php BWӶUvendor/symfony/translation/Symfony/Component/Translation/Catalogue/MergeOperation.php BWسSvendor/symfony/translation/Symfony/Component/Translation/MetadataAwareInterface.php BW%MtYvendor/symfony/translation/Symfony/Component/Translation/Exception/ExceptionInterface.php BW6"_vendor/symfony/translation/Symfony/Component/Translation/Exception/InvalidResourceException.php BWDŽ`vendor/symfony/translation/Symfony/Component/Translation/Exception/NotFoundResourceException.php BW2BSvendor/symfony/translation/Symfony/Component/Translation/Loader/XliffFileLoader.phpA BWA8tTvendor/symfony/translation/Symfony/Component/Translation/Loader/IcuDatFileLoader.php BWTöPvendor/symfony/translation/Symfony/Component/Translation/Loader/MoFileLoader.php BW0Pvendor/symfony/translation/Symfony/Component/Translation/Loader/PoFileLoader.php BWʶSvendor/symfony/translation/Symfony/Component/Translation/Loader/LoaderInterface.php- BW-Rvendor/symfony/translation/Symfony/Component/Translation/Loader/YamlFileLoader.php BW:޶Tvendor/symfony/translation/Symfony/Component/Translation/Loader/IcuResFileLoader.phpz BWz CSQvendor/symfony/translation/Symfony/Component/Translation/Loader/PhpFileLoader.php; BW;rPvendor/symfony/translation/Symfony/Component/Translation/Loader/QtFileLoader.php BW r;(Qvendor/symfony/translation/Symfony/Component/Translation/Loader/CsvFileLoader.php" BW" i3Qvendor/symfony/translation/Symfony/Component/Translation/Loader/IniFileLoader.php BWN@ Ovendor/symfony/translation/Symfony/Component/Translation/Loader/ArrayLoader.php BWREvendor/symfony/translation/Symfony/Component/Translation/Interval.php BW g?ZBvendor/symfony/stopwatch/Symfony/Component/Stopwatch/Stopwatch.phpC BWCƘHvendor/symfony/stopwatch/Symfony/Component/Stopwatch/StopwatchPeriod.phpl BWlGvendor/symfony/stopwatch/Symfony/Component/Stopwatch/StopwatchEvent.php` BW`@E@vendor/symfony/stopwatch/Symfony/Component/Stopwatch/Section.php BW2EmGvendor/symfony/config/Symfony/Component/Config/FileLocatorInterface.php{ BW{KIvendor/symfony/config/Symfony/Component/Config/Definition/NumericNode.php. BW.>Fvendor/symfony/config/Symfony/Component/Config/Definition/BaseNode.php! BW!׶Mvendor/symfony/config/Symfony/Component/Config/Definition/ReferenceDumper.php0 BW00۶Fvendor/symfony/config/Symfony/Component/Config/Definition/EnumNode.php  BW aVpJvendor/symfony/config/Symfony/Component/Config/Definition/VariableNode.php BW m Ivendor/symfony/config/Symfony/Component/Config/Definition/IntegerNode.php BW@Gvendor/symfony/config/Symfony/Component/Config/Definition/Processor.php' BW' UGvendor/symfony/config/Symfony/Component/Config/Definition/FloatNode.phpP BWPKYvendor/symfony/config/Symfony/Component/Config/Definition/Builder/NodeParentInterface.php BWYӶ[vendor/symfony/config/Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.php BW'nڭWvendor/symfony/config/Symfony/Component/Config/Definition/Builder/ValidationBuilder.php\ BW\XNI[vendor/symfony/config/Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.php BW= Qvendor/symfony/config/Symfony/Component/Config/Definition/Builder/TreeBuilder.php BWVhUZvendor/symfony/config/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php5 BW5@)Yvendor/symfony/config/Symfony/Component/Config/Definition/Builder/FloatNodeDefinition.php BWtpXvendor/symfony/config/Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php BW<Yvendor/symfony/config/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php9 BW9URvendor/symfony/config/Symfony/Component/Config/Definition/Builder/MergeBuilder.phpv BWv&\vendor/symfony/config/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php BWS2Zvendor/symfony/config/Symfony/Component/Config/Definition/Builder/ScalarNodeDefinition.php BWYTvendor/symfony/config/Symfony/Component/Config/Definition/Builder/NodeDefinition.php@ BW@נcvendor/symfony/config/Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php` BW`8*=Qvendor/symfony/config/Symfony/Component/Config/Definition/Builder/NodeBuilder.php BWp 6jQvendor/symfony/config/Symfony/Component/Config/Definition/Builder/ExprBuilder.php> BW>Jȵ[vendor/symfony/config/Symfony/Component/Config/Definition/Builder/NumericNodeDefinition.phpZ BWZJ>pXvendor/symfony/config/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php  BW MsWvendor/symfony/config/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php|& BW|&ƶGvendor/symfony/config/Symfony/Component/Config/Definition/ArrayNode.php?+ BW?+d#+Ivendor/symfony/config/Symfony/Component/Config/Definition/BooleanNode.php  BW (CĶQvendor/symfony/config/Symfony/Component/Config/Definition/Exception/Exception.php BWpo:]vendor/symfony/config/Symfony/Component/Config/Definition/Exception/DuplicateKeyException.phpE BWE|bvendor/symfony/config/Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.php BW]F4evendor/symfony/config/Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.phpR BWRh'NYvendor/symfony/config/Symfony/Component/Config/Definition/Exception/UnsetKeyException.php BWcvendor/symfony/config/Symfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.phpQ BWQ:2&\vendor/symfony/config/Symfony/Component/Config/Definition/Exception/InvalidTypeException.php BW@Hvendor/symfony/config/Symfony/Component/Config/Definition/ScalarNode.php BWZ^Qvendor/symfony/config/Symfony/Component/Config/Definition/PrototypedArrayNode.php' BW'qUTvendor/symfony/config/Symfony/Component/Config/Definition/PrototypeNodeInterface.phpw BWweTvendor/symfony/config/Symfony/Component/Config/Definition/ConfigurationInterface.phpe BWe\Kvendor/symfony/config/Symfony/Component/Config/Definition/NodeInterface.php BW@vendor/symfony/config/Symfony/Component/Config/Util/XmlUtils.php BW>vendor/symfony/config/Symfony/Component/Config/FileLocator.phpi BWi ݆۶Mvendor/symfony/config/Symfony/Component/Config/Resource/ResourceInterface.php, BW,Mvendor/symfony/config/Symfony/Component/Config/Resource/DirectoryResource.php BW xqHvendor/symfony/config/Symfony/Component/Config/Resource/FileResource.php BWSTvendor/symfony/config/Symfony/Component/Config/Exception/FileLoaderLoadException.php BW ׶gvendor/symfony/config/Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.phpC BWCWׯ>vendor/symfony/config/Symfony/Component/Config/ConfigCache.php BW 0Dvendor/symfony/config/Symfony/Component/Config/Loader/FileLoader.php BWwso^Ivendor/symfony/config/Symfony/Component/Config/Loader/LoaderInterface.php BW|;Jvendor/symfony/config/Symfony/Component/Config/Loader/DelegatingLoader.phpb BWbPmQvendor/symfony/config/Symfony/Component/Config/Loader/LoaderResolverInterface.php BW!KĶ@vendor/symfony/config/Symfony/Component/Config/Loader/Loader.phpF BWFu|hHvendor/symfony/config/Symfony/Component/Config/Loader/LoaderResolver.php BW$.Xvendor/symfony/validator/Symfony/Component/Validator/Context/ExecutionContextFactory.php BW+avendor/symfony/validator/Symfony/Component/Validator/Context/ExecutionContextFactoryInterface.php% BW%ohhZvendor/symfony/validator/Symfony/Component/Validator/Context/ExecutionContextInterface.php$ BW$S6Wvendor/symfony/validator/Symfony/Component/Validator/Context/LegacyExecutionContext.phpw BWwx`^vendor/symfony/validator/Symfony/Component/Validator/Context/LegacyExecutionContextFactory.php7 BW7{Qvendor/symfony/validator/Symfony/Component/Validator/Context/ExecutionContext.php(' BW('[Jvendor/symfony/validator/Symfony/Component/Validator/MetadataInterface.php' BW' Kvendor/symfony/validator/Symfony/Component/Validator/ValidatorInterface.php BWbHٶIvendor/symfony/validator/Symfony/Component/Validator/ValidatorBuilder.phpc0 BWc0ZL>RUvendor/symfony/validator/Symfony/Component/Validator/ConstraintViolationInterface.php BW cvendor/symfony/validator/Symfony/Component/Validator/Violation/LegacyConstraintViolationBuilder.phpx BWx H4%fvendor/symfony/validator/Symfony/Component/Validator/Violation/ConstraintViolationBuilderInterface.phpM BWM Jvendor/symfony/validator/Symfony/Component/Validator/Constraints/Email.php BWTvendor/symfony/validator/Symfony/Component/Validator/Constraints/ChoiceValidator.php BWR߶Ovendor/symfony/validator/Symfony/Component/Validator/Constraints/NotEqualTo.php! BW!yӶIvendor/symfony/validator/Symfony/Component/Validator/Constraints/Luhn.php BWijOvendor/symfony/validator/Symfony/Component/Validator/Constraints/Expression.php BWHfJvendor/symfony/validator/Symfony/Component/Validator/Constraints/Regex.phpl BWl 1GRvendor/symfony/validator/Symfony/Component/Validator/Constraints/IbanValidator.phpV BWV-Dj0Ivendor/symfony/validator/Symfony/Component/Validator/Constraints/Isbn.php/ BW/bMvendor/symfony/validator/Symfony/Component/Validator/Constraints/Traverse.php BW: -Ovendor/symfony/validator/Symfony/Component/Validator/Constraints/CardScheme.php? BW?ͶRvendor/symfony/validator/Symfony/Component/Validator/Constraints/DateValidator.phps BWs4Tvendor/symfony/validator/Symfony/Component/Validator/Constraints/LocaleValidator.php BWܒPvendor/symfony/validator/Symfony/Component/Validator/Constraints/IpValidator.phpY BWY :Rvendor/symfony/validator/Symfony/Component/Validator/Constraints/NullValidator.php BWO}%Uvendor/symfony/validator/Symfony/Component/Validator/ConstraintValidatorInterface.php BW,'Rvendor/symfony/validator/Symfony/Component/Validator/ValidatorBuilderInterface.php> BW>bSvendor/symfony/validator/Symfony/Component/Validator/ConstraintValidatorFactory.phph BWh?pRvendor/symfony/validator/Symfony/Component/Validator/PropertyMetadataInterface.php~ BW~Rvendor/symfony/validator/Symfony/Component/Validator/ExecutionContextInterface.php4 BW4[Lvendor/symfony/validator/Symfony/Component/Validator/ClassBasedInterface.php BWxBvendor/symfony/validator/Symfony/Component/Validator/Validator.phpg BWg]Yvendor/symfony/validator/Symfony/Component/Validator/ConstraintViolationListInterface.php BW⿶Cvendor/symfony/validator/Symfony/Component/Validator/Constraint.php0& BW0&\bXvendor/symfony/validator/Symfony/Component/Validator/GlobalExecutionContextInterface.php' BW'$Ivendor/symfony/validator/Symfony/Component/Validator/ExecutionContext.phpf! BWf! SeCvendor/symfony/validator/Symfony/Component/Validator/Validation.php BW@Uvendor/symfony/validator/Symfony/Component/Validator/Exception/ExceptionInterface.php BWT_vendor/symfony/validator/Symfony/Component/Validator/Exception/UnsupportedMetadataException.php BW [vendor/symfony/validator/Symfony/Component/Validator/Exception/InvalidArgumentException.php BW\Svendor/symfony/validator/Symfony/Component/Validator/Exception/MappingException.phpV BWVQZvendor/symfony/validator/Symfony/Component/Validator/Exception/NoSuchMetadataException.php BWxSvendor/symfony/validator/Symfony/Component/Validator/Exception/RuntimeException.php BWz`vendor/symfony/validator/Symfony/Component/Validator/Exception/ConstraintDefinitionException.phpc BWc1"Zvendor/symfony/validator/Symfony/Component/Validator/Exception/InvalidOptionsException.phpR BWRLЉ[vendor/symfony/validator/Symfony/Component/Validator/Exception/GroupDefinitionException.php^ BW^M#Yvendor/symfony/validator/Symfony/Component/Validator/Exception/BadMethodCallException.php BWyĶWvendor/symfony/validator/Symfony/Component/Validator/Exception/OutOfBoundsException.php BW|Zvendor/symfony/validator/Symfony/Component/Validator/Exception/UnexpectedTypeException.php< BW<bɶZvendor/symfony/validator/Symfony/Component/Validator/Exception/MissingOptionsException.phpR BWRuնUvendor/symfony/validator/Symfony/Component/Validator/Exception/ValidatorException.phpV BWV $Rvendor/symfony/validator/Symfony/Component/Validator/Mapping/CascadingStrategy.php BW,avendor/symfony/validator/Symfony/Component/Validator/Mapping/Factory/MetadataFactoryInterface.php~ BW~L&*avendor/symfony/validator/Symfony/Component/Validator/Mapping/Factory/BlackHoleMetadataFactory.php BW&scvendor/symfony/validator/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php BWmRvendor/symfony/validator/Symfony/Component/Validator/Mapping/MetadataInterface.php BWo֏Yvendor/symfony/validator/Symfony/Component/Validator/Mapping/BlackholeMetadataFactory.php BWv&xFOvendor/symfony/validator/Symfony/Component/Validator/Mapping/GetterMetadata.php BWOvendor/symfony/validator/Symfony/Component/Validator/Mapping/MemberMetadata.php BW멈Nvendor/symfony/validator/Symfony/Component/Validator/Mapping/ClassMetadata.php? BW?GZOZvendor/symfony/validator/Symfony/Component/Validator/Mapping/PropertyMetadataInterface.phpN BWNEȶQvendor/symfony/validator/Symfony/Component/Validator/Mapping/PropertyMetadata.php^ BW^o<` Uvendor/symfony/validator/Symfony/Component/Validator/Mapping/ClassMetadataFactory.php BW>y;Rvendor/symfony/validator/Symfony/Component/Validator/Mapping/TraversalStrategy.phpF BWFcUvendor/symfony/validator/Symfony/Component/Validator/Mapping/Cache/CacheInterface.php) BW)P `Ovendor/symfony/validator/Symfony/Component/Validator/Mapping/Cache/ApcCache.php$ BW$\ Tvendor/symfony/validator/Symfony/Component/Validator/Mapping/Cache/DoctrineCache.php` BW`KPvendor/symfony/validator/Symfony/Component/Validator/Mapping/GenericMetadata.php BW3qPvendor/symfony/validator/Symfony/Component/Validator/Mapping/ElementMetadata.phpN BWN-RZvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php0 BW0Rvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/FileLoader.php] BW]+Uvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php BWWvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/YamlFilesLoader.php BWWvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/LoaderInterface.php BW33Xvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php BW ̐Vvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.phpV BWV%)޶Vvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/XmlFilesLoader.php BWaCVvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php BW pxSvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/LoaderChain.php^ BW^mSvendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/FilesLoader.php BWg8Wvendor/symfony/validator/Symfony/Component/Validator/Mapping/ClassMetadataInterface.php BW Uvendor/symfony/validator/Symfony/Component/Validator/Validator/ValidatorInterface.php BWMwS̶Uvendor/symfony/validator/Symfony/Component/Validator/Validator/RecursiveValidator.php BWN_vendor/symfony/validator/Symfony/Component/Validator/Validator/ContextualValidatorInterface.php BW uԋ_vendor/symfony/validator/Symfony/Component/Validator/Validator/RecursiveContextualValidator.phpN BWN 0Rvendor/symfony/validator/Symfony/Component/Validator/Validator/LegacyValidator.php@ BW@ l Svendor/symfony/validator/Symfony/Component/Validator/ObjectInitializerInterface.php1 BW1z9Pvendor/symfony/validator/Symfony/Component/Validator/ConstraintViolationList.php BW -Svendor/symfony/validator/Symfony/Component/Validator/ValidationVisitorInterface.php BW5vendor/twig/twig/lib/Twig/FilterCallableInterface.php BWX϶3vendor/twig/twig/lib/Twig/TestCallableInterface.php BWڶ3vendor/twig/twig/lib/Twig/TokenParser/Spaceless.phpp BWp)P/vendor/twig/twig/lib/Twig/TokenParser/Flush.php BWGd޶,vendor/twig/twig/lib/Twig/TokenParser/If.php BW sJ)-vendor/twig/twig/lib/Twig/TokenParser/Set.php BW S1vendor/twig/twig/lib/Twig/TokenParser/Include.php6 BW6bwʶ.vendor/twig/twig/lib/Twig/TokenParser/From.php BW#6/vendor/twig/twig/lib/Twig/TokenParser/Block.phpD BWD RB1vendor/twig/twig/lib/Twig/TokenParser/Sandbox.php BW+`0vendor/twig/twig/lib/Twig/TokenParser/Import.php BW8/vendor/twig/twig/lib/Twig/TokenParser/Embed.php BW<Ⴖ1vendor/twig/twig/lib/Twig/TokenParser/Extends.phpK BWK3,vendor/twig/twig/lib/Twig/TokenParser/Do.php BWZ 0vendor/twig/twig/lib/Twig/TokenParser/Filter.php BWK4vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php BW "׶-vendor/twig/twig/lib/Twig/TokenParser/For.php BWV-vendor/twig/twig/lib/Twig/TokenParser/Use.phpW BWW۞E/vendor/twig/twig/lib/Twig/TokenParser/Macro.php BW G<&vendor/twig/twig/lib/Twig/Compiler.php BW $vendor/twig/twig/lib/Twig/Markup.php BWE "vendor/twig/twig/lib/Twig/Test.php BWl+vendor/twig/twig/lib/Twig/Error/Runtime.php BW }ܶ*vendor/twig/twig/lib/Twig/Error/Syntax.php BW :*vendor/twig/twig/lib/Twig/Error/Loader.php BWH@$,vendor/twig/twig/lib/Twig/Node/Spaceless.php BW(vendor/twig/twig/lib/Twig/Node/Flush.php BWDj%vendor/twig/twig/lib/Twig/Node/If.php BW-E&vendor/twig/twig/lib/Twig/Node/Set.php BW Z=O*vendor/twig/twig/lib/Twig/Node/Include.php BW 1vendor/twig/twig/lib/Twig/Node/BlockReference.php BWq(vendor/twig/twig/lib/Twig/Node/Block.phpB BWB*vendor/twig/twig/lib/Twig/Node/Sandbox.php BW!1vendor/twig/twig/lib/Twig/Node/SandboxedPrint.phpg BWg8vendor/twig/twig/lib/Twig/Node/Expression/MethodCall.php BW&P2vendor/twig/twig/lib/Twig/Node/Expression/Test.php BW<vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.phpt BWt7vendor/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php BWd 7vendor/twig/twig/lib/Twig/Node/Expression/Unary/Not.php BW5A7vendor/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php BW`2vendor/twig/twig/lib/Twig/Node/Expression/Call.phpF% BWF%t6vendor/twig/twig/lib/Twig/Node/Expression/Function.phpl BWl 8vendor/twig/twig/lib/Twig/Node/Expression/AssignName.phpr BWrtxG<vendor/twig/twig/lib/Twig/Node/Expression/Filter/Default.php/ BW/"3vendor/twig/twig/lib/Twig/Node/Expression/Array.php8 BW8 +V9vendor/twig/twig/lib/Twig/Node/Expression/Conditional.php BW%٠4vendor/twig/twig/lib/Twig/Node/Expression/Parent.php BW)]I6vendor/twig/twig/lib/Twig/Node/Expression/Constant.php- BW-Dȶ5vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php BW M:vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php BWn}?vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php BW)I7vendor/twig/twig/lib/Twig/Node/Expression/Binary/Or.php BWQ=vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php| BW|<vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php BWhPAvendor/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php BWJf¶;vendor/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php BWeO?vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.phpq BWq*7vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php BW%rn>vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php BWVT8vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php BWc<vendor/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php BWī8vendor/twig/twig/lib/Twig/Node/Expression/Binary/Div.php BW ?vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php BWIl:vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php BWVBV>vendor/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php BW$_8vendor/twig/twig/lib/Twig/Node/Expression/Binary/Add.php BW(H9vendor/twig/twig/lib/Twig/Node/Expression/Binary/Less.php BWiض=vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php BWZ=vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php BWe:vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php BWi:vendor/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php BW -8vendor/twig/twig/lib/Twig/Node/Expression/Binary/And.php BWgP8vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php BW]8vendor/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php BW b3vendor/twig/twig/lib/Twig/Node/Expression/Unary.php BW~P4vendor/twig/twig/lib/Twig/Node/Expression/Filter.php BW 6vendor/twig/twig/lib/Twig/Node/Expression/TempName.phpR BWR2vendor/twig/twig/lib/Twig/Node/Expression/Name.php BW ڧ4vendor/twig/twig/lib/Twig/Node/Expression/Binary.php BWAo@vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php0 BW0>))vendor/twig/twig/lib/Twig/Node/Module.phpB3 BWB3G4)vendor/twig/twig/lib/Twig/Node/Import.php BWH(vendor/twig/twig/lib/Twig/Node/Embed.php BW֨Ͷ(vendor/twig/twig/lib/Twig/Node/Print.php BWYc%vendor/twig/twig/lib/Twig/Node/Do.phpQ BWQF-ն-vendor/twig/twig/lib/Twig/Node/AutoEscape.php BWP0xN&vendor/twig/twig/lib/Twig/Node/For.php BW0vendor/twig/twig/lib/Twig/Node/CheckSecurity.php BW q-*vendor/twig/twig/lib/Twig/Node/ForLoop.phpa BWa,.-vendor/twig/twig/lib/Twig/Node/Expression.php BWAW'vendor/twig/twig/lib/Twig/Node/Body.phpQ BWQ3'vendor/twig/twig/lib/Twig/Node/Text.phpr BWrn*vendor/twig/twig/lib/Twig/Node/SetTemp.phpH BWH!ݶ(vendor/twig/twig/lib/Twig/Node/Macro.php BW A2W/vendor/twig/twig/lib/Twig/Extension/Sandbox.phpY BWY /vendor/twig/twig/lib/Twig/Extension/Staging.php@ BW@Ḳ,1vendor/twig/twig/lib/Twig/Extension/Optimizer.php BWD-vendor/twig/twig/lib/Twig/Extension/Debug.php BW0vendor/twig/twig/lib/Twig/Extension/Profiler.php; BW;vA4vendor/twig/twig/lib/Twig/Extension/StringLoader.phpB BWB֪Kw,vendor/twig/twig/lib/Twig/Extension/Core.phpl BWlA6#/vendor/twig/twig/lib/Twig/Extension/Escaper.php BW ~j&vendor/twig/twig/lib/Twig/Template.phpO BWO+vendor/twig/twig/lib/Twig/TestInterface.php BW 7䈶7vendor/twig/twig/lib/Twig/FunctionCallableInterface.php BW޶&vendor/twig/twig/lib/Twig/Function.php BWf7vendor/twig/twig/lib/Twig/Util/DeprecationCollector.phpK BWKe6vendor/twig/twig/lib/Twig/Util/TemplateDirIterator.php BWo4}2vendor/twig/twig/lib/Twig/TokenParserInterface.php BWFw #vendor/twig/twig/lib/Twig/Error.phpu BWu18-vendor/twig/twig/lib/Twig/Filter/Function.php BW#5[+vendor/twig/twig/lib/Twig/Filter/Method.phpE BWE)vendor/twig/twig/lib/Twig/Filter/Node.php| BW| "-vendor/twig/twig/lib/Twig/LoaderInterface.phpU BWUd3vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php BWUV.vendor/twig/twig/lib/Twig/ExpressionParser.phpe BWe=#vendor/twig/twig/lib/Twig/Lexer.php{? BW{?G1vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.phpD BWD >b6vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php BWy+3vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.phpb# BWb#1vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php5 BW5Vg+vendor/twig/twig/lib/Twig/NodeTraverser.php= BW= [A8vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php BWkǶ*vendor/twig/twig/lib/Twig/SimpleFilter.php BW nA/vendor/twig/twig/lib/Twig/CompilerInterface.php BWp,vendor/twig/twig/lib/Twig/CacheInterface.phpo BWoQǃ-vendor/twig/twig/lib/Twig/ParserInterface.php BWQ }-vendor/twig/twig/lib/Twig/BaseNodeVisitor.php BW?Z$vendor/twig/twig/lib/Twig/Parser.php7/ BW7/wC,vendor/twig/twig/lib/Twig/SimpleFunction.php BW{(vendor/twig/twig/lib/Twig/Autoloader.php BW8kG'vendor/twig/twig/lib/Twig/Extension.phpT BWTjԑk)vendor/twig/twig/lib/Twig/Environment.php BW $vendor/twig/twig/lib/Twig/Filter.php BWN)vendor/twig/twig/lib/Twig/TokenStream.phpn BWnԩ=vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php0 BW0{/@vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php BW}Evendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php BW3˶Cvendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php BW 3vendor/twig/twig/lib/Twig/Sandbox/SecurityError.php BW=4vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php BW"vendor/twig/twig/lib/Twig/Node.php BW"a#vendor/twig/twig/lib/Twig/Token.php BWh׶1vendor/twig/twig/lib/Twig/NodeOutputInterface.php_ BW_ ';vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php BW$+/vendor/twig/twig/lib/Twig/FunctionInterface.php' BW'Rp-vendor/twig/twig/lib/Twig/FilterInterface.phpQ BWQew-l.vendor/twig/twig/lib/Twig/Cache/Filesystem.php^ BW^ (vendor/twig/twig/lib/Twig/Cache/Null.php BWD,vendor/twig/twig/lib/Twig/LexerInterface.php BW0W϶/vendor/twig/twig/lib/Twig/TokenParserBroker.php BW|j2vendor/twig/twig/lib/Twig/NodeVisitorInterface.php, BW,Y /vendor/twig/twig/lib/Twig/TemplateInterface.php BWT葶)vendor/twig/twig/lib/Twig/TokenParser.php BWLm˴(vendor/twig/twig/lib/Twig/SimpleTest.php BWiѩ/vendor/twig/twig/lib/Twig/Function/Function.php BW'-vendor/twig/twig/lib/Twig/Function/Method.phpm BWm²[+vendor/twig/twig/lib/Twig/Function/Node.php BW+vendor/twig/twig/lib/Twig/Loader/String.php BW2*vendor/twig/twig/lib/Twig/Loader/Array.phpU BWU tH*vendor/twig/twig/lib/Twig/Loader/Chain.php BW/vendor/twig/twig/lib/Twig/Loader/Filesystem.php6 BW6~$Ⱦ+vendor/twig/twig/lib/Twig/NodeInterface.php BWKh8vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php BW .˶8vendor/twig/twig/lib/Twig/Profiler/Node/LeaveProfile.php BWO]Z;vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php BW J2vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php BW2vendor/twig/twig/lib/Twig/Profiler/Dumper/Text.php BWb7vendor/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php BW/d.vendor/twig/twig/lib/Twig/Profiler/Profile.php\ BW\C<0vendor/twig/twig/lib/Twig/ExtensionInterface.php+ BW+7!Mvendor/zendframework/zend-servicemanager/src/ServiceLocatorAwareInterface.php BWvendor/zendframework/zend-stdlib/src/Hydrator/ClassMethods.phpD BWD6Gvendor/zendframework/zend-stdlib/src/Hydrator/HydratorPluginManager.php! BW!Q@vendor/zendframework/zend-stdlib/src/Hydrator/ObjectProperty.php? BW?Hvendor/zendframework/zend-stdlib/src/Hydrator/HydratorAwareInterface.php BWkeJvendor/zendframework/zend-stdlib/src/Hydrator/Strategy/ClosureStrategy.php BW =Ovendor/zendframework/zend-stdlib/src/Hydrator/Strategy/SerializableStrategy.php BW 1Jvendor/zendframework/zend-stdlib/src/Hydrator/Strategy/DefaultStrategy.php BW*Lvendor/zendframework/zend-stdlib/src/Hydrator/Strategy/StrategyInterface.phpE BWE%϶Jvendor/zendframework/zend-stdlib/src/Hydrator/HydratorOptionsInterface.php  BW *ƶJvendor/zendframework/zend-stdlib/src/Hydrator/StrategyEnabledInterface.phph BWh+CKvendor/zendframework/zend-stdlib/src/ArrayObject/PhpLegacyCompatibility.php BWzʫNvendor/zendframework/zend-stdlib/src/ArrayObject/PhpReferenceCompatibility.php& BW&򝄯9vendor/zendframework/zend-stdlib/src/SplPriorityQueue.phpa BWaH?vendor/zendframework/zend-stdlib/src/InitializableInterface.php BWc1ǡ6vendor/zendframework/zend-stdlib/src/PriorityQueue.php BW"[3vendor/zendframework/zend-stdlib/src/ArrayUtils.phpf BWf4$&8vendor/zendframework/zend-stdlib/src/AbstractOptions.php BWD -vendor/zendframework/zend-stdlib/src/Glob.php BWij>vendor/zendframework/zend-stdlib/src/DispatchableInterface.phpu BWu1vendor/zendframework/zend-stdlib/src/SplQueue.phpI BWI#J:vendor/zendframework/zend-stdlib/src/ResponseInterface.php BWj(Cvendor/zendframework/zend-stdlib/src/ArraySerializableInterface.php BWE0vendor/zendframework/zend-stdlib/src/Request.php BWCV9vendor/zendframework/zend-stdlib/src/RequestInterface.php BW=8vendor/zendframework/zend-stdlib/src/CallbackHandler.php BWq3vendor/zendframework/zend-stdlib/src/ArrayStack.phpW BWWRȉ<vendor/zendframework/zend-stdlib/src/ParametersInterface.php< BW<01vendor/zendframework/zend-stdlib/src/Response.php BW.0Ճ5vendor/zendframework/zend-stdlib/src/ErrorHandler.php# BW# t@4vendor/zendframework/zend-stdlib/src/ArrayObject.php BWP{3vendor/zendframework/zend-stdlib/src/Parameters.phpn BWn u4vendor/zendframework/zend-stdlib/src/StringUtils.phpL BWLV1vendor/zendframework/zend-stdlib/src/DateTime.php9 BW9xyжAvendor/zendframework/zend-stdlib/src/ParameterObjectInterface.php BWNvendor/zendframework/zend-stdlib/src/Exception/ExtensionNotLoadedException.php BW>:NEvendor/zendframework/zend-stdlib/src/Exception/ExceptionInterface.php BW <ŶKvendor/zendframework/zend-stdlib/src/Exception/InvalidArgumentException.php BW1kIAvendor/zendframework/zend-stdlib/src/Exception/LogicException.php BWfɶKvendor/zendframework/zend-stdlib/src/Exception/InvalidCallbackException.php BW9겶Cvendor/zendframework/zend-stdlib/src/Exception/RuntimeException.php BW땒 Ivendor/zendframework/zend-stdlib/src/Exception/BadMethodCallException.php BW[Bvendor/zendframework/zend-stdlib/src/Exception/DomainException.php BWͪ9vendor/zendframework/zend-stdlib/src/MessageInterface.php BWc0=vendor/zendframework/zend-stdlib/src/StringWrapper/Native.php BWo˶Lvendor/zendframework/zend-stdlib/src/StringWrapper/AbstractStringWrapper.php! BW!;s;vendor/zendframework/zend-stdlib/src/StringWrapper/Intl.php BWQ?vendor/zendframework/zend-stdlib/src/StringWrapper/MbString.php BW V[Mvendor/zendframework/zend-stdlib/src/StringWrapper/StringWrapperInterface.php BW a<vendor/zendframework/zend-stdlib/src/StringWrapper/Iconv.php BW>ȶ?vendor/zendframework/zend-stdlib/src/compatibility/autoload.php` BW`\ '0vendor/zendframework/zend-filter/src/Encrypt.phpU BWU m)T1vendor/zendframework/zend-filter/src/Callback.php BW hD<vendor/zendframework/zend-filter/src/Encrypt/BlockCipher.phpl BWlEMvendor/zendframework/zend-filter/src/Encrypt/EncryptionAlgorithmInterface.php BW1@8vendor/zendframework/zend-filter/src/Encrypt/Openssl.php0 BW0,؝7vendor/zendframework/zend-filter/src/AbstractFilter.php BW 5;<vendor/zendframework/zend-filter/src/FilterPluginManager.php BWn0vendor/zendframework/zend-filter/src/Decrypt.php BWnTA/vendor/zendframework/zend-filter/src/Digits.php BW2U4vendor/zendframework/zend-filter/src/FilterChain.phpY BWY?A3vendor/zendframework/zend-filter/src/StringTrim.php. BW. q,vendor/zendframework/zend-filter/src/Dir.phpi BWi~6vendor/zendframework/zend-filter/src/StringToUpper.php BWe-7:vendor/zendframework/zend-filter/src/DateTimeFormatter.phpG BWGZvCvendor/zendframework/zend-filter/src/Word/CamelCaseToUnderscore.php  BW ?,=vendor/zendframework/zend-filter/src/Word/DashToCamelCase.php BWuۭ'Bvendor/zendframework/zend-filter/src/Word/SeparatorToCamelCase.php BWa;^=vendor/zendframework/zend-filter/src/Word/SeparatorToDash.phpq BWq>E^Bvendor/zendframework/zend-filter/src/Word/CamelCaseToSeparator.phpU BWU`|n=vendor/zendframework/zend-filter/src/Word/DashToSeparator.phpc BWc7>vendor/zendframework/zend-filter/src/Word/DashToUnderscore.php BW$db?vendor/zendframework/zend-filter/src/Word/AbstractSeparator.php  BW ,=vendor/zendframework/zend-filter/src/Word/CamelCaseToDash.php BW^Bvendor/zendframework/zend-filter/src/Word/SeparatorToSeparator.php BW HKCvendor/zendframework/zend-filter/src/Word/UnderscoreToSeparator.phpy BWy`>vendor/zendframework/zend-filter/src/Word/UnderscoreToDash.php  BW FJCvendor/zendframework/zend-filter/src/Word/UnderscoreToCamelCase.php  BW X2vendor/zendframework/zend-filter/src/Inflector.phpj1 BWj1N'˶5vendor/zendframework/zend-filter/src/StaticFilter.php BWѶ5vendor/zendframework/zend-filter/src/HtmlEntities.php BW%à2vendor/zendframework/zend-filter/src/StripTags.php' BW'6¶1vendor/zendframework/zend-filter/src/BaseName.php BW35vendor/zendframework/zend-filter/src/File/Encrypt.php BW [5vendor/zendframework/zend-filter/src/File/Decrypt.php BW LĬ7vendor/zendframework/zend-filter/src/File/UpperCase.php9 BW9SͶ:vendor/zendframework/zend-filter/src/File/RenameUpload.phpz! BWz!bJa4vendor/zendframework/zend-filter/src/File/Rename.phpu% BWu%3>7vendor/zendframework/zend-filter/src/File/LowerCase.php( BW(X&5vendor/zendframework/zend-filter/src/UriNormalize.php BWhl-vendor/zendframework/zend-filter/src/Null.php_ BW_<6vendor/zendframework/zend-filter/src/StringToLower.php BWK6vendor/zendframework/zend-filter/src/StripNewlines.php BWǶζ8vendor/zendframework/zend-filter/src/AbstractUnicode.php BW.wI4vendor/zendframework/zend-filter/src/PregReplace.php BWd8Ovendor/zendframework/zend-filter/src/Compress/CompressionAlgorithmInterface.php BW𽽶5vendor/zendframework/zend-filter/src/Compress/Lzf.php8 BW8n8vendor/zendframework/zend-filter/src/Compress/Snappy.php BWvuBNvendor/zendframework/zend-filter/src/Compress/AbstractCompressionAlgorithm.php BWr5vendor/zendframework/zend-filter/src/Compress/Zip.php$ BW$Wȶ4vendor/zendframework/zend-filter/src/Compress/Gz.php BWF T5vendor/zendframework/zend-filter/src/Compress/Bz2.phpA BWAa5vendor/zendframework/zend-filter/src/Compress/Rar.php BWHͣ5vendor/zendframework/zend-filter/src/Compress/Tar.php BW}¶8vendor/zendframework/zend-filter/src/FilterInterface.phpR BWRwI1vendor/zendframework/zend-filter/src/Compress.php BWvendor/zendframework/zend-cache/src/Pattern/PatternOptions.phpC BWC"9?vendor/zendframework/zend-cache/src/Pattern/AbstractPattern.php BWuʶIvendor/zendframework/zend-cache/src/Storage/ClearByNamespaceInterface.php! BW!Nvendor/zendframework/zend-cache/src/Storage/AvailableSpaceCapableInterface.php BW=jꭶ9vendor/zendframework/zend-cache/src/Storage/PostEvent.php$ BW$=vendor/zendframework/zend-cache/src/Storage/PluginManager.php BW8}Avendor/zendframework/zend-cache/src/Storage/IteratorInterface.php BW؜Bvendor/zendframework/zend-cache/src/Storage/FlushableInterface.php BWԒFvendor/zendframework/zend-cache/src/Storage/ClearByPrefixInterface.php BW&<5vendor/zendframework/zend-cache/src/Storage/Event.php BW;Avendor/zendframework/zend-cache/src/Storage/IterableInterface.php BW@vendor/zendframework/zend-cache/src/Storage/StorageInterface.php  BW ζ<vendor/zendframework/zend-cache/src/Storage/Capabilities.php5 BW5n}Fvendor/zendframework/zend-cache/src/Storage/Plugin/PluginInterface.php BWr&Dvendor/zendframework/zend-cache/src/Storage/Plugin/PluginOptions.php@ BW@,HAvendor/zendframework/zend-cache/src/Storage/Plugin/Serializer.php BW W"Evendor/zendframework/zend-cache/src/Storage/Plugin/AbstractPlugin.php' BW'&hFvendor/zendframework/zend-cache/src/Storage/Plugin/IgnoreUserAbort.php BW BW> @vendor/zendframework/zend-cache/src/Storage/Adapter/WinCache.phpW@ BWW@#aKFvendor/zendframework/zend-cache/src/Storage/Adapter/ZendServerDisk.php BWv6Pvendor/zendframework/zend-cache/src/Storage/Adapter/MemcachedResourceManager.php-> BW->.kJvendor/zendframework/zend-cache/src/Storage/Adapter/AbstractZendServer.php BW }a>vendor/zendframework/zend-cache/src/Storage/Adapter/XCache.php; BW; UAvendor/zendframework/zend-cache/src/Storage/Adapter/Memcached.phpR BWRH ?vendor/zendframework/zend-cache/src/Storage/Adapter/Session.php9 BW9he;vendor/zendframework/zend-cache/src/Storage/Adapter/Apc.phpX BWXzw;vendor/zendframework/zend-cache/src/Storage/Adapter/Dba.php ; BW ;z~߶Dvendor/zendframework/zend-cache/src/Storage/Adapter/RedisOptions.php BW̘rFvendor/zendframework/zend-cache/src/Storage/Adapter/AdapterOptions.php BW#Di׶>vendor/zendframework/zend-cache/src/Storage/Adapter/Memory.phpN BWNXkBvendor/zendframework/zend-cache/src/Storage/Adapter/ApcOptions.php BW˄Hvendor/zendframework/zend-cache/src/Storage/Adapter/MemcachedOptions.php! BW!~ٶIvendor/zendframework/zend-cache/src/Storage/Adapter/FilesystemOptions.php, BW,uҶDvendor/zendframework/zend-cache/src/Storage/AdapterPluginManager.php BW'Evendor/zendframework/zend-cache/src/Storage/ClearExpiredInterface.php BWհжJvendor/zendframework/zend-cache/src/Storage/TotalSpaceCapableInterface.php BW]>vendor/zendframework/zend-cache/src/Storage/ExceptionEvent.php BWH{@Avendor/zendframework/zend-cache/src/Storage/TaggableInterface.php< BW<~Sa6vendor/zendframework/zend-cache/src/StorageFactory.php BW$Mvendor/zendframework/zend-cache/src/Exception/ExtensionNotLoadedException.php BWc愶Dvendor/zendframework/zend-cache/src/Exception/ExceptionInterface.phpx BWxC{KEvendor/zendframework/zend-cache/src/Exception/MissingKeyException.php BWDjLvendor/zendframework/zend-cache/src/Exception/MissingDependencyException.php BWF~Jvendor/zendframework/zend-cache/src/Exception/InvalidArgumentException.php BW|'6@vendor/zendframework/zend-cache/src/Exception/LogicException.php BWҶ Pvendor/zendframework/zend-cache/src/Exception/UnsupportedMethodCallException.php BWU̶Jvendor/zendframework/zend-cache/src/Exception/UnexpectedValueException.php BW2@Bvendor/zendframework/zend-cache/src/Exception/RuntimeException.php BWHvendor/zendframework/zend-cache/src/Exception/BadMethodCallException.php BW~'fEvendor/zendframework/zend-cache/src/Exception/OutOfSpaceException.php BW XDvendor/zendframework/zend-eventmanager/src/EventManagerInterface.php BWgAvendor/zendframework/zend-eventmanager/src/StaticEventManager.phpx BWxv=vendor/zendframework/zend-eventmanager/src/EventInterface.php BW\ضHvendor/zendframework/zend-eventmanager/src/AbstractListenerAggregate.phpM BWMJvendor/zendframework/zend-eventmanager/src/SharedEventManagerInterface.phpY BWY!:vendor/zendframework/zend-eventmanager/src/FilterChain.php BW ==vendor/zendframework/zend-eventmanager/src/ProvidesEvents.php BWV<Ovendor/zendframework/zend-eventmanager/src/SharedListenerAggregateInterface.php BW?tDvendor/zendframework/zend-eventmanager/src/Filter/FilterIterator.php BW IL?@Evendor/zendframework/zend-eventmanager/src/Filter/FilterInterface.phpp BWp=GEvendor/zendframework/zend-eventmanager/src/EventsCapableInterface.php BWՈ~p4vendor/zendframework/zend-eventmanager/src/Event.php BW%;vendor/zendframework/zend-eventmanager/src/EventManager.phpF BWFXAvendor/zendframework/zend-eventmanager/src/SharedEventManager.phph BWhEvendor/zendframework/zend-eventmanager/src/ListenerAggregateTrait.phpg BWgYAvendor/zendframework/zend-eventmanager/src/ResponseCollection.phpk BWkdzUOvendor/zendframework/zend-eventmanager/src/SharedEventManagerAwareInterface.php BW >Ivendor/zendframework/zend-eventmanager/src/ListenerAggregateInterface.php BWK~Ivendor/zendframework/zend-eventmanager/src/EventManagerAwareInterface.php BWEvendor/zendframework/zend-eventmanager/src/EventManagerAwareTrait.php BWYSAAvendor/zendframework/zend-eventmanager/src/GlobalEventManager.phpJ BWJ "ݶKvendor/zendframework/zend-eventmanager/src/Exception/ExceptionInterface.php BWŶQvendor/zendframework/zend-eventmanager/src/Exception/InvalidArgumentException.php BWQvendor/zendframework/zend-eventmanager/src/Exception/InvalidCallbackException.php BWWHvendor/zendframework/zend-eventmanager/src/Exception/DomainException.php BWuQvendor/zendframework/zend-eventmanager/src/SharedEventAggregateAwareInterface.php BWў/vendor/zendframework/zend-config/src/Config.php$ BW$7b`3vendor/zendframework/zend-config/src/Writer/Ini.phpM BWM eH4vendor/zendframework/zend-config/src/Writer/Json.php BW0:Ѷ?vendor/zendframework/zend-config/src/Writer/WriterInterface.php  BW 8s>vendor/zendframework/zend-config/src/Writer/AbstractWriter.php? BW? *i=4vendor/zendframework/zend-config/src/Writer/Yaml.phpa BWaA[`3vendor/zendframework/zend-config/src/Writer/Xml.php BW ]ٶ8vendor/zendframework/zend-config/src/Writer/PhpArray.php BWM=7<vendor/zendframework/zend-config/src/ReaderPluginManager.php BWK0vendor/zendframework/zend-config/src/Factory.phpp BWpB59Evendor/zendframework/zend-config/src/Processor/ProcessorInterface.php BW8vendor/zendframework/zend-config/src/Processor/Queue.php[ BW[-|;vendor/zendframework/zend-config/src/Processor/Constant.php` BW`?Ƕ9vendor/zendframework/zend-config/src/Processor/Filter.php BW:¶=vendor/zendframework/zend-config/src/Processor/Translator.phpI BWI x68vendor/zendframework/zend-config/src/Processor/Token.phpN BWN^ڡ<vendor/zendframework/zend-config/src/WriterPluginManager.phph BWhEvendor/zendframework/zend-config/src/Exception/ExceptionInterface.phpx BWx1Kvendor/zendframework/zend-config/src/Exception/InvalidArgumentException.php BW-e Cvendor/zendframework/zend-config/src/Exception/RuntimeException.php BWOĶ3vendor/zendframework/zend-config/src/Reader/Ini.php BWi-4vendor/zendframework/zend-config/src/Reader/Json.phpI BWI /(G?vendor/zendframework/zend-config/src/Reader/ReaderInterface.php BW$݆4vendor/zendframework/zend-config/src/Reader/Yaml.phpn BWn#jA3vendor/zendframework/zend-config/src/Reader/Xml.php BWTT3vendor/zendframework/zend-i18n/src/Filter/Alnum.php@ BW@ 挶3vendor/zendframework/zend-i18n/src/Filter/Alpha.php. BW.1n:vendor/zendframework/zend-i18n/src/Filter/NumberFormat.php BWa<vendor/zendframework/zend-i18n/src/Filter/AbstractLocale.phpT BWTFvendor/zendframework/zend-i18n/src/Translator/TranslatorAwareTrait.php BW #(Evendor/zendframework/zend-i18n/src/Translator/LoaderPluginManager.php! BW!?ntJvendor/zendframework/zend-i18n/src/Translator/TranslatorAwareInterface.php BW~HJvendor/zendframework/zend-i18n/src/Translator/TranslatorServiceFactory.php\ BW\eg<vendor/zendframework/zend-i18n/src/Translator/Translator.phpT BWTٹ?vendor/zendframework/zend-i18n/src/Translator/Plural/Parser.phpI% BWI%N4?vendor/zendframework/zend-i18n/src/Translator/Plural/Symbol.phpi BWi Ƕ=vendor/zendframework/zend-i18n/src/Translator/Plural/Rule.phpy BWy>c<vendor/zendframework/zend-i18n/src/Translator/TextDomain.php3 BW3ж<vendor/zendframework/zend-i18n/src/Translator/Loader/Ini.php BW >:@vendor/zendframework/zend-i18n/src/Translator/Loader/Gettext.php BW>`Lvendor/zendframework/zend-i18n/src/Translator/Loader/FileLoaderInterface.php BWd_Nvendor/zendframework/zend-i18n/src/Translator/Loader/RemoteLoaderInterface.php BWPˢ̶Avendor/zendframework/zend-i18n/src/Translator/Loader/PhpArray.php BWpǶ8vendor/zendframework/zend-i18n/src/View/HelperConfig.php BW}ʶ<vendor/zendframework/zend-i18n/src/View/Helper/Translate.php_ BW_k?vendor/zendframework/zend-i18n/src/View/Helper/NumberFormat.php BW*Avendor/zendframework/zend-i18n/src/View/Helper/CurrencyFormat.php9 BW9WeBvendor/zendframework/zend-i18n/src/View/Helper/TranslatePlural.php  BW ~֏)9vendor/zendframework/zend-i18n/src/View/Helper/Plural.php| BW| W=vendor/zendframework/zend-i18n/src/View/Helper/DateFormat.php BWSKvendor/zendframework/zend-i18n/src/View/Helper/AbstractTranslatorHelper.php BW 0Lvendor/zendframework/zend-i18n/src/Exception/ExtensionNotLoadedException.php BWX>Cvendor/zendframework/zend-i18n/src/Exception/ExceptionInterface.phpv BWvn=eIvendor/zendframework/zend-i18n/src/Exception/InvalidArgumentException.php BWZ3w?vendor/zendframework/zend-i18n/src/Exception/ParseException.php BWZN ?vendor/zendframework/zend-i18n/src/Exception/RangeException.php BWJAvendor/zendframework/zend-i18n/src/Exception/RuntimeException.php BWk]Evendor/zendframework/zend-i18n/src/Exception/OutOfBoundsException.php BW y6vendor/zendframework/zend-i18n/src/Validator/Float.php5 BW5f51۶6vendor/zendframework/zend-i18n/src/Validator/Alnum.php BW yQ6vendor/zendframework/zend-i18n/src/Validator/Alpha.php5 BW5mڐ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AI.php? BW?l֋S?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/RS.phpL BWL?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/DZ.php BWж?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GW.php BWw8L?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NE.php BW4.?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TZ.phpj BWjS?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GL.php< BW<#!W?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LV.phpE BWE.^?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GA.php BW8v?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/ME.php BWi5?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TJ.php< BW<Ҷ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LB.php BWז5p?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PG.php BWPl?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TH.php BW3U?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LU.phpu BWu=3?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/HN.php BWE@a?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KG.php; BW;GW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/UY.php BW3?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/IO.phpj BWjQ}R?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GR.php BW7am?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TV.php BWqf?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TN.php BW.;!?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/VC.php BWK*?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CK.php BW[E?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/RU.php BW#?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/IL.phpB BWB?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/EH.phpO BWO6%x?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SE.php BWS?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/IM.php BWߐ*?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/UA.php BW*?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MP.php BW_V?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LI.php BWQ8?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/DK.phpG BWG咰?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/FJ.php2 BW20F?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PA.php BW ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KP.php BW M?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AG.php BWyvr5?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MQ.php BWk?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MX.php  BW ]%?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KM.php BWcX?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SJ.php BWѶ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MM.php BW5?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/QA.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NP.php BW}%?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KI.phpV BWV^?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TO.php BW}?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CC.php BW\vO?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CM.php" BW"w!?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GE.php BW](?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NL.php BW[B>?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LA.phpT BWT?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MA.php BWc=?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GG.php_ BW_^?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PR.php BWZ骶?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/FM.php BW6?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TD.php BWѫQ۶?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/HT.php BWX+?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LC.php BWb?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PH.php BWyX?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CA.php BW$?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KR.php BWJ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/IS.phpY BWY:ڶ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/ZA.php BW b*?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/JO.php) BW)c<?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/UZ.php BW\Q?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AL.php BWا?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BT.phpD BWD?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KE.php BWPX@2?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BD.php BW hƶ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SN.php9 BW99?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NF.php BW7$?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SD.php BWྲྀ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MT.php BWh-k\?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KW.php BWi?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CO.php BW4(?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MN.php BWV?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BL.php BWSSɶ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PL.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LK.php$ BW$~?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GQ.php  BW wI\?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/JP.phpv BWv)r?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/ID.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NC.php BW0B?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NO.php BW\q?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BW.phpx BWxNz?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/ZM.php BWL-N?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BZ.php BWnԶ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/VN.php BW`o?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SS.phpy BWyヶ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MO.php BW '?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NU.php BWߨ\?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CR.php BW3?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BB.php; BW;\9?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MV.phpo BWo?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SC.php BWu?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/YE.phpZ BWZde?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BY.php BWu1?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BF.phpI BWIsR??vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AD.php BW ն?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MK.php BWpVE?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MY.php BW Z?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AR.php BWZ5?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/FR.php BW~?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/OM.php BWm?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AZ.php BWN}?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KZ.phpL BWL?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GN.phpu BWu ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NZ.php BWJS;̶?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AU.php BWXD¶?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BO.php BWtm?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/ET.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/DO.phpO BWO5m?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/UG.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PW.php BW F?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MD.php BWYٶ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/WF.php BW؍Ŷ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KY.php BWKö?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/HU.phpI BWIRm?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/IE.phpe BWe^?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PE.php BW`&ж?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CD.php BWYL?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SK.php BWY?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BQ.php BWWE?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CI.php? BW???vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BE.phpi BWi~?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CY.php BWοE?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/VI.php BWJ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TW.php BWdg?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/FI.php BWL˶?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BI.php BW%?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MZ.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MU.php BW! O?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GI.php BW;?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CL.phpe BWed?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GY.php BWRs>?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AF.php  BW [P?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MC.php\ BW\:˥?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PM.php BW;?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MS.php$ BW$j?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SB.php BW^0?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/ZW.php BW6?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/IT.php BWFz9?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GM.php< BW<|^?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CU.php BW)/?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/EE.php BWIQ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AT.php$ BW$P?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SL.php BW=c?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/JM.php6 BW6XkP?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MG.php? BW?=/?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SO.php BWLr?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/YT.php BWP?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/DJ.php BW{b?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/HK.php BWNg{?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TC.php BW.a?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TG.php BW J?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GF.php BWuֶ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NR.php% BW%Wh?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GH.php  BW ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LR.php BW]̶?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BA.phpz BWze?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TL.php BW .?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AE.phpz BWz/?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CZ.php BWny?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AC.php BWo?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AM.php BW~?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SG.php BW+s?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/DE.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CH.php BW_?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SI.phpm BWm?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TR.php  BW @Dƶ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LS.php BW x?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/RW.php BWl'?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MF.php BWC|?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AX.php BWo?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MR.phpH BWHR猶?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BM.php` BW`zж?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KN.phpc BWc ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/VA.php BWB/?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/WS.php BW#?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/ER.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/VU.php BWB?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SX.phpN BWN5a?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CX.php BWѯ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SR.php BWDQ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/US.phpK BWK2?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/VE.php BW4pޛ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PF.php BW+"?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SV.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/FK.php BWA?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CG.php BWO?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/EC.php BWZͮ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GU.php BW~d?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/ST.php BWT=R?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MW.php- BW-8$?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/MH.php BW`c?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LT.php BWt?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CW.php BW"7?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BS.php BW ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/VG.php BW;)?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PK.php BWU?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GT.phpB BWBʦ#z?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/JE.php BWb$?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BJ.php* BW*H<?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TK.phpp BWp?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GB.php BW ^1tW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/KH.php BWȻ㑶?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TT.php BW$;?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BR.phpp BWpl@?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PS.php BWɠ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GP.php4 BW4?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SA.phpy BWy/B?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AW.php BWmH?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AO.php BWw?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NI.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/DM.phpr BWr\"X?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/RE.php BWR‡?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/IN.phpv BWv Ŷ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BG.php BW'`|?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/FO.php BW;!?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CV.php BWvK M?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SZ.php] BW]F?Y?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CN.phpC BWCc⺶?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SM.php BW:H?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/IQ.php BW\>?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/LY.php  BW IK^?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/HR.php BW2i?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SH.php> BW>p̶?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NG.php  BW 8?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/TM.php, BW,?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/AS.php- BW-kN?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BN.php BWz?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/ES.php BWʉ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/RO.php BWMLܶ?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/GD.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/IR.php BW:?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/BH.php BW?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/NA.phpA BWA'/=?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/EG.php BWc⁹?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PT.phpO BWOQX"?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/PY.php BWWV?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/ML.php: BW:UGT?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/SY.phpQ BWQkWն?vendor/zendframework/zend-i18n/src/Validator/PhoneNumber/CF.php BWCYض9vendor/zendframework/zend-i18n/src/Validator/PostCode.php$, BW$,v_S9vendor/zendframework/zend-i18n/src/Validator/DateTime.phpE BWE}}+vendor/zendframework/zend-math/src/Rand.php BWսCvendor/zendframework/zend-math/src/Exception/ExceptionInterface.phpv BWv7Ivendor/zendframework/zend-math/src/Exception/InvalidArgumentException.php BW`DAvendor/zendframework/zend-math/src/Exception/RuntimeException.php BWc}϶@vendor/zendframework/zend-math/src/Exception/DomainException.php BW$q8vendor/zendframework/zend-math/src/Source/HashTiming.phpv BWvê+vendor/zetacomponents/base/src/features.php. BW.''vendor/zetacomponents/base/src/init.phpV BWVko*vendor/zetacomponents/base/src/options.php BWy*Ll)vendor/zetacomponents/base/src/struct.php? BW?tAvendor/zetacomponents/base/src/exceptions/extension_not_found.php6 BW6~9 Ivendor/zetacomponents/base/src/exceptions/functionality_not_supported.php> BW> V&J7vendor/zetacomponents/base/src/exceptions/exception.php BWCTs;vendor/zetacomponents/base/src/exceptions/setting_value.php[ BW[?vendor/zetacomponents/base/src/exceptions/setting_not_found.phpT BWTH[YFvendor/zetacomponents/base/src/exceptions/init_callback_configured.php BW: Lvendor/zetacomponents/base/src/exceptions/double_class_repository_prefix.phpV BWVw5vendor/zetacomponents/base/src/exceptions/file_io.php BWO;3vendor/zetacomponents/base/src/exceptions/value.php BW.Ѷ6vendor/zetacomponents/base/src/exceptions/whatever.php  BW 8K6vendor/zetacomponents/base/src/exceptions/autoload.phpw BWw7}X=vendor/zetacomponents/base/src/exceptions/file_permission.php BW Dg7<vendor/zetacomponents/base/src/exceptions/file_not_found.phpJ BWJT]DXDvendor/zetacomponents/base/src/exceptions/invalid_callback_class.php_ BW_ Z»Avendor/zetacomponents/base/src/exceptions/property_permission.phpf BWf>D@vendor/zetacomponents/base/src/exceptions/property_not_found.php BW"yABvendor/zetacomponents/base/src/exceptions/invalid_parent_class.phpE BWE<vendor/zetacomponents/base/src/exceptions/file_exception.php- BW-'vendor/zetacomponents/base/src/file.php_H BW_H ^3vendor/zetacomponents/base/src/metadata/tarball.php BW g^0vendor/zetacomponents/base/src/metadata/pear.php BW<+vendor/zetacomponents/base/src/metadata.php BWb0vendor/zetacomponents/base/src/ezc_bootstrap.php| BW|Mɶ<vendor/zetacomponents/base/src/structs/file_find_context.php BW -њ?vendor/zetacomponents/base/src/structs/repository_directory.php BW 8'U3vendor/zetacomponents/base/src/options/autoload.php BW %ݶ0vendor/zetacomponents/base/src/base_autoload.phpN BWN¬Gvendor/zetacomponents/base/src/interfaces/configuration_initializer.php BWE9vendor/zetacomponents/base/src/interfaces/persistable.php BWJ 8vendor/zetacomponents/base/src/interfaces/exportable.php BW5'vendor/zetacomponents/base/src/base.phpY BWY\>vendor/zetacomponents/document/src/dom_elements/locateable.php BW KzFvendor/zetacomponents/document/src/dom_elements/property_container.phpE BWE F2vendor/zetacomponents/document/src/pcss/parser.phpu5 BWu5˿<vendor/zetacomponents/document/src/pcss/style_inferencer.php@ BW@Jj>vendor/zetacomponents/document/src/pcss/style/string_value.phpE BWE쓐>vendor/zetacomponents/document/src/pcss/style/border_value.php BWX&;vendor/zetacomponents/document/src/pcss/style/src_value.phpm BWm %*<vendor/zetacomponents/document/src/pcss/style/line_value.php BW e%@vendor/zetacomponents/document/src/pcss/style/line_box_value.php BW 8Cvendor/zetacomponents/document/src/pcss/style/measure_box_value.php BW#I^Avendor/zetacomponents/document/src/pcss/style/color_box_value.php BWD7vendor/zetacomponents/document/src/pcss/style/value.php0 BW0 /<ն<vendor/zetacomponents/document/src/pcss/style/list_value.php{ BW{@=;vendor/zetacomponents/document/src/pcss/style/int_value.php@ BW@29vendor/zetacomponents/document/src/pcss/style/default.php& BW&X=vendor/zetacomponents/document/src/pcss/style/color_value.php BWxRf?vendor/zetacomponents/document/src/pcss/style/measure_value.php BWⅶBvendor/zetacomponents/document/src/pcss/style/border_box_value.php BWSil;vendor/zetacomponents/document/src/pcss/style/box_value.php  BW RB5vendor/zetacomponents/document/src/pcss/directive.php BW <vendor/zetacomponents/document/src/pcss/layout_directive.phpV BWVٶ3vendor/zetacomponents/document/src/pcss/measure.php BWvAvendor/zetacomponents/document/src/pcss/declaration_directive.php= BW=4噶Avendor/zetacomponents/document/src/converters/element_visitor.php- BW-Ng=6vendor/zetacomponents/document/src/converters/xslt.php BWUIvendor/zetacomponents/document/src/converters/element_visitor_handler.php| BW|tCvendor/zetacomponents/document/src/converters/xslt/docbook_html.php BW+*Uvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/handler.php BW [_vendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/special_paragraph.phpn BWn 03[vendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/internal_link.phpb BWb ;QZvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/ordered_list.php BW cUvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/literal.php BWrVvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/footnote.php BWktǶ\vendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/literal_layout.php[ BW[ [H[vendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/variable_list.phpR BWR Vvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/emphasis.php BWUgUvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/section.php BWQܶRvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/head.php BW Xvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/begin_page.php BWh۶_vendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/inlinemediaobject.php BWC)Svendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/table.php BW.%0[Uvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/recurse.php BWOoWvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/paragraph.php BW ꀗ[vendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/itemized_list.php2 BW2 <[vendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/external_link.php  BW Yvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/mediaobject.phph BWhGUvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/comment.php BW=|Xvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/blockquote.php BW a׶Tvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/ignore.php BWVvendor/zetacomponents/document/src/converters/element_visitor/docbook/rst/citation.php BW^Vvendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/handler.php& BW& C0-\vendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/internal_link.phpH BWHNg|[vendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/ordered_list.php BW dVvendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/literal.php BW؄]vendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/literal_layout.php< BW< 'Wvendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/emphasis.php BWӶVvendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/section.php BW rƶYvendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/begin_page.php BW``vendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/inlinemediaobject.phpp BWp'Tvendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/table.php BW -EVvendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/recurse.php BWaJiXvendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/paragraph.php BW6\vendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/itemized_list.php BW \vendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/external_link.php  BW /LVZvendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/mediaobject.php BWoiUvendor/zetacomponents/document/src/converters/element_visitor/docbook/wiki/ignore.phpc BWcpŶWvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/handler.phpc BWc墶avendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/special_paragraph.php BW # Vvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/mapper.php\ BW\ [\evendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/definition_list_entry.php BW []vendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/internal_link.php BWsg:Xvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/footnote.php BW_˶^vendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/literal_layout.php BW ےtXvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/emphasis.phpg BWgWvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/section.php BW zZvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/table_cell.php BWD>;Tvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/head.phpz BWz JVvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/anchor.php BW90^Yvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/paragraph.php BW;`]vendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/external_link.phpt BWtFÏ[vendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/mediaobject.php BW VWvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/comment.php BWgߏAZvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/blockquote.php BW ]tVvendor/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/ignore.php BWn;Q_vendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/style_information.php BWkvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter_manager.php BWmvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/font_size.php BWߌٶivendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/color.php BWEsvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/text_decoration.php BWc jvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/margin.php BW˵okvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/default.php BWnxmvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/font_name.php BWHZ;jvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/border.php BW/:hvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/font.php BWtfvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/preprocessor.php BW %`cvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter.phpb BWbۢ5ivendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter_tools.php BW3!Vlvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator.php BW ۷Acvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator.php BW 4Skvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/preprocessor/list.php> BW>pvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/preprocessor/paragraph.phpv BWv kvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/preprocessor/font.php9 BW9lqvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/list.phpE BWEaoqvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/text.php BW kvvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/table_row.phpX BWX 1u;wvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/table_cell.php BW WKѶrvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/table.php BW ?˽vvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/paragraph.phpH BWH ;6ʊhvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/list.php. BW..V|hvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/text.php BW m5Q$mvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/table_row.php BW Y K/nvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/table_cell.php BW>ivendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/table.php BW pwǶmvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/paragraph.php BWfݶYvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss.php# BW#)ѭͶ\vendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/meta_generator.php BW *xTvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler.php BW 9[vendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/image_locator.php: BW: vfvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/handler.php BW@ cvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/list.php2 BW2.evendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/mapper.phpr BWr 4wHdvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/ulink.php BWLb gvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/footnote.phpm BWm 9͗}mvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/literal_layout.php BWyöfvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/section.php BW5Զevendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/anchor.php BW  dvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/table.php BWlkvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/media_object.phpz BWzSR5hvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/paragraph.php BW~.Dcvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/link.php3 BW3>ܶfvendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/comment.php BW4ʶivendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/page_break.php BWGevendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/ignore.php BW ~evendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/inline.php BWO)5\vendor/zetacomponents/document/src/converters/element_visitor/docbook/odt/text_processor.php BWUvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/title.php~ BW~}0"Vvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/mapper.php1 BW1 _"@s]vendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/internal_link.php BW \vendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/ordered_list.php BWiXvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/footnote.php BWs}^vendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/literal_layout.php+ BW+ ƋCXvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/emphasis.phpn BWnXݟWvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/section.phpj BWj^Zvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/table_cell.phpG BWGVvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/anchor.php BW(Uvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/table.phpQ BWQ\4Wvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/recurse.php BWYvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/paragraph.php BW`]vendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/itemized_list.php BW65]vendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/external_link.php BWUWvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/comment.php BWsVvendor/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/ignore.phpa BWas?ҶOvendor/zetacomponents/document/src/converters/element_visitor/docbook_ezxml.php" BW"9)oӶMvendor/zetacomponents/document/src/converters/element_visitor/docbook_rst.phpZ/ BWZ/Mvendor/zetacomponents/document/src/converters/element_visitor/docbook_odt.php' BW'TQNvendor/zetacomponents/document/src/converters/element_visitor/docbook_html.php+ BW+;LOvendor/zetacomponents/document/src/converters/element_visitor/ezxml_docbook.phpM BWM.ӶNvendor/zetacomponents/document/src/converters/element_visitor/docbook_wiki.php BWZ?Tvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/list.php BW VVvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/mapper.php1 BW1 BWvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/literal.php BW f Yvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/table_row.php BW g6Xvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/emphasis.php  BW Zvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/table_cell.php BWWVvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/anchor.phpt BWtOTvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/line.php BW 0\^Uvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/table.php~ BW~ꯘVvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/header.php BWF3tTvendor/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/link.php BW vendor/zetacomponents/document/src/document/pdf/hyphenator.php BWH CFvendor/zetacomponents/document/src/document/pdf/hyphenator/default.php BWJ8vendor/zetacomponents/document/src/document/pdf/page.phpR BWRZAvendor/zetacomponents/document/src/document/pdf/image/handler.php BWگ`=vendor/zetacomponents/document/src/document/pdf/image/php.phps BWs #pHvendor/zetacomponents/document/src/document/pdf/item_generator/alpha.php BWdEvendor/zetacomponents/document/src/document/pdf/item_generator/no.php< BW<gIIvendor/zetacomponents/document/src/document/pdf/item_generator/bullet.php BW]@Ivendor/zetacomponents/document/src/document/pdf/item_generator/number.phps BWs`Hvendor/zetacomponents/document/src/document/pdf/item_generator/roman.php BW F圿Hvendor/zetacomponents/document/src/document/pdf/item_generator/alnum.php BW L9vendor/zetacomponents/document/src/document/pdf/image.phpU BWUUVEvendor/zetacomponents/document/src/document/pdf/tokenizer/literal.php BW =YEvendor/zetacomponents/document/src/document/pdf/tokenizer/default.php BW .=vendor/zetacomponents/document/src/document/pdf/tokenizer.php BW  Ӷ8vendor/zetacomponents/document/src/document/pdf/part.php BWaE<vendor/zetacomponents/document/src/document/pdf/renderer.php* BW*w:vendor/zetacomponents/document/src/document/pdf/driver.php{& BW{&b϶?vendor/zetacomponents/document/src/document/pdf/part/footer.php BWO?vendor/zetacomponents/document/src/document/pdf/part/header.php BW*wBvendor/zetacomponents/document/src/document/pdf/renderer/title.phpJ BWJ8>Avendor/zetacomponents/document/src/document/pdf/renderer/list.php BW?O4Evendor/zetacomponents/document/src/document/pdf/renderer/text_box.php1` BW1`eqFvendor/zetacomponents/document/src/document/pdf/renderer/list_item.phpD BWD 9ֶBvendor/zetacomponents/document/src/document/pdf/renderer/table.php@ BW@\Bvendor/zetacomponents/document/src/document/pdf/renderer/block.php BW?Fvendor/zetacomponents/document/src/document/pdf/renderer/paragraph.php BW3>{Jvendor/zetacomponents/document/src/document/pdf/renderer/literal_block.php BWtA%SAvendor/zetacomponents/document/src/document/pdf/renderer/main.php< BW<?Hvendor/zetacomponents/document/src/document/pdf/renderer/mediaobject.php BW˘%Gvendor/zetacomponents/document/src/document/pdf/renderer/text_block.php BWD*Gvendor/zetacomponents/document/src/document/pdf/renderer/blockquote.phpk BWk g7vendor/zetacomponents/document/src/document/pdf/box.php BW5Bvendor/zetacomponents/document/src/document/pdf/item_generator.php BWEWhQvendor/zetacomponents/document/src/document/pdf/table_column_width_calculator.php BWlԿBvendor/zetacomponents/document/src/document/pdf/driver/wrapper.phpjE BWjE 0Hvendor/zetacomponents/document/src/document/pdf/driver/wrapper_state.php( BW(3#v?vendor/zetacomponents/document/src/document/pdf/driver/haru.phpo BWoƶ>vendor/zetacomponents/document/src/document/pdf/driver/svg.phpG BWGVl@vendor/zetacomponents/document/src/document/pdf/driver/tcpdf.phpV BWVZjYvendor/zetacomponents/document/src/document/pdf/default_table_column_width_calculator.phpT BWTdy_4vendor/zetacomponents/document/src/document/wiki.phpC+ BWC+﫜N3vendor/zetacomponents/document/src/document/rst.php; BW;PZƶ:vendor/zetacomponents/document/src/document/rst/parser.php BWoɶ=vendor/zetacomponents/document/src/document/rst/tokenizer.php BW88vendor/zetacomponents/document/src/document/rst/role.phpT BWT y)Dvendor/zetacomponents/document/src/document/rst/directive/danger.php BW b@DBvendor/zetacomponents/document/src/document/rst/directive/note.php BWZCvendor/zetacomponents/document/src/document/rst/directive/image.php BW Gvendor/zetacomponents/document/src/document/rst/directive/attention.php BW s{|Dvendor/zetacomponents/document/src/document/rst/directive/figure.php> BW> IFvendor/zetacomponents/document/src/document/rst/directive/contents.phpk BWktEvendor/zetacomponents/document/src/document/rst/directive/warning.php BW lDvendor/zetacomponents/document/src/document/rst/directive/notice.php BWYhжEvendor/zetacomponents/document/src/document/rst/directive/include.php BWʶ;vendor/zetacomponents/document/src/document/rst/visitor.php] BW]B)Bvendor/zetacomponents/document/src/document/rst/document_stack.phpT BWTA9vendor/zetacomponents/document/src/document/rst/token.php" BW"Ѷ=vendor/zetacomponents/document/src/document/rst/directive.php- BW-PtҶCvendor/zetacomponents/document/src/document/rst/visitor/docbook.phpwX BWwXFvendor/zetacomponents/document/src/document/rst/visitor/xhtml_body.php BWaWAvendor/zetacomponents/document/src/document/rst/visitor/xhtml.phpdk BWdk@A8vendor/zetacomponents/document/src/document/rst/node.phps& BWs& =@vendor/zetacomponents/document/src/document/rst/role/literal.php1 BW1 \Hvendor/zetacomponents/document/src/document/rst/role/title_reference.php; BW; }Dvendor/zetacomponents/document/src/document/rst/role/superscript.phpX BWX{~Avendor/zetacomponents/document/src/document/rst/role/emphasis.php9 BW9Q?vendor/zetacomponents/document/src/document/rst/role/strong.php^ BW^|oQBvendor/zetacomponents/document/src/document/rst/role/subscript.phpD BWDBvendor/zetacomponents/document/src/document/rst/nodes/document.php~ BW~P_<Ovendor/zetacomponents/document/src/document/rst/nodes/markup_inline_literal.php< BW<2ՖjPvendor/zetacomponents/document/src/document/rst/nodes/markup_strong_emphasis.php BWf?vendor/zetacomponents/document/src/document/rst/nodes/title.php BWSP/Dvendor/zetacomponents/document/src/document/rst/nodes/table_body.phpg BWg@vendor/zetacomponents/document/src/document/rst/nodes/markup.phpD BWD%Z5Ivendor/zetacomponents/document/src/document/rst/nodes/named_reference.phpb BWb2Nvendor/zetacomponents/document/src/document/rst/nodes/definition_list_list.php BW.Avendor/zetacomponents/document/src/document/rst/nodes/literal.php BW^Bvendor/zetacomponents/document/src/document/rst/nodes/footnote.php= BW= f'Cvendor/zetacomponents/document/src/document/rst/nodes/table_row.phpb BWb^޶Ivendor/zetacomponents/document/src/document/rst/nodes/line_block_line.php BW Ivendor/zetacomponents/document/src/document/rst/nodes/definition_list.php BW,Avendor/zetacomponents/document/src/document/rst/nodes/section.php BW GJDvendor/zetacomponents/document/src/document/rst/nodes/table_cell.phpC BWC Ovendor/zetacomponents/document/src/document/rst/nodes/blockquote_annotation.php BW@vendor/zetacomponents/document/src/document/rst/nodes/target.php BW;FDvendor/zetacomponents/document/src/document/rst/nodes/line_block.php BWŅDvendor/zetacomponents/document/src/document/rst/nodes/field_list.php BW bSHvendor/zetacomponents/document/src/document/rst/nodes/anon_reference.php BW2-Cvendor/zetacomponents/document/src/document/rst/nodes/text_line.php BWKCvendor/zetacomponents/document/src/document/rst/nodes/reference.phpJ BWJ jJvendor/zetacomponents/document/src/document/rst/nodes/bullet_list_list.php BW1?vendor/zetacomponents/document/src/document/rst/nodes/table.php BWzCvendor/zetacomponents/document/src/document/rst/nodes/directive.php BW Ivendor/zetacomponents/document/src/document/rst/nodes/enumerated_list.phpV BWV mMvendor/zetacomponents/document/src/document/rst/nodes/markup_substitution.php BWDvendor/zetacomponents/document/src/document/rst/nodes/table_head.phpg BWg_)zHvendor/zetacomponents/document/src/document/rst/nodes/link_reference.phpb BWb Qvendor/zetacomponents/document/src/document/rst/nodes/markup_interpreted_text.php1 BW1 8Ivendor/zetacomponents/document/src/document/rst/nodes/markup_emphasis.php BW]?vendor/zetacomponents/document/src/document/rst/nodes/block.php BWtCvendor/zetacomponents/document/src/document/rst/nodes/paragraph.php BWn5Gvendor/zetacomponents/document/src/document/rst/nodes/literal_block.php BWͶ>vendor/zetacomponents/document/src/document/rst/nodes/link.php BWmHHvendor/zetacomponents/document/src/document/rst/nodes/link_anonymous.phpR BWREvendor/zetacomponents/document/src/document/rst/nodes/bullet_list.php BWc)Dvendor/zetacomponents/document/src/document/rst/nodes/blockquote.php BW ,V#Nvendor/zetacomponents/document/src/document/rst/nodes/enumerated_list_list.php BW(ӦDvendor/zetacomponents/document/src/document/rst/nodes/transition.php BWFvendor/zetacomponents/document/src/document/rst/nodes/substitution.php; BW;3vendor/zetacomponents/document/src/document/pdf.php BWcYж9vendor/zetacomponents/document/src/document/xml/ezxml.php BWr;vendor/zetacomponents/document/src/document/xml/docbook.php BW`ݷZvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/special_paragraph.php BW :,Mvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/text.phpo BWow7Rvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/tablecell.php BW ZNvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/image.php BWWkjSvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/enumerated.phpl BWl ԶPvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/literal.php BWuSRvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/lineblock.php( BW( בQvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/footnote.php BW)ԶNvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/table.php3 BW3Wvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/definitionlist.php BW bOvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/strong.phpe BWeGOvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/header.phpb BWbDPvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/mapping.php BW R.Rvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/paragraph.phpo BWo D)Mvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/link.php BW R[ Svendor/zetacomponents/document/src/document/xml/xhtml/filter/element/blockquote.phpZ BWZ Mvendor/zetacomponents/document/src/document/xml/xhtml/filter/element/base.phpo BWo#Ivendor/zetacomponents/document/src/document/xml/xhtml/filter/metadata.php BWqTȩPvendor/zetacomponents/document/src/document/xml/xhtml/filter/content_locator.php BWE9ضFvendor/zetacomponents/document/src/document/xml/xhtml/filter/xpath.php BW ץHvendor/zetacomponents/document/src/document/xml/xhtml/filter/element.php BW*œEvendor/zetacomponents/document/src/document/xml/xhtml/filter/base.php+ BW+zCGvendor/zetacomponents/document/src/document/xml/xhtml/filter/tables.php BW畕Q7vendor/zetacomponents/document/src/document/xml/odt.phpr/ BWr/)tDvendor/zetacomponents/document/src/document/xml/odt/style/parser.phpU BWU4Gvendor/zetacomponents/document/src/document/xml/odt/style/extractor.php BW 2<Hvendor/zetacomponents/document/src/document/xml/odt/style/inferencer.php BWyBvendor/zetacomponents/document/src/document/xml/odt/list_style.php BW tIOvendor/zetacomponents/document/src/document/xml/odt/list_level_style/bullet.php BW e/C3Ovendor/zetacomponents/document/src/document/xml/odt/list_level_style/number.phpN BWNFRWHvendor/zetacomponents/document/src/document/xml/odt/list_level_style.php? BW? FoDvendor/zetacomponents/document/src/document/xml/odt/filter/image.php BW NKvendor/zetacomponents/document/src/document/xml/odt/filter/element/list.php BWLvendor/zetacomponents/document/src/document/xml/odt/filter/element/frame.phpp BWpn3Lvendor/zetacomponents/document/src/document/xml/odt/filter/element/image.phpm BWmsKԊOvendor/zetacomponents/document/src/document/xml/odt/filter/element/footnote.php BW n7 Qvendor/zetacomponents/document/src/document/xml/odt/filter/element/html_table.php BW幅Lvendor/zetacomponents/document/src/document/xml/odt/filter/element/table.php3 BW34OIMvendor/zetacomponents/document/src/document/xml/odt/filter/element/header.phpn BWn \a:Pvendor/zetacomponents/document/src/document/xml/odt/filter/element/paragraph.php BW qKvendor/zetacomponents/document/src/document/xml/odt/filter/element/link.php BWq7IQvendor/zetacomponents/document/src/document/xml/odt/filter/element/whitespace.php BW tEKvendor/zetacomponents/document/src/document/xml/odt/filter/element/base.php BW=eIvendor/zetacomponents/document/src/document/xml/odt/filter/style/rule.php BW`3Tvendor/zetacomponents/document/src/document/xml/odt/filter/style/rule/list_level.php BW@`Rvendor/zetacomponents/document/src/document/xml/odt/filter/style/rule/emphasis.phpP BWP OFvendor/zetacomponents/document/src/document/xml/odt/filter/element.phpS BWSaCvendor/zetacomponents/document/src/document/xml/odt/filter/base.php0 BW04q!Dvendor/zetacomponents/document/src/document/xml/odt/filter/style.php BW Vvendor/zetacomponents/document/src/document/xml/odt/formatting/property_collection.php BW TEMvendor/zetacomponents/document/src/document/xml/odt/formatting/properties.php BW"_=vendor/zetacomponents/document/src/document/xml/odt/style.phpJ BWJQxMvendor/zetacomponents/document/src/document/xml/ezxml/dummy_link_provider.php BWȶNvendor/zetacomponents/document/src/document/xml/ezxml/dummy_link_converter.php= BW=(49vendor/zetacomponents/document/src/document/xml/xhtml.php4 BW48vendor/zetacomponents/document/src/document/xml_base.php BWAKն;vendor/zetacomponents/document/src/document/wiki/parser.php BWpw;vendor/zetacomponents/document/src/document/wiki/plugin.php BW y:@vendor/zetacomponents/document/src/document/wiki/plugin/code.php BWᰣEvendor/zetacomponents/document/src/document/wiki/tokenizer/creole.phpS' BWS'*Gvendor/zetacomponents/document/src/document/wiki/tokenizer/dokuwiki.phpC2 BWC2 WHvendor/zetacomponents/document/src/document/wiki/tokenizer/mediawiki.php# BW#+*Ivendor/zetacomponents/document/src/document/wiki/tokenizer/confluence.php5 BW5^.E>vendor/zetacomponents/document/src/document/wiki/tokenizer.php& BW&3&<vendor/zetacomponents/document/src/document/wiki/visitor.php BW >;vendor/zetacomponents/document/src/document/wiki/creole.phpU BWU A:vendor/zetacomponents/document/src/document/wiki/token.php BW=ׇDvendor/zetacomponents/document/src/document/wiki/visitor/docbook.phpF BWF~Ӆ9vendor/zetacomponents/document/src/document/wiki/node.php| BW|~=vendor/zetacomponents/document/src/document/wiki/dokuwiki.php BW,ODvendor/zetacomponents/document/src/document/wiki/token/underline.php BWDvendor/zetacomponents/document/src/document/wiki/token/separator.php BWA@vendor/zetacomponents/document/src/document/wiki/token/title.php BW.bAvendor/zetacomponents/document/src/document/wiki/token/plugin.php BWq3XFvendor/zetacomponents/document/src/document/wiki/token/end_of_file.php BW'7DEvendor/zetacomponents/document/src/document/wiki/token/link_start.php BW6zPvendor/zetacomponents/document/src/document/wiki/token/confluence_link_start.phpV BWV Y4Dvendor/zetacomponents/document/src/document/wiki/token/image_end.php BWb #Hvendor/zetacomponents/document/src/document/wiki/token/internal_link.php BW{~Gvendor/zetacomponents/document/src/document/wiki/token/literal_line.php BWҨ?vendor/zetacomponents/document/src/document/wiki/token/bold.php BWWCZGvendor/zetacomponents/document/src/document/wiki/token/inline_quote.php BWXGvendor/zetacomponents/document/src/document/wiki/token/table_header.php BWGvendor/zetacomponents/document/src/document/wiki/token/footnote_end.php BW Fvendor/zetacomponents/document/src/document/wiki/token/superscript.php BWDuYFvendor/zetacomponents/document/src/document/wiki/token/line_markup.php BWeUIvendor/zetacomponents/document/src/document/wiki/token/footnote_start.php BWDvendor/zetacomponents/document/src/document/wiki/token/monospace.php BWDvendor/zetacomponents/document/src/document/wiki/token/table_row.php BW0 Cvendor/zetacomponents/document/src/document/wiki/token/link_end.php BWfyBvendor/zetacomponents/document/src/document/wiki/token/deleted.php BW+@vendor/zetacomponents/document/src/document/wiki/token/quote.php BW閬[Jvendor/zetacomponents/document/src/document/wiki/token/definition_list.php@ BW@yKvendor/zetacomponents/document/src/document/wiki/token/escape_character.php BWNPJvendor/zetacomponents/document/src/document/wiki/token/inter_wiki_link.php BW9Hvendor/zetacomponents/document/src/document/wiki/token/inline_markup.php BWcDvendor/zetacomponents/document/src/document/wiki/token/text_line.php BW#䂶Fvendor/zetacomponents/document/src/document/wiki/token/indentation.php BWT>aJvendor/zetacomponents/document/src/document/wiki/token/enumerated_list.php BWw{Avendor/zetacomponents/document/src/document/wiki/token/strike.php BWnXEvendor/zetacomponents/document/src/document/wiki/token/line_break.php BWj⊶Avendor/zetacomponents/document/src/document/wiki/token/italic.php BWяFMvendor/zetacomponents/document/src/document/wiki/token/mediawiki_emphasis.phpQ BWQbAgHvendor/zetacomponents/document/src/document/wiki/token/special_chars.php BWefHvendor/zetacomponents/document/src/document/wiki/token/literal_block.php BW™Hvendor/zetacomponents/document/src/document/wiki/token/external_link.php BW!GIvendor/zetacomponents/document/src/document/wiki/token/inline_literal.php BW. Cvendor/zetacomponents/document/src/document/wiki/token/new_line.php BWH]Fvendor/zetacomponents/document/src/document/wiki/token/bullet_list.php BWAGvendor/zetacomponents/document/src/document/wiki/token/block_markup.php BW޶Evendor/zetacomponents/document/src/document/wiki/token/page_break.php BW+(Evendor/zetacomponents/document/src/document/wiki/token/whitespace.php BWFvendor/zetacomponents/document/src/document/wiki/token/image_start.php< BW< <¶Dvendor/zetacomponents/document/src/document/wiki/token/subscript.php BWߘ~?vendor/zetacomponents/document/src/document/wiki/confluence.php BW*=gCvendor/zetacomponents/document/src/document/wiki/nodes/document.php  BW sJvendor/zetacomponents/document/src/document/wiki/nodes/invisible_break.php BWـmDvendor/zetacomponents/document/src/document/wiki/nodes/underline.php BW"yDvendor/zetacomponents/document/src/document/wiki/nodes/separator.php BWX=;T@vendor/zetacomponents/document/src/document/wiki/nodes/title.phpz BWzSAvendor/zetacomponents/document/src/document/wiki/nodes/plugin.php BW0C?vendor/zetacomponents/document/src/document/wiki/nodes/list.php BW~Dvendor/zetacomponents/document/src/document/wiki/nodes/image_end.php BWhٶ?vendor/zetacomponents/document/src/document/wiki/nodes/text.php BWjHvendor/zetacomponents/document/src/document/wiki/nodes/internal_link.php BW4Mʶ?vendor/zetacomponents/document/src/document/wiki/nodes/bold.php  BW U7ڶOvendor/zetacomponents/document/src/document/wiki/nodes/enumerated_list_item.php BWL=Gvendor/zetacomponents/document/src/document/wiki/nodes/inline_quote.php BW CƂ@vendor/zetacomponents/document/src/document/wiki/nodes/image.php BW&:Gvendor/zetacomponents/document/src/document/wiki/nodes/footnote_end.php BWƯMFvendor/zetacomponents/document/src/document/wiki/nodes/superscript.php BW=Qvendor/zetacomponents/document/src/document/wiki/nodes/table_header_separator.phpO BWO-vCvendor/zetacomponents/document/src/document/wiki/nodes/footnote.php BWǰ,%Dvendor/zetacomponents/document/src/document/wiki/nodes/monospace.php BWaݶDvendor/zetacomponents/document/src/document/wiki/nodes/table_row.php BWr&Cvendor/zetacomponents/document/src/document/wiki/nodes/link_end.php BWn8>Bvendor/zetacomponents/document/src/document/wiki/nodes/deleted.php BW<Bvendor/zetacomponents/document/src/document/wiki/nodes/section.php BW: Jvendor/zetacomponents/document/src/document/wiki/nodes/inter_wiki_link.php BW:3Evendor/zetacomponents/document/src/document/wiki/nodes/table_cell.php BWoc?vendor/zetacomponents/document/src/document/wiki/nodes/line.php BW$ ?Ӷ@vendor/zetacomponents/document/src/document/wiki/nodes/table.php BW%ĶJvendor/zetacomponents/document/src/document/wiki/nodes/enumerated_list.php BWJCEvendor/zetacomponents/document/src/document/wiki/nodes/line_break.php BWp RAvendor/zetacomponents/document/src/document/wiki/nodes/italic.php BW|UӶ@vendor/zetacomponents/document/src/document/wiki/nodes/block.php BW}Dvendor/zetacomponents/document/src/document/wiki/nodes/paragraph.php BWӶHvendor/zetacomponents/document/src/document/wiki/nodes/literal_block.php  BW V o?vendor/zetacomponents/document/src/document/wiki/nodes/link.php BW?Hvendor/zetacomponents/document/src/document/wiki/nodes/external_link.php BW=Ivendor/zetacomponents/document/src/document/wiki/nodes/inline_literal.php BW"O˶Fvendor/zetacomponents/document/src/document/wiki/nodes/bullet_list.php BW9iE.Evendor/zetacomponents/document/src/document/wiki/nodes/page_break.php BWEEvendor/zetacomponents/document/src/document/wiki/nodes/blockquote.php BW1{Kvendor/zetacomponents/document/src/document/wiki/nodes/bullet_list_item.php BWS\Avendor/zetacomponents/document/src/document/wiki/nodes/inline.php BWZJvendor/zetacomponents/document/src/document/wiki/nodes/matching_inline.php BWoooDvendor/zetacomponents/document/src/document/wiki/nodes/subscript.php BW4i6vendor/zetacomponents/document/src/document/bbcode.php$ BW$2=vendor/zetacomponents/document/src/document/bbcode/parser.php^ BW^.=vendor/zetacomponents/document/src/document/bbcode/plugin.php BW2@vendor/zetacomponents/document/src/document/bbcode/tokenizer.phpV, BWV,s7Avendor/zetacomponents/document/src/document/bbcode/plugins/no.php BW,uDvendor/zetacomponents/document/src/document/bbcode/plugins/image.php. BW.oҶDvendor/zetacomponents/document/src/document/bbcode/plugins/email.php BW CøDvendor/zetacomponents/document/src/document/bbcode/plugins/quote.php BW .0uGvendor/zetacomponents/document/src/document/bbcode/plugins/emphasis.php  BW MBvendor/zetacomponents/document/src/document/bbcode/plugins/url.php BW >vendor/zetacomponents/document/src/document/bbcode/visitor.phpc BWcfd<vendor/zetacomponents/document/src/document/bbcode/token.php BWRtFvendor/zetacomponents/document/src/document/bbcode/visitor/docbook.php\ BW\/L,b;vendor/zetacomponents/document/src/document/bbcode/node.php BWࣿFvendor/zetacomponents/document/src/document/bbcode/token/tag_clsoe.php BWzuHvendor/zetacomponents/document/src/document/bbcode/token/end_of_file.php BW3dEvendor/zetacomponents/document/src/document/bbcode/token/tag_open.php BWXFvendor/zetacomponents/document/src/document/bbcode/token/text_line.php BW6YFvendor/zetacomponents/document/src/document/bbcode/token/list_item.php BWɗ"Gvendor/zetacomponents/document/src/document/bbcode/token/line_break.php BWzJvendor/zetacomponents/document/src/document/bbcode/token/special_chars.php BWJvendor/zetacomponents/document/src/document/bbcode/token/literal_block.php BWh?Evendor/zetacomponents/document/src/document/bbcode/token/new_line.php BW󡱶Gvendor/zetacomponents/document/src/document/bbcode/token/whitespace.php BWjhEvendor/zetacomponents/document/src/document/bbcode/nodes/document.php  BW (+ߛAvendor/zetacomponents/document/src/document/bbcode/nodes/list.php BWq]FAvendor/zetacomponents/document/src/document/bbcode/nodes/text.php BW@Ҷ@vendor/zetacomponents/document/src/document/bbcode/nodes/tag.php BW Fvendor/zetacomponents/document/src/document/bbcode/nodes/list_item.php% BW%<Evendor/zetacomponents/document/src/document/bbcode/nodes/list_end.php BWY"Lvendor/zetacomponents/document/src/document/bbcode/nodes/enumerated_list.php& BW&/aBvendor/zetacomponents/document/src/document/bbcode/nodes/block.php BWo6Fvendor/zetacomponents/document/src/document/bbcode/nodes/paragraph.php BW,ضJvendor/zetacomponents/document/src/document/bbcode/nodes/literal_block.php( BW(=;mKvendor/zetacomponents/document/src/document/bbcode/nodes/inline_literal.php  BW XHvendor/zetacomponents/document/src/document/bbcode/nodes/bullet_list.php BWFvendor/zetacomponents/document/src/document/bbcode/nodes/tag_close.php BW@vendor/zetacomponents/document/src/tools/list_bullet_guesser.php6 BW6 A8vendor/zetacomponents/document/src/exceptions/parser.phpw BWw=vendor/zetacomponents/document/src/exceptions/invalid_odt.php/ BW/ Rk;vendor/zetacomponents/document/src/exceptions/exception.php BWϐxAvendor/zetacomponents/document/src/exceptions/invalid_docbook.php BW1жHvendor/zetacomponents/document/src/exceptions/missing_plugin_handler.php BWĶ?vendor/zetacomponents/document/src/exceptions/erroneous_xml.php BW۩>vendor/zetacomponents/document/src/exceptions/unknown_font.phpB BWBCm 9vendor/zetacomponents/document/src/exceptions/visitor.php BWE̶Kvendor/zetacomponents/document/src/exceptions/missing_directive_handler.php BWeL7Kvendor/zetacomponents/document/src/exceptions/missing_text_role_handler.php BW6m?vendor/zetacomponents/document/src/exceptions/rst_tokenizer.php BWRTAvendor/zetacomponents/document/src/exceptions/missing_visitor.phpB BWB*.@vendor/zetacomponents/document/src/exceptions/wiki_tokenizer.php BW"<vendor/zetacomponents/document/src/exceptions/conversion.php BW j~gQvendor/zetacomponents/document/src/exceptions/odt/formatting_properties_exist.php BW@O7vendor/zetacomponents/document/src/validation_error.php BW >te8vendor/zetacomponents/document/src/document_autoload.phpa BWa847vendor/zetacomponents/document/src/options/document.phpL BWL =%>vendor/zetacomponents/document/src/options/document_parser.php BW ZkFvendor/zetacomponents/document/src/options/converter_docbook_ezxml.php BW 9@;vendor/zetacomponents/document/src/options/document_odt.php BW Y8vendor/zetacomponents/document/src/options/converter.php BW ߶=vendor/zetacomponents/document/src/options/html_rendering.phpY BWYya;vendor/zetacomponents/document/src/options/document_rst.php7 BW7 boEvendor/zetacomponents/document/src/options/converter_docbook_wiki.phpj BWj 0R@J<vendor/zetacomponents/document/src/options/document_wiki.php BW DKDvendor/zetacomponents/document/src/options/converter_docbook_rst.php' BW'ʐ=vendor/zetacomponents/document/src/options/document_ezxml.php BW DĶ>vendor/zetacomponents/document/src/options/document_bbcode.php BW xBvendor/zetacomponents/document/src/options/document_pdf_footer.php BWxJvendor/zetacomponents/document/src/options/converter_docbook_html_xslt.php BW`6=vendor/zetacomponents/document/src/options/document_xhtml.php| BW| W];vendor/zetacomponents/document/src/options/document_xml.php BW 9PFvendor/zetacomponents/document/src/options/converter_ezxml_docbook.php BW Bn;vendor/zetacomponents/document/src/options/document_pdf.phpt BWt[+?vendor/zetacomponents/document/src/options/document_docbook.php BW sEvendor/zetacomponents/document/src/options/converter_docbook_html.php BWVRDDvendor/zetacomponents/document/src/options/converter_docbook_odt.php BWI=vendor/zetacomponents/document/src/options/converter_xslt.phpd BWdG9:vendor/zetacomponents/document/src/interfaces/document.phpg BWglն8vendor/zetacomponents/document/src/interfaces/parser.phpW BWWOJֶ<vendor/zetacomponents/document/src/interfaces/locateable.php BWH϶Evendor/zetacomponents/document/src/interfaces/ezxml_link_provider.php? BW?DI6Cvendor/zetacomponents/document/src/interfaces/conversions/xhtml.phpP BWP(^ֶ@vendor/zetacomponents/document/src/interfaces/rst_xhtml_role.php BW,4O;vendor/zetacomponents/document/src/interfaces/converter.phpr BWr$=<vendor/zetacomponents/document/src/interfaces/validation.php BW*Fvendor/zetacomponents/document/src/interfaces/ezxml_link_converter.php BWɶAvendor/zetacomponents/document/src/interfaces/error_reporting.php BWʰEvendor/zetacomponents/document/src/interfaces/rst_xhtml_directive.php BWNvendor/composer/LICENSE3 BW3vendor/composer/installed.jsonN BWN }<<vendor/composer/21b04df9/symfony-finder-203a10f/CHANGELOG.mdG BWG17vendor/composer/21b04df9/symfony-finder-203a10f/LICENSE) BW)&9vendor/composer/21b04df9/symfony-finder-203a10f/README.mdq BWqn;#vendor/erusev/parsedown/LICENSE.txtC BWC8E(vendor/erusev/parsedown/phpunit.xml.dist BWv!vendor/erusev/parsedown/README.mdU BWU %vendor/erusev/parsedown/composer.json BWxp1vendor/nikic/php-parser/grammar/kmyacc.php.parser% BW%vendor/symfony/filesystem/Symfony/Component/Filesystem/LICENSE) BW)NmQ@vendor/symfony/filesystem/Symfony/Component/Filesystem/README.md  BW !]Dvendor/symfony/filesystem/Symfony/Component/Filesystem/composer.json BW'YsZvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/phpunit.xml.distF BWFY̛Vvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/CHANGELOG.md BW lQvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/LICENSE) BW)&Svendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/README.mdW BWWvܶuvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd BWr dضWvendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/composer.json BW𶙛Avendor/symfony/console/Symfony/Component/Console/phpunit.xml.dist: BW:?l=vendor/symfony/console/Symfony/Component/Console/CHANGELOG.md3 BW3EJɶ8vendor/symfony/console/Symfony/Component/Console/LICENSE) BW)&Nvendor/symfony/console/Symfony/Component/Console/Resources/bin/hiddeninput.exe$ BW$v:vendor/symfony/console/Symfony/Component/Console/README.mdr BWrwwH]>vendor/symfony/console/Symfony/Component/Console/composer.json! BW!NtXvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/phpunit.xml.dist BWY̶Tvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/CHANGELOG.md BW$NOvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/LICENSE) BW)&Qvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/README.md BWAjUvendor/symfony/expression-language/Symfony/Component/ExpressionLanguage/composer.jsonS BWS,Avendor/symfony/process/Symfony/Component/Process/phpunit.xml.dist BW9=vendor/symfony/process/Symfony/Component/Process/CHANGELOG.md= BW= y8vendor/symfony/process/Symfony/Component/Process/LICENSE) BW)&:vendor/symfony/process/Symfony/Component/Process/README.md" BW"];>vendor/symfony/process/Symfony/Component/Process/composer.json& BW&3%Rvendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/phpunit.xml.distB BWBQH<Nvendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/CHANGELOG.md BWѯ Ivendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/LICENSE) BW)&Kvendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/README.mdu BWunȶOvendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/composer.jsonv BWvNl?vendor/symfony/finder/Symfony/Component/Finder/phpunit.xml.dist BWs+;vendor/symfony/finder/Symfony/Component/Finder/CHANGELOG.mdG BWG16vendor/symfony/finder/Symfony/Component/Finder/LICENSE) BW)&8vendor/symfony/finder/Symfony/Component/Finder/README.mdq BWqn;<vendor/symfony/finder/Symfony/Component/Finder/composer.json" BW"q;vendor/symfony/yaml/Symfony/Component/Yaml/phpunit.xml.dist BWiŶ7vendor/symfony/yaml/Symfony/Component/Yaml/CHANGELOG.md BWXl2vendor/symfony/yaml/Symfony/Component/Yaml/LICENSE) BW)&4vendor/symfony/yaml/Symfony/Component/Yaml/README.mdk BWk]8vendor/symfony/yaml/Symfony/Component/Yaml/composer.json BW Jvendor/symfony/class-loader/Symfony/Component/ClassLoader/phpunit.xml.dist> BW>;Fvendor/symfony/class-loader/Symfony/Component/ClassLoader/CHANGELOG.md BW^Avendor/symfony/class-loader/Symfony/Component/ClassLoader/LICENSE) BW)&Cvendor/symfony/class-loader/Symfony/Component/ClassLoader/README.md= BW= jvGvendor/symfony/class-loader/Symfony/Component/ClassLoader/composer.jsona BWaܖIvendor/symfony/translation/Symfony/Component/Translation/phpunit.xml.dist: BW:^C Evendor/symfony/translation/Symfony/Component/Translation/CHANGELOG.mdz BWz^;@vendor/symfony/translation/Symfony/Component/Translation/LICENSE) BW)NmQBvendor/symfony/translation/Symfony/Component/Translation/README.md BW3$'ovendor/symfony/translation/Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsd BWxO]vendor/symfony/translation/Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsd" BW": ZFvendor/symfony/translation/Symfony/Component/Translation/composer.json BWֶEvendor/symfony/stopwatch/Symfony/Component/Stopwatch/phpunit.xml.dist  BW 0<vendor/symfony/stopwatch/Symfony/Component/Stopwatch/LICENSE) BW)&>vendor/symfony/stopwatch/Symfony/Component/Stopwatch/README.md BWBvendor/symfony/stopwatch/Symfony/Component/Stopwatch/composer.json. BW.g ?vendor/symfony/config/Symfony/Component/Config/phpunit.xml.dist9 BW99f;vendor/symfony/config/Symfony/Component/Config/CHANGELOG.md BWKK6vendor/symfony/config/Symfony/Component/Config/LICENSE) BW)&8vendor/symfony/config/Symfony/Component/Config/README.md BW@<vendor/symfony/config/Symfony/Component/Config/composer.jsonH BWH"VӶEvendor/symfony/validator/Symfony/Component/Validator/phpunit.xml.dist  BW L5Avendor/symfony/validator/Symfony/Component/Validator/CHANGELOG.md " BW " 5<vendor/symfony/validator/Symfony/Component/Validator/LICENSE) BW)&]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.fr.xlfJ BWJcr]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.en.xlf"G BW"G"]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.pt.xlf`G BW`G+.ζ`vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlfoI BWoIL]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.he.xlf,I BW,I?]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.hu.xlf!I BW!IqUm]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.de.xlfI BWIͻ_`vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf+E BW+E]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.da.xlf5 BW5 8]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.lb.xlf1F BW1F.e]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.no.xlf1 BW1;T]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.ja.xlfYJ BWYJ^@i]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sk.xlfuJ BWuJ6qc]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.es.xlf`I BW`I,]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sq.xlft5 BWt547]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.vi.xlfB BWBR`vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf< BW<RE]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.bg.xlfI BWI R]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.ru.xlfV BWVg]]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.eu.xlfA BWA젼]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.ro.xlf@E BW@Eʿ\]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.gl.xlfJ BWJ<]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.ar.xlf/Y BW/Yן]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.nb.xlf9 BW9^PW]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.lt.xlfII BWIIr4bvendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlfrR BWrRx=]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sl.xlfwK BWwK$Ϣ1]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.ca.xlfH BWHj.Ѷ]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.nl.xlfH BWHfz]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.hr.xlf'@ BW'@f]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.el.xlfM BWM%bbvendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlfmG BWmG?@]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.uk.xlfVK BWVK]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sv.xlfF BWF]L]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.af.xlf3 BW3qٶ]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.fi.xlf2 BW2Ħ ]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.pl.xlfdJ BWdJN]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.it.xlfI BWI-ն]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.et.xlft= BWt=mU]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.id.xlf> BW>.4]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.th.xlfFQ BWFQb]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.mn.xlf" BW"UL]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.hy.xlfG, BWG,in]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.az.xlfj1 BWj1]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.cy.xlf1 BW1gC]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.fa.xlfG BWGbWA]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.tr.xlf&1 BW&1/`]vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.cs.xlfI BWIID>vendor/symfony/validator/Symfony/Component/Validator/README.md BW Rs|vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd- BW-TOöBvendor/symfony/validator/Symfony/Component/Validator/composer.json- BW-gRp4vendor/zendframework/zend-servicemanager/LICENSE.txt  BW c89vendor/zendframework/zend-servicemanager/phpunit.xml.dist0 BW0`;;vendor/zendframework/zend-servicemanager/phpunit.xml.travis0 BW0`;8vendor/zendframework/zend-servicemanager/CONTRIBUTING.md BW2vendor/zendframework/zend-servicemanager/README.mdx BWx: U!6vendor/zendframework/zend-servicemanager/composer.json\ BW\j׺O,vendor/zendframework/zend-stdlib/LICENSE.txt  BW c81vendor/zendframework/zend-stdlib/phpunit.xml.dist( BW(mI 3vendor/zendframework/zend-stdlib/phpunit.xml.travis( BW(mI 0vendor/zendframework/zend-stdlib/CONTRIBUTING.mdz BWz$*vendor/zendframework/zend-stdlib/README.md BWL$H.vendor/zendframework/zend-stdlib/composer.json& BW&n,vendor/zendframework/zend-filter/LICENSE.txt  BW c81vendor/zendframework/zend-filter/phpunit.xml.disty BWy3vendor/zendframework/zend-filter/phpunit.xml.travisy BWy0vendor/zendframework/zend-filter/CONTRIBUTING.mdz BWz>*vendor/zendframework/zend-filter/README.md BW<ض.vendor/zendframework/zend-filter/composer.json^ BW^q +vendor/zendframework/zend-cache/LICENSE.txt  BW c80vendor/zendframework/zend-cache/phpunit.xml.dist BW rʳ2vendor/zendframework/zend-cache/phpunit.xml.travis BW 9/vendor/zendframework/zend-cache/CONTRIBUTING.mds BWsD)vendor/zendframework/zend-cache/README.mdz BWz|e-vendor/zendframework/zend-cache/composer.json BWTK12vendor/zendframework/zend-eventmanager/LICENSE.txt  BW c87vendor/zendframework/zend-eventmanager/phpunit.xml.dist/ BW/s9vendor/zendframework/zend-eventmanager/phpunit.xml.travis/ BW/s6vendor/zendframework/zend-eventmanager/CONTRIBUTING.md BW}"0vendor/zendframework/zend-eventmanager/README.md\ BW\y*4vendor/zendframework/zend-eventmanager/composer.json9 BW9Nu,vendor/zendframework/zend-config/LICENSE.txt  BW c81vendor/zendframework/zend-config/phpunit.xml.dist* BW*Z3vendor/zendframework/zend-config/phpunit.xml.travis| BW|^0vendor/zendframework/zend-config/CONTRIBUTING.mdz BWzb*vendor/zendframework/zend-config/README.md BW*Y.vendor/zendframework/zend-config/composer.json BW&8*vendor/zendframework/zend-i18n/LICENSE.txt  BW c8/vendor/zendframework/zend-i18n/phpunit.xml.dist& BW&T1vendor/zendframework/zend-i18n/phpunit.xml.travis& BW&T.vendor/zendframework/zend-i18n/CONTRIBUTING.mdl BWly֊(vendor/zendframework/zend-i18n/README.md BW ,vendor/zendframework/zend-i18n/composer.json BW'2*vendor/zendframework/zend-json/LICENSE.txt  BW c8/vendor/zendframework/zend-json/phpunit.xml.dist& BW&>1vendor/zendframework/zend-json/phpunit.xml.travis& BW&>.vendor/zendframework/zend-json/CONTRIBUTING.mdl BWlǟc(vendor/zendframework/zend-json/README.mdi BWicꓶ,vendor/zendframework/zend-json/composer.json BWT0vendor/zendframework/zend-serializer/LICENSE.txt  BW c85vendor/zendframework/zend-serializer/phpunit.xml.dist, BW,wg7vendor/zendframework/zend-serializer/phpunit.xml.travis, BW,wg4vendor/zendframework/zend-serializer/CONTRIBUTING.md BW6Ѷ.vendor/zendframework/zend-serializer/README.md] BW];_n2vendor/zendframework/zend-serializer/composer.json BWI,Ѷ*vendor/zendframework/zend-math/LICENSE.txt  BW c8/vendor/zendframework/zend-math/phpunit.xml.dist& BW&P1vendor/zendframework/zend-math/phpunit.xml.travis& BW&P.vendor/zendframework/zend-math/CONTRIBUTING.mdl BWl&4 (vendor/zendframework/zend-math/README.mdt BWtV4*,vendor/zendframework/zend-math/composer.jsonY BWYiZ9vendor/zetacomponents/document/src/pcss/style/default.css BW 2tFvendor/zetacomponents/document/src/document/xml/xhtml/schema/xlink.xsd BWW~iNvendor/zetacomponents/document/src/document/xml/xhtml/schema/xhtml1-strict.xsd BWA$Hvendor/zetacomponents/document/src/document/xml/xhtml/schema/docbook.xsd@ BW@ V Dvendor/zetacomponents/document/src/document/xml/xhtml/schema/xml.xsd[ BW['ZTvendor/zetacomponents/document/src/document/xml/xhtml/schema/xhtml1-transitional.xsdC BWCvDvendor/zetacomponents/document/src/document/xml/odt/data/odf_1.2.rngI BWI ,~܆Rvendor/zetacomponents/document/src/document/xml/ezxml/schema/ezxml_schema_lose.rng7? BW7?< >Mvendor/zetacomponents/document/src/document/xml/ezxml/schema/ezxml_schema.rnge BWe2ݷ>vendor/zetacomponents/document/src/options/data/html_style.css@ BW@N=vendor/zetacomponents/document/src/options/data/template.fodtN& BWN&ѾW;vendor/zetacomponents/document/src/options/data/docbook.xsd2 BW2an#src/phpDocumentor/Configuration.php BWem 0src/phpDocumentor/Descriptor/ClassDescriptor.phpY# BWY#̶ҋ/src/phpDocumentor/Descriptor/Example/Finder.php BWuD;1src/phpDocumentor/Descriptor/MethodDescriptor.php BW D0src/phpDocumentor/Descriptor/ProjectAnalyzer.php  BW 6}83src/phpDocumentor/Descriptor/FunctionDescriptor.php BWYL.src/phpDocumentor/Descriptor/TagDescriptor.phpT BWTm0۶0src/phpDocumentor/Descriptor/TraitDescriptor.php2 BW26oE3src/phpDocumentor/Descriptor/ArgumentDescriptor.phpZ BWZ 34src/phpDocumentor/Descriptor/NamespaceDescriptor.php BWj/src/phpDocumentor/Descriptor/FileDescriptor.phpD! BWD!z2src/phpDocumentor/Descriptor/Filter/Filterable.php BWdǚ9src/phpDocumentor/Descriptor/Filter/StripOnVisibility.php BW֮5src/phpDocumentor/Descriptor/Filter/StripInternal.php- BW- ..src/phpDocumentor/Descriptor/Filter/Filter.php BW!e3src/phpDocumentor/Descriptor/Filter/StripIgnore.php BWȳж4src/phpDocumentor/Descriptor/Filter/ClassFactory.phpA BWAbZ5src/phpDocumentor/Descriptor/Tag/MethodDescriptor.php BWU[2src/phpDocumentor/Descriptor/Tag/VarDescriptor.php BWG{ 3src/phpDocumentor/Descriptor/Tag/LinkDescriptor.phpq BWqͶ4src/phpDocumentor/Descriptor/Tag/SinceDescriptor.php BWG6src/phpDocumentor/Descriptor/Tag/ExampleDescriptor.php BW >9src/phpDocumentor/Descriptor/Tag/DeprecatedDescriptor.php BW)z5src/phpDocumentor/Descriptor/Tag/AuthorDescriptor.php BWߘ3src/phpDocumentor/Descriptor/Tag/UsesDescriptor.php BW Dsrc/phpDocumentor/Descriptor/Tag/BaseTypes/TypedVariableAbstract.php BWt>|<src/phpDocumentor/Descriptor/Tag/BaseTypes/TypedAbstract.php BW并7src/phpDocumentor/Descriptor/Tag/PropertyDescriptor.php BWŒ4src/phpDocumentor/Descriptor/Tag/ParamDescriptor.php BWD)5src/phpDocumentor/Descriptor/Tag/ThrowsDescriptor.php BWDqWh6src/phpDocumentor/Descriptor/Tag/VersionDescriptor.php BWk 5src/phpDocumentor/Descriptor/Tag/ReturnDescriptor.php BWs(2src/phpDocumentor/Descriptor/Tag/SeeDescriptor.php BW :src/phpDocumentor/Descriptor/Builder/AssemblerAbstract.php| BW|2Dsrc/phpDocumentor/Descriptor/Builder/Reflector/AssemblerAbstract.phpF BWFB+/Asrc/phpDocumentor/Descriptor/Builder/Reflector/TraitAssembler.php BW O@src/phpDocumentor/Descriptor/Builder/Reflector/FileAssembler.php@! BW@!^^uGsrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/ThrowsAssembler.php BWkTKsrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/GenericTagAssembler.phpF BWFB.Esrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/UsesAssembler.php BWT6<Fsrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/ParamAssembler.phpz BWzܾOsrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/TypeCollectionAssembler.php BW#Gsrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/AuthorAssembler.phpi BWio'}Esrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/LinkAssembler.php BWT~̶Isrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/PropertyAssembler.phpk BWk"?}Gsrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/MethodAssembler.php_ BW_@ZFsrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssembler.php BW1!Hsrc/phpDocumentor/Descriptor/Builder/Reflector/Tags/VersionAssembler.php BW9src/phpDocumentor/Descriptor/ProjectDescriptorBuilder.php BWiN9src/phpDocumentor/Descriptor/Interfaces/FileInterface.php BW0<src/phpDocumentor/Descriptor/Interfaces/ProjectInterface.phpD BWDt5:src/phpDocumentor/Descriptor/Interfaces/TraitInterface.php BW94;src/phpDocumentor/Descriptor/Interfaces/MethodInterface.php BWQ[>src/phpDocumentor/Descriptor/Interfaces/InterfaceInterface.php7 BW7.:src/phpDocumentor/Descriptor/Interfaces/ChildInterface.php BWZzj\?src/phpDocumentor/Descriptor/Interfaces/VisibilityInterface.php( BW(29src/phpDocumentor/Descriptor/Interfaces/TypeInterface.phpS BWStж=src/phpDocumentor/Descriptor/Interfaces/ArgumentInterface.php3 BW3 S/4<src/phpDocumentor/Descriptor/Interfaces/PackageInterface.php BW}g?>src/phpDocumentor/Descriptor/Interfaces/NamespaceInterface.php: BW:S᧶<src/phpDocumentor/Descriptor/Interfaces/ElementInterface.php BW *}=src/phpDocumentor/Descriptor/Interfaces/PropertyInterface.php BWp=src/phpDocumentor/Descriptor/Interfaces/FunctionInterface.php BWC=src/phpDocumentor/Descriptor/Interfaces/ConstantInterface.phpg BWgp:src/phpDocumentor/Descriptor/Interfaces/ClassInterface.php BW󮏠>src/phpDocumentor/Descriptor/Interfaces/ContainerInterface.phpO BWOsrc/phpDocumentor/Descriptor/Cache/ProjectDescriptorMapper.phpX BWX:ާ3src/phpDocumentor/Descriptor/DescriptorAbstract.php* BW*-SsEsrc/phpDocumentor/Descriptor/Exception/MissingDependencyException.php BW24src/phpDocumentor/Descriptor/InterfaceDescriptor.php1 BW18n0src/phpDocumentor/Descriptor/Validator/Error.php BWwQ.7src/phpDocumentor/Descriptor/Type/BooleanDescriptor.php BW6;ض7src/phpDocumentor/Descriptor/Type/IntegerDescriptor.php BW-掳:src/phpDocumentor/Descriptor/Type/CollectionDescriptor.php BW`#ߏ;src/phpDocumentor/Descriptor/Type/UnknownTypeDescriptor.php BWs>6src/phpDocumentor/Descriptor/Type/StringDescriptor.php BW_5src/phpDocumentor/Descriptor/Type/FloatDescriptor.php BW3src/phpDocumentor/Descriptor/ConstantDescriptor.phpD BWDosrc/phpDocumentor/Bootstrap.php BW:n:.src/phpDocumentor/Translator/Configuration.php BW0src/phpDocumentor/Translator/ServiceProvider.phpK BWKcnw+src/phpDocumentor/Translator/Translator.php BW3$src/phpDocumentor/Event/LogEvent.php\ BW\A Y&src/phpDocumentor/Event/DebugEvent.php BW.&src/phpDocumentor/Event/Dispatcher.php BW !)src/phpDocumentor/Event/EventAbstract.php BW ;#src/phpDocumentor/Plugin/Plugin.php BWVö0src/phpDocumentor/Plugin/Graphs/Writer/Graph.php" BW"3src/phpDocumentor/Plugin/Graphs/ServiceProvider.phpD BWDϘ]T+src/phpDocumentor/Plugin/Core/Exception.phpe BWe4ㆶHsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/ValidatorAbstract.php  BW @Usrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Functions/AreAllArgumentsValid.php BWHsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/RequiredValidator.php BW *spsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesArgumentNameMatchParamValidator.php BWpqsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsReturnTypeNotAnIdeDefaultValidator.php BWolfsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesParamsExistsValidator.php BW$>jsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/AreAllArgumentsValidValidator.php\ BW\#{]src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesParamsExists.phpl BWlj{Ӷtsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesArgumentTypehintMatchParamValidator.php BW`jsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsArgumentInDocBlockValidator.php BWӹksrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesArgumentTypehintMatchParam.php BW4Tasrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsArgumentInDocBlock.phpe BWe hsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsReturnTypeNotAnIdeDefault.phpw BWwĜjasrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/AreAllArgumentsValid.php BW gsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesArgumentNameMatchParam.phpv BWvkpsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsParamTypeNotAnIdeDefaultValidator.php BW |gsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsParamTypeNotAnIdeDefault.phpu BWuTulsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasPackageWithSubpackageValidator.phpo BWoA[src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSinglePackage.phpp BWp^src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSingleSubpackage.phpv BWv2޶dsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSinglePackageValidator.php BW Scsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasPackageWithSubpackage.php BW6gsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSingleSubpackageValidator.php BWwb)Vsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Property/HasSummary.phpd BWd]G_src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Property/HasSummaryValidator.php. BW.YlJsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/DeprecatedValidator.php BW D6"Lsrc/phpDocumentor/Plugin/Core/Descriptor/Validator/ValidationValueObject.php BWm@0src/phpDocumentor/Plugin/Core/Xslt/Extension.php BW _D1src/phpDocumentor/Plugin/Core/ServiceProvider.php BW&5-src/phpDocumentor/Plugin/Core/Messages/en.php BW^T-src/phpDocumentor/Plugin/Core/Messages/de.phph BWh \\Jsrc/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/ArgumentConverter.php` BW`Jsrc/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/ConstantConverter.phpx BWxˏEsrc/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/TagConverter.php_ BW_EBy̶Hsrc/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/MethodConverter.php BW !iKsrc/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/InterfaceConverter.phpG BWGcζGsrc/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/TraitConverter.php BW 8Jsrc/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/PropertyConverter.php BW GPJsrc/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/DocBlockConverter.php BW#ȯ?src/phpDocumentor/Plugin/Core/Transformer/Writer/Pathfinder.php BW ijж?src/phpDocumentor/Plugin/Core/Transformer/Writer/Statistics.php BW1?src/phpDocumentor/Plugin/Core/Transformer/Writer/Checkstyle.php BW#v;src/phpDocumentor/Plugin/Core/Transformer/Writer/FileIo.php BW *)8src/phpDocumentor/Plugin/Core/Transformer/Writer/Xsl.php2 BW2M8src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml.phpW BWWв٭?src/phpDocumentor/Plugin/Core/Transformer/Writer/Sourcecode.php BW Fsrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/LicenseTag.php BW .GDsrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/ParamTag.php BW, Gsrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/PropertyTag.phpJ BWJ 5S4Csrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/UsesTag.php BWhjEsrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/ReturnTag.phpq BWq Esrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/MethodTag.php  BW Esrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/CoversTag.php BWXBsrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/VarTag.php BWGsrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/InternalTag.php BW!Esrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/IgnoreTag.php BWI#.Esrc/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/AuthorTag.phpb BWbC6׶,src/phpDocumentor/Plugin/ServiceProvider.phpR BWR&src/phpDocumentor/Plugin/Parameter.phpm BWm5>7Esrc/phpDocumentor/Plugin/LegacyNamespaceConverter/ServiceProvider.phpO BWO Ksrc/phpDocumentor/Plugin/LegacyNamespaceConverter/LegacyNamespaceFilter.php BW jf;src/phpDocumentor/Plugin/LegacyNamespaceConverter/README.mdJ BWJ>0eUsrc/phpDocumentor/Plugin/LegacyNamespaceConverter/Tests/LegacyNamespaceFilterTest.php BW0-src/phpDocumentor/Plugin/Twig/Writer/Twig.phpB4 BWB4'V+src/phpDocumentor/Plugin/Twig/Extension.php BW1src/phpDocumentor/Plugin/Twig/ServiceProvider.phpF BWFZzE4src/phpDocumentor/Plugin/Twig/ExtensionInterface.php  BW 1src/phpDocumentor/Plugin/Scrybe/Template/Twig.phpV BWV{ b4src/phpDocumentor/Plugin/Scrybe/Template/Factory.php BW ۶>src/phpDocumentor/Plugin/Scrybe/Template/TemplateInterface.phpB BWBf<Usrc/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Template/Mock/Template.php BW>*϶Psrc/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Template/TwigTest.php BWFSsrc/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Template/FactoryTest.php BW r5Nsrc/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/ApplicationTest.php. BW.l3lsrc/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Converter/Metadata/TableOfContents/ModuleTest.phpS BWSvosrc/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Converter/Metadata/TableOfContents/BaseEntryTest.php9 BW9 LFjsrc/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Converter/Metadata/TableOfContents/FileTest.phpG BWG esrc/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Converter/Metadata/TableOfContentsTest.php BWB5osrc/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Converter/RestructuredText/Visitors/DiscoverTest.php BW {Fsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/layout.pdf.twig BW{Dsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/toc.html.twig BWFsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/layout.tex.twig BWѺQGsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/layout.html.twig BW7fLsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/css/bootstrap.min.cssM BWMi 2Wsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/css/bootstrap-responsive.min.css BWpHsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/css/bootstrap.cssB> BWB>떄Ssrc/phpDocumentor/Plugin/Scrybe/data/templates/default/css/bootstrap-responsive.css/) BW/)6Gsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/css/template.css"% BW"%ywPGsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/css/prettify.css BWlԶEsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/css/scrybe.cssk BWkj:Ssrc/phpDocumentor/Plugin/Scrybe/data/templates/default/img/glyphicons-halflings.png BW!˶Ysrc/phpDocumentor/Plugin/Scrybe/data/templates/default/img/glyphicons-halflings-white.png BW2zǶFsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/img/favicon.ico~ BW~\WEsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/img/loader.gifv BWv zJsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/bootstrap.min.jsP BWP@h}-Msrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-ml.jsQ BWQSPsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-proto.js. BW.Osrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-yaml.js BW,IMsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-xq.jsZ BWZċONsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-lua.js( BW(ʥҥNsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-tex.js BWCٶOsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-lisp.js BW9׶Osrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-wiki.js BWRsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/prettify.min.js@5 BW@5;JMsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-vb.js BW.+Qsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-apollo.js BWEMsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-hs.js9 BW9uk3VOsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-vhdl.js BWնPsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-scala.js BW(Lsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-n.jsx BWxV7eNsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-css.js] BW],zMsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-go.js BWZONsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-clj.js BWޤNsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/prettify/lang-sql.js BW7hMsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/jquery-1.7.1.min.js BWGEsrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/template.js BWu8Asrc/phpDocumentor/Plugin/Scrybe/data/templates/default/js/menu.js BWEa9src/phpDocumentor/Plugin/Scrybe/docs/commands/to-html.rst BW:src/phpDocumentor/Plugin/Scrybe/docs/commands/to-latex.rst BW8src/phpDocumentor/Plugin/Scrybe/docs/commands/to-pdf.rst BW.src/phpDocumentor/Plugin/Scrybe/docs/index.rst BWl t2src/phpDocumentor/Plugin/Scrybe/docs/internals.rst BWZA0src/phpDocumentor/Plugin/Scrybe/docs/license.rst1 BW1vO4src/phpDocumentor/Plugin/Scrybe/docs/images/logo.png- BW-yw?src/phpDocumentor/Plugin/Scrybe/Converter/Metadata/Glossary.php~ BW~~{OPsrc/phpDocumentor/Plugin/Scrybe/Converter/Metadata/TableOfContents/BaseEntry.php BW öNsrc/phpDocumentor/Plugin/Scrybe/Converter/Metadata/TableOfContents/Heading.php BW?+FMsrc/phpDocumentor/Plugin/Scrybe/Converter/Metadata/TableOfContents/Module.php BWw@DKsrc/phpDocumentor/Plugin/Scrybe/Converter/Metadata/TableOfContents/File.php BWmOFsrc/phpDocumentor/Plugin/Scrybe/Converter/Metadata/TableOfContents.phpu BWu Ѷ=src/phpDocumentor/Plugin/Scrybe/Converter/Metadata/Assets.php BW <@src/phpDocumentor/Plugin/Scrybe/Converter/Definition/Factory.php BW84Csrc/phpDocumentor/Plugin/Scrybe/Converter/Definition/Definition.phpZ BWZrsb=src/phpDocumentor/Plugin/Scrybe/Converter/ToHtmlInterface.php7 BW7C1Hsrc/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Roles/Doc.php BW _ݶEsrc/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/ToHtml.php BW@TGsrc/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Document.php  BW -Psrc/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Visitors/Discover.php BWbnuOsrc/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Visitors/Creator.php BW91Osrc/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Directives/Image.php BWQsrc/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Directives/Toctree.php BW 5Ssrc/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Directives/CodeBlock.php BW[gPsrc/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Directives/Figure.php BW⅕<src/phpDocumentor/Plugin/Scrybe/Converter/ToPdfInterface.phpP BWP&>src/phpDocumentor/Plugin/Scrybe/Converter/ToLatexInterface.php. BW.n5src/phpDocumentor/Plugin/Scrybe/Converter/Factory.phpe BWeo(@src/phpDocumentor/Plugin/Scrybe/Converter/ConverterInterface.php) BW) ;src/phpDocumentor/Plugin/Scrybe/Converter/BaseConverter.php BWkRsrc/phpDocumentor/Plugin/Scrybe/Converter/Exception/ConverterNotFoundException.php BW%޶;src/phpDocumentor/Plugin/Scrybe/Converter/Format/Format.php BW D?src/phpDocumentor/Plugin/Scrybe/Converter/Format/Collection.phpv BWvHfVsrc/phpDocumentor/Plugin/Scrybe/Converter/Format/Exception/FormatNotFoundException.phpo BWok+src/phpDocumentor/Console/Output/Output.php3 BW3#aa-src/phpDocumentor/Console/Input/ArgvInput.php BW3*src/phpDocumentor/Parser/Configuration.php BW֩m&src/phpDocumentor/Parser/Exception.php] BW]\FjW1src/phpDocumentor/Parser/Util/ParserPopulator.php BW#src/phpDocumentor/Parser/Parser.phpm- BWm-}n/src/phpDocumentor/Parser/Event/PreFileEvent.php BW!!src/phpDocumentor/Parser/File.php* BW*P,src/phpDocumentor/Parser/ServiceProvider.php BWNi9src/phpDocumentor/Parser/Command/Project/ParseCommand.php5 BW5Y (src/phpDocumentor/Parser/Messages/en.php BW 'Asrc/phpDocumentor/Parser/Exception/MissingDependencyException.php BW|Ŷ=src/phpDocumentor/Parser/Exception/FilesNotFoundException.php BW0Ӷ0src/phpDocumentor/Parser/Configuration/Files.php BW}0src/phpDocumentor/Command/Phar/UpdateCommand.phpR BWRɊ8src/phpDocumentor/Command/Helper/ConfigurationHelper.php~ BW~Q1src/phpDocumentor/Command/Helper/LoggerHelper.php BW)|k0src/phpDocumentor/Command/Project/RunCommand.php)+ BW)+be%src/phpDocumentor/Command/Command.phpn BWnr5.src/phpDocumentor/Partials/ServiceProvider.php- BW- Ǩ&)src/phpDocumentor/Partials/Collection.phpi BWiCGsrc/phpDocumentor/Partials/Exception/MissingNameForPartialException.php BWҵQ&src/phpDocumentor/Partials/Partial.php BWq#ӵ6src/phpDocumentor/Transformer/Writer/Initializable.php BWoi5src/phpDocumentor/Transformer/Writer/Translatable.php9 BW9gӻ7src/phpDocumentor/Transformer/Writer/WriterAbstract.php# BW#g:3src/phpDocumentor/Transformer/Writer/Collection.phpJ BWJ 7?Esrc/phpDocumentor/Transformer/Writer/Exception/RequirementMissing.php BW]1src/phpDocumentor/Transformer/Writer/Routable.php BW,/src/phpDocumentor/Transformer/Configuration.phpA BWA zf4src/phpDocumentor/Transformer/Template/Parameter.phpQ BWQ2src/phpDocumentor/Transformer/Template/Factory.php BW ͌ȶ7src/phpDocumentor/Transformer/Template/PathResolver.phpi BWiβ75src/phpDocumentor/Transformer/Template/Collection.php BW A+src/phpDocumentor/Transformer/Exception.phpt BWtEж*src/phpDocumentor/Transformer/Template.phpu! BWu!s1src/phpDocumentor/Transformer/Router/Renderer.php BW7src/phpDocumentor/Transformer/Router/ExternalRouter.php] BW]ٶ.src/phpDocumentor/Transformer/Router/Queue.php BWJ7src/phpDocumentor/Transformer/Router/StandardRouter.php BWchJ5src/phpDocumentor/Transformer/Router/ForFileProxy.php BW/Asrc/phpDocumentor/Transformer/Router/Matcher/MatcherInterface.php BW;-src/phpDocumentor/Transformer/Router/Rule.php BW f6Nsrc/phpDocumentor/Transformer/Router/UrlGenerator/Standard/ClassDescriptor.php BWzʼOsrc/phpDocumentor/Transformer/Router/UrlGenerator/Standard/MethodDescriptor.phpi BWi@cQsrc/phpDocumentor/Transformer/Router/UrlGenerator/Standard/FunctionDescriptor.php BWlL Rsrc/phpDocumentor/Transformer/Router/UrlGenerator/Standard/NamespaceDescriptor.phpj BWjбvMsrc/phpDocumentor/Transformer/Router/UrlGenerator/Standard/FileDescriptor.php7 BW7pڶZsrc/phpDocumentor/Transformer/Router/UrlGenerator/Standard/QualifiedNameToUrlConverter.php! BW! Psrc/phpDocumentor/Transformer/Router/UrlGenerator/Standard/PackageDescriptor.phpb BWbkb$yQsrc/phpDocumentor/Transformer/Router/UrlGenerator/Standard/PropertyDescriptor.phpt BWt;%kQsrc/phpDocumentor/Transformer/Router/UrlGenerator/Standard/ConstantDescriptor.php BWKsrc/phpDocumentor/Transformer/Router/UrlGenerator/UrlGeneratorInterface.php BWn:7src/phpDocumentor/Transformer/Router/RouterAbstract.php} BW}Ic-src/phpDocumentor/Transformer/Transformer.phpe) BWe)uAsrc/phpDocumentor/Transformer/Event/WriterInitializationEvent.php BW֖?src/phpDocumentor/Transformer/Event/PostTransformationEvent.php BW8ק':src/phpDocumentor/Transformer/Event/PostTransformEvent.php BW9src/phpDocumentor/Transformer/Event/PreTransformEvent.php BW&g9src/phpDocumentor/Transformer/Event/PreXslWriterEvent.php BW1o>src/phpDocumentor/Transformer/Event/PreTransformationEvent.phpM BWMa~V1src/phpDocumentor/Transformer/ServiceProvider.php% BW%ݶ0src/phpDocumentor/Transformer/Transformation.php# BW#; ->src/phpDocumentor/Transformer/Command/Template/ListCommand.php BWBsrc/phpDocumentor/Transformer/Command/Project/TransformCommand.php 2 BW 2# =src/phpDocumentor/Transformer/Behaviour/BehaviourAbstract.phpv BWv')6src/phpDocumentor/Transformer/Behaviour/Collection.phpr BWr?rYFsrc/phpDocumentor/Transformer/Exception/MissingDependencyException.php BWuo9src/phpDocumentor/Transformer/Exception/UnknownWriter.php BWr&A?src/phpDocumentor/Transformer/Configuration/Transformations.php BWNHsrc/phpDocumentor/Transformer/Configuration/Transformations/Template.php BWHfJsrc/phpDocumentor/Transformer/Configuration/ExternalClassDocumentation.php BW2K!src/phpDocumentor/Application.php% BW%dwD'src/phpDocumentor/Compiler/Compiler.php BWǶ;src/phpDocumentor/Compiler/Pass/MarkerFromTagsExtractor.php BW 8src/phpDocumentor/Compiler/Pass/ElementsIndexBuilder.phpt BWtȏ P7src/phpDocumentor/Compiler/Pass/ExampleTagsEnricher.php7 BW7 β6src/phpDocumentor/Compiler/Pass/PackageTreeBuilder.php' BW'A(?src/phpDocumentor/Compiler/Pass/ResolveInlineLinkAndSeeTags.php BW\81)src/phpDocumentor/Compiler/Pass/Debug.php BW2g8src/phpDocumentor/Compiler/Pass/NamespaceTreeBuilder.php8 BW8/4,src/phpDocumentor/Compiler/Linker/Linker.php2 BW2YV4src/phpDocumentor/Compiler/CompilerPassInterface.php BWg U*src/phpDocumentor/Configuration/Merger.php BWa/+src/phpDocumentor/Configuration/Logging.php BW8src/phpDocumentor/Configuration/Resources/phpdoc.tpl.xml BWM?=src/phpDocumentor/Configuration/Merger/Annotation/Replace.php BW:3src/phpDocumentor/Configuration/ServiceProvider.php BW($^L*src/phpDocumentor/Configuration/Loader.php+ BW+t 3src/Cilex/Provider/JmsSerializerServiceProvider.php` BW` \7vendor/twig/twig/lib/Twig/Node/Expression/Test/Even.php| BW| ^u>vendor/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php BW <;vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.phpj BWjP϶9vendor/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php BW(I:vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.phpG BWGDl6vendor/twig/twig/lib/Twig/Node/Expression/Test/Odd.phpy BWy|7vendor/twig/twig/lib/Twig/Node/Expression/Test/Null.phpj BWj-data/templates/abstract/report_deprecated.xslm BWm ai*data/templates/abstract/report_markers.xsl BW @Qt#data/templates/abstract/content.xsl BW1ʶ#data/templates/abstract/api-doc.xsll BWlԸ!data/templates/abstract/index.xsl BWUBI$data/templates/abstract/template.xml BW ťR#data/templates/abstract/helpers.xsl BW"data/templates/abstract/chrome.xsl BWtF0data/templates/abstract/report_parse_markers.xsl BW  ;(data/templates/abstract/css/template.cssj BWj,data/templates/abstract/css/sen.full.min.cssm BWmY(data/templates/abstract/css/abstract.css1 BW1];#data/templates/abstract/sidebar.xsl% BW%gti'data/templates/abstract/graph_class.xsln BWn._)data/templates/abstract/api-doc/class.xslC BWCcL|,data/templates/abstract/api-doc/docblock.xsl! BW!i,data/templates/abstract/api-doc/property.xsl BW Ov(data/templates/abstract/api-doc/file.xsl BWoo v,data/templates/abstract/api-doc/function.xslR BWR ֶ,data/templates/abstract/api-doc/constant.xsl BW*data/templates/abstract/sidebar/footer.xsl9 BW9S,data/templates/abstract/sidebar/sections.xsl BW vE7data/templates/abstract/sidebar/sections/namespaces.xsl BW ߼Ҷ2data/templates/abstract/sidebar/sections/files.xsl BWF~u0data/templates/abstract/sidebar/sections/api.xsl7 BW7sfy3data/templates/abstract/sidebar/sections/charts.xsll BWls 4data/templates/abstract/sidebar/sections/reports.xsl3 BW35data/templates/abstract/sidebar/sections/packages.xsl BWx{*data/templates/abstract/sidebar/header.xsl? BW?i`data/templates/abstract/README BW)data/templates/abstract/chrome/footer.xsl BWE`'data/templates/abstract/chrome/menu.xsl BWqɟ)data/templates/abstract/chrome/header.xsl/ BW/Q'data/templates/abstract/chrome/head.xsl BW%V-data/templates/abstract/js/jquery.treeview.jsH BWH nY&data/templates/abstract/js/template.js BWcd=,data/templates/abstract/js/jquery.panzoom.js9 BW9[.data/templates/abstract/js/jquery.tools.min.jsõ BWõt*ݶ8data/templates/abstract/js/jquery-ui-1.8.2.custom.min.js( BW( +data/templates/abstract/js/jquery.cookie.js BW+B.data/templates/abstract/js/jquery-1.4.2.min.js BW4'data/templates/abstract/images/logo.png BW92data/templates/abstract/images/icons/interface.png BWǛL3data/templates/abstract/images/icons/arrow_down.png^ BW^8V/data/templates/abstract/images/icons/method.png BWk;data/templates/abstract/images/icons/visibility_private.pngi BWi 1data/templates/abstract/images/icons/constant.pngW BWWIH`-data/templates/abstract/images/icons/file.gifn BWnG~N/data/templates/abstract/images/icons/folder.gifj BWjZr:data/templates/abstract/images/icons/visibility_public.png{ BW{ /s1data/templates/abstract/images/icons/function.png BWp 4data/templates/abstract/images/icons/arrow_right.pngt BWttF4data/templates/abstract/images/icons/view_source.png[ BW[EQ=data/templates/abstract/images/icons/visibility_protected.png BWm0data/templates/abstract/images/icons/favicon.ico~ BW~+data/templates/abstract/images/icons/ok.pnge BWe "1data/templates/abstract/images/icons/variable.png= BW=&1data/templates/abstract/images/icons/property.pngB BWB{w~.data/templates/abstract/images/icons/class.png BWÅ1data/templates/abstract/images/icons/file-php.png BW .2data/templates/abstract/images/icons/namespace.png BWF/data/templates/abstract/images/icons/search.gif BW>/data/templates/abstract/images/collapse_all.png BWѫ>-data/templates/abstract/images/expand_all.png BWZU)data/templates/abstract/images/search.gif BWYb"data/templates/old-ocean/index.xsl> BW>q%data/templates/old-ocean/template.xmlw BWwg#data/templates/old-ocean/layout.xslg BWg RN"data/templates/old-ocean/class.xsl- BW-Il#data/templates/old-ocean/chrome.xsl BWc4'data/templates/old-ocean/classgraph.xsl BWO#data/templates/old-ocean/search.xsl BW LԐ0data/templates/old-ocean/css/jquery.treeview.css BW ,I(data/templates/old-ocean/css/default.css BW {;Adata/templates/old-ocean/css/black-tie/jquery-ui-1.8.2.custom.cssl{ BWl{WNMdata/templates/old-ocean/css/black-tie/images/ui-bg_glass_40_111111_1x400.png| BW|yZ6Mdata/templates/old-ocean/css/black-tie/images/ui-bg_flat_65_ffffff_40x100.png BWYoIdata/templates/old-ocean/css/black-tie/images/ui-icons_ffcf29_256x240.png BWRJIdata/templates/old-ocean/css/black-tie/images/ui-icons_ffffff_256x240.png BW\Vdata/templates/old-ocean/css/black-tie/images/ui-bg_highlight-soft_50_aaaaaa_1x100.pngf BWfKIdata/templates/old-ocean/css/black-tie/images/ui-icons_4ca300_256x240.png BWKWdata/templates/old-ocean/css/black-tie/images/ui-bg_highlight-hard_100_f9f9f9_1x100.pngV BWVN5Vdata/templates/old-ocean/css/black-tie/images/ui-bg_highlight-hard_40_aaaaaa_1x100.pngd BWd ̶Idata/templates/old-ocean/css/black-tie/images/ui-icons_222222_256x240.png BW7Vdata/templates/old-ocean/css/black-tie/images/ui-bg_diagonals-thick_8_333333_40x40.png BWjRdata/templates/old-ocean/css/black-tie/images/ui-bg_inset-hard_55_ffeb80_1x100.pngq BWq/@Edata/templates/old-ocean/css/black-tie/images/ui-anim_basic_16x16.gif BW{0Rdata/templates/old-ocean/css/black-tie/images/ui-bg_inset-hard_45_cd0a0a_1x100.png{ BW{;oIdata/templates/old-ocean/css/black-tie/images/ui-icons_ededed_256x240.png BWuzIdata/templates/old-ocean/css/black-tie/images/ui-icons_bbbbbb_256x240.png BW ] ҶMdata/templates/old-ocean/css/black-tie/images/ui-bg_glass_55_1c1c1c_1x400.png BWb':data/templates/old-ocean/css/images/treeview-famfamfam.gif BWt36data/templates/old-ocean/css/images/treeview-black.gif BW29data/templates/old-ocean/css/images/treeview-red-line.gifU BWU5,data/templates/old-ocean/css/images/file.gifn BWnG~N;data/templates/old-ocean/css/images/treeview-black-line.gifU BWU3.data/templates/old-ocean/css/images/folder.gifj BWjZr,data/templates/old-ocean/css/images/plus.gifI BWI\M9?data/templates/old-ocean/css/images/treeview-famfamfam-line.gif' BW'[〶=data/templates/old-ocean/css/images/treeview-default-line.gif BW9J3data/templates/old-ocean/css/images/ajax-loader.gifO BWO=s-data/templates/old-ocean/css/images/minus.gifE BWEN:5data/templates/old-ocean/css/images/folder-closed.gifi BWi϶8data/templates/old-ocean/css/images/treeview-default.gif BWk74data/templates/old-ocean/css/images/treeview-red.gif BW& v:data/templates/old-ocean/css/images/treeview-gray-line.gifU BWU:h845data/templates/old-ocean/css/images/treeview-gray.gif BW3!data/templates/old-ocean/file.xsl BW臨!data/templates/old-ocean/menu.xsl- BW-2׶data/templates/old-ocean/README BW$data/templates/old-ocean/markers.xsl7 BW7ζ)data/templates/old-ocean/object-index.xsl BWNӶ*data/templates/old-ocean/parse_markers.xsl BW "Jն.data/templates/old-ocean/js/jquery.treeview.jsH BWH nY/data/templates/old-ocean/js/jquery-1.7.1.min.js BWG.data/templates/old-ocean/js/jquery.splitter.js- BW-U-data/templates/old-ocean/js/jquery.panzoom.js9 BW9[%data/templates/old-ocean/js/SVGPan.js BW@/data/templates/old-ocean/js/jquery.tools.min.jsõ BWõt*ݶ#data/templates/old-ocean/js/menu.js BWEdata/templates/old-ocean/images/icons/visibility_protected.png BWm1data/templates/old-ocean/images/icons/favicon.ico~ BW~,data/templates/old-ocean/images/icons/ok.pnge BWe "2data/templates/old-ocean/images/icons/variable.png= BW=&2data/templates/old-ocean/images/icons/property.pngB BWB{w~/data/templates/old-ocean/images/icons/class.png BWÅ2data/templates/old-ocean/images/icons/file-php.png BW .0data/templates/old-ocean/images/icons/search.gif BW>2data/templates/old-ocean/images/top-background.png BW 83data/templates/old-ocean/images/menu-background.png BWo5data/templates/responsive-twig/graphs/class.html.twig BWaE.data/templates/responsive-twig/index.html.twig BW  o.data/templates/responsive-twig/class.html.twig& BW&WLk@+data/templates/responsive-twig/template.xml BW]P6;data/templates/responsive-twig/base/class.sidebar.html.twigL BWL~4data/templates/responsive-twig/base/macros.html.twig BWb5data/templates/responsive-twig/base/sidebar.html.twig BWK;data/templates/responsive-twig/reports/deprecated.html.twig~ BW~ dZ[7data/templates/responsive-twig/reports/errors.html.twigs BWs ͂a8data/templates/responsive-twig/reports/markers.html.twig BW }0data/templates/responsive-twig/package.html.twig BWBF/data/templates/responsive-twig/method.html.twig BW09G/data/templates/responsive-twig/layout.html.twig BWH2data/templates/responsive-twig/namespace.html.twig BW%ܶ*data/templates/responsive/graphs/class.xsl BWko#data/templates/responsive/index.xsl BWvOض)data/templates/responsive/search.json.xsl BW]\G(data/templates/responsive/namespaces.xsl BWh>&data/templates/responsive/template.xmlR BWR$$data/templates/responsive/layout.xsl, BW, B#data/templates/responsive/class.xsls BWsއ>80data/templates/responsive/reports/deprecated.xsl BWĒ,data/templates/responsive/reports/errors.xsl  BW x}:-data/templates/responsive/reports/markers.xsln BWn{g/data/templates/responsive/css/bootstrap.min.cssU BWU1:data/templates/responsive/css/bootstrap-responsive.min.css BWp+data/templates/responsive/css/bootstrap.cssZ> BWZ>I~6data/templates/responsive/css/bootstrap-responsive.css/) BW/)6*data/templates/responsive/css/template.css5% BW5%Gh*data/templates/responsive/css/prettify.css BWlԶ0data/templates/responsive/css/jquery.iviewer.css3 BW3Զ-data/templates/responsive/elements/common.xsl3# BW3# 0data/templates/responsive/elements/namespace.xsl BW ?.data/templates/responsive/elements/package.xslc BWcp,data/templates/responsive/elements/class.xsl& BW&-J/data/templates/responsive/elements/property.xsl BW%/data/templates/responsive/elements/function.xsl BWѝd/data/templates/responsive/elements/constant.xslo BWo)`2data/templates/responsive/img/apple-touch-icon.png BW u6data/templates/responsive/img/glyphicons-halflings.png BW!˶1data/templates/responsive/img/icons/interface.png BWWG2data/templates/responsive/img/icons/arrow_down.png^ BW^8V.data/templates/responsive/img/icons/method.pngy BWy?`0Ƕ:data/templates/responsive/img/icons/visibility_private.pngi BWi 0data/templates/responsive/img/icons/constant.png BW0A׶,data/templates/responsive/img/icons/file.gifn BWnG~N3data/templates/responsive/img/icons/icon-th-big.pngj BWjs̶.data/templates/responsive/img/icons/folder.gifj BWjZr9data/templates/responsive/img/icons/visibility_public.png{ BW{ /s0data/templates/responsive/img/icons/function.pngR BWRK+H5data/templates/responsive/img/icons/icon_template.svgX BWX /3data/templates/responsive/img/icons/arrow_right.pngt BWttF3data/templates/responsive/img/icons/view_source.png[ BW[EQ<data/templates/responsive/img/icons/icon-folder-open-big.png BW<data/templates/responsive/img/icons/visibility_protected.png BWm/data/templates/responsive/img/icons/favicon.ico~ BW~*data/templates/responsive/img/icons/ok.pnge BWe "0data/templates/responsive/img/icons/variable.png= BW=&0data/templates/responsive/img/icons/property.pngh BWh-data/templates/responsive/img/icons/class.png BWJX0data/templates/responsive/img/icons/file-php.png BW ..data/templates/responsive/img/icons/search.gif BW>:data/templates/responsive/img/apple-touch-icon-114x114.pngn BWnl<data/templates/responsive/img/glyphicons-halflings-white.png BW2zǶ;data/templates/responsive/img/iviewer/iviewer.zoom_zero.pngC BWC<data/templates/responsive/img/iviewer/iviewer.zoom_zero2.gifb BWbL7;data/templates/responsive/img/iviewer/iviewer.zoom_out2.gifE BWEt=data/templates/responsive/img/iviewer/iviewer.rotate_left.png BWtm.data/templates/responsive/img/iviewer/grab.cur~ BW~'2:data/templates/responsive/img/iviewer/iviewer.zoom_in2.gifZ BWZ*.data/templates/responsive/img/iviewer/hand.cur~ BW~hګ:data/templates/responsive/img/iviewer/iviewer.zoom_fit.png BW2ж9data/templates/responsive/img/iviewer/iviewer.zoom_in.png BWMז>data/templates/responsive/img/iviewer/iviewer.rotate_right.png BW-Ģ϶:data/templates/responsive/img/iviewer/iviewer.zoom_out.png BW^;data/templates/responsive/img/iviewer/iviewer.zoom_fit2.gif_ BW_& )data/templates/responsive/img/favicon.ico~ BW~\W8data/templates/responsive/img/apple-touch-icon-72x72.png1 BW1C(data/templates/responsive/img/loader.gifv BWv z&data/templates/responsive/packages.xsl BWE=#data/templates/responsive/README.mdl BWl 6/data/templates/responsive/js/jquery.xml2json.jsS BWS-data/templates/responsive/js/bootstrap.min.jsP BWP@h}-/data/templates/responsive/js/jquery.treeview.jsH BWH nY0data/templates/responsive/js/prettify/lang-ml.jsQ BWQS3data/templates/responsive/js/prettify/lang-proto.js. BW.2data/templates/responsive/js/prettify/lang-yaml.js BW,I0data/templates/responsive/js/prettify/lang-xq.jsZ BWZċO1data/templates/responsive/js/prettify/lang-lua.js( BW(ʥҥ1data/templates/responsive/js/prettify/lang-tex.js BWCٶ2data/templates/responsive/js/prettify/lang-lisp.js BW9׶2data/templates/responsive/js/prettify/lang-wiki.js BW5data/templates/responsive/js/prettify/prettify.min.js@5 BW@5;J0data/templates/responsive/js/prettify/lang-vb.js BW.+4data/templates/responsive/js/prettify/lang-apollo.js BWE0data/templates/responsive/js/prettify/lang-hs.js9 BW9uk3V2data/templates/responsive/js/prettify/lang-vhdl.js BWն3data/templates/responsive/js/prettify/lang-scala.js BW(/data/templates/responsive/js/prettify/lang-n.jsx BWxV7e1data/templates/responsive/js/prettify/lang-css.js] BW],z0data/templates/responsive/js/prettify/lang-go.js BWZO1data/templates/responsive/js/prettify/lang-clj.js BWޤ1data/templates/responsive/js/prettify/lang-sql.js BW7h0data/templates/responsive/js/jquery-1.7.1.min.js BWG.data/templates/responsive/js/jquery.iviewer.js: BW:`YĶ)data/templates/responsive/js/bootstrap.js# BW#-#3(data/templates/responsive/js/template.js& BW& 2data/templates/responsive/js/jquery.iviewer.min.jsR= BWR=9/data/templates/responsive/js/jquery.splitter.js- BW-U.data/templates/responsive/js/jquery.panzoom.js9 BW9[&data/templates/responsive/js/SVGPan.js BW@0data/templates/responsive/js/jquery.tools.min.jsõ BWõt*ݶ$data/templates/responsive/js/menu.js BWE BW>ͨEdata/templates/responsive/js/jqplot/plugins/jqplot.barRenderer.min.jsn4 BWn4Idata/templates/responsive/js/jqplot/plugins/jqplot.logAxisRenderer.min.js BWE91data/templates/responsive/js/jqplot/copyright.txt BW!@$/data/templates/responsive/js/jqplot/gpl-2.0.txt; BW;^/data/templates/responsive/js/jqplot/changes.txtT BWT5data/templates/responsive/js/jquery.mousewheel.min.jsh BWh7!x0data/templates/responsive/js/jquery-1.4.2.min.js BW4$data/templates/responsive/graph.html BW2/ data/templates/xml/template.xmlb BWbˠdata/templates/xml/README.mdV BWVƙdata/templates/zend/index.xsl BW _z#data/templates/zend/page_header.xsl BWUY data/templates/zend/template.xml BW ^+data/templates/zend/css/jquery.treeview.css BW!b"data/templates/zend/css/manual.css BW(]h$data/templates/zend/css/template.cssp BWpM<data/templates/zend/css/black-tie/jquery-ui-1.8.2.custom.cssl{ BWl{WNHdata/templates/zend/css/black-tie/images/ui-bg_glass_40_111111_1x400.png| BW|yZ6Hdata/templates/zend/css/black-tie/images/ui-bg_flat_65_ffffff_40x100.png BWYoDdata/templates/zend/css/black-tie/images/ui-icons_ffcf29_256x240.png BWRJDdata/templates/zend/css/black-tie/images/ui-icons_ffffff_256x240.png BW\Qdata/templates/zend/css/black-tie/images/ui-bg_highlight-soft_50_aaaaaa_1x100.pngf BWfKDdata/templates/zend/css/black-tie/images/ui-icons_4ca300_256x240.png BWKRdata/templates/zend/css/black-tie/images/ui-bg_highlight-hard_100_f9f9f9_1x100.pngV BWVN5Qdata/templates/zend/css/black-tie/images/ui-bg_highlight-hard_40_aaaaaa_1x100.pngd BWd ̶Ddata/templates/zend/css/black-tie/images/ui-icons_222222_256x240.png BW7Qdata/templates/zend/css/black-tie/images/ui-bg_diagonals-thick_8_333333_40x40.png BWjMdata/templates/zend/css/black-tie/images/ui-bg_inset-hard_55_ffeb80_1x100.pngq BWq/@@data/templates/zend/css/black-tie/images/ui-anim_basic_16x16.gif BW{0Mdata/templates/zend/css/black-tie/images/ui-bg_inset-hard_45_cd0a0a_1x100.png{ BW{;oDdata/templates/zend/css/black-tie/images/ui-icons_ededed_256x240.png BWuzDdata/templates/zend/css/black-tie/images/ui-icons_bbbbbb_256x240.png BW ] ҶHdata/templates/zend/css/black-tie/images/ui-bg_glass_55_1c1c1c_1x400.png BWb':data/templates/zend/css/phpdoc/images/icons/chart15x12.png} BW} ];data/templates/zend/css/phpdoc/images/icons/reports9x12.png- BW-data/templates/zend/READMEU BWUQ"data/templates/zend/js/template.js BWcd=)data/templates/zend/js/jquery.splitter.js- BW-U&data/templates/zend/images/bkg_top.gif9 BW9(Ӷ)data/templates/zend/images/logo_small.gifJ BWJ 0.data/templates/zend/images/behind-the-site.gif BW<%data/templates/new-black/template.xml BW =[(data/templates/new-black/search/ajax.xslw BWw}@*data/templates/new-black/search/simple.xsl BW Y+0data/templates/new-black/css/jquery.treeview.css BW!b*data/templates/new-black/css/jquery-ui.css BWpg|+data/templates/new-black/css/navigation.css@ BW@(data/templates/new-black/css/default.css BWU<)data/templates/new-black/css/template.css BW?data/templates/new-black/css/phpdoc/jquery-ui-1.8.16.custom.cssJ BWJy>Sdata/templates/new-black/css/phpdoc/images/ui-bg_highlight-hard_40_232325_1x100.pngw BWw{3Fdata/templates/new-black/css/phpdoc/images/ui-icons_ffcf29_256x240.png BW&޶Sdata/templates/new-black/css/phpdoc/images/ui-bg_highlight-hard_65_232325_1x100.png{ BW{LশFdata/templates/new-black/css/phpdoc/images/ui-icons_ffffff_256x240.png BW\Sdata/templates/new-black/css/phpdoc/images/ui-bg_highlight-soft_40_aaaaaa_1x100.pngm BWm8Sdata/templates/new-black/css/phpdoc/images/ui-bg_highlight-soft_50_aaaaaa_1x100.pngf BWfK?data/templates/new-black/css/phpdoc/images/icons/chart15x12.png} BW} ]=data/templates/new-black/css/phpdoc/images/icons/packages.png BW /<data/templates/new-black/css/phpdoc/images/icons/reports.png BW@@data/templates/new-black/css/phpdoc/images/icons/reports9x12.png- BW-:data/templates/new-black/css/phpdoc/images/icons/chart.png- BW- #s>data/templates/new-black/css/phpdoc/images/icons/dashboard.png BW :data/templates/new-black/css/phpdoc/images/icons/files.pngO BWO Aw7?data/templates/new-black/css/phpdoc/images/icons/namespaces.png BW 9!9data/templates/new-black/css/phpdoc/images/icons/book.png BW yIhFdata/templates/new-black/css/phpdoc/images/ui-icons_4ca300_256x240.png BWKTdata/templates/new-black/css/phpdoc/images/ui-bg_highlight-hard_100_f9f9f9_1x100.pngV BWVN5Ldata/templates/new-black/css/phpdoc/images/ui-bg_hexagon_15_232325_12x10.png BW^QFdata/templates/new-black/css/phpdoc/images/ui-icons_222222_256x240.png BW7Odata/templates/new-black/css/phpdoc/images/ui-bg_inset-hard_55_ffeb80_1x100.pngq BWq/@Odata/templates/new-black/css/phpdoc/images/ui-bg_inset-hard_45_cd0a0a_1x100.png{ BW{;oFdata/templates/new-black/css/phpdoc/images/ui-icons_ededed_256x240.png BW<Fdata/templates/new-black/css/phpdoc/images/ui-icons_bbbbbb_256x240.png BW ] ҶJdata/templates/new-black/css/phpdoc/images/ui-bg_glass_55_1c1c1c_1x400.png BW)ζ,data/templates/new-black/css/api-content.css BWD<ζ:data/templates/new-black/css/images/treeview-famfamfam.gif BWt36data/templates/new-black/css/images/treeview-black.gif BW29data/templates/new-black/css/images/treeview-red-line.gifU BWU5,data/templates/new-black/css/images/file.gifn BWnG~N;data/templates/new-black/css/images/treeview-black-line.gifU BWU3.data/templates/new-black/css/images/folder.gifj BWjZr,data/templates/new-black/css/images/plus.gifI BWI\M9?data/templates/new-black/css/images/treeview-famfamfam-line.gif' BW'[〶=data/templates/new-black/css/images/treeview-default-line.gif BW9J3data/templates/new-black/css/images/ajax-loader.gifO BWO=s-data/templates/new-black/css/images/minus.gifE BWEN:5data/templates/new-black/css/images/folder-closed.gifi BWi϶8data/templates/new-black/css/images/treeview-default.gif BWk74data/templates/new-black/css/images/treeview-red.gif BW& v:data/templates/new-black/css/images/treeview-gray-line.gifU BWU:h845data/templates/new-black/css/images/treeview-gray.gif BW3.data/templates/new-black/css/images/search.gif BWYb$data/templates/new-black/sidebar.xsl BWU"data/templates/new-black/README.md BW'data/templates/new-black/js/template.js BW /0&data/templates/new-black/js/sidebar.js BW(data/templates/new-black/ajax_search.php BWqdŶ+data/templates/clean/graphs/class.html.twig BWjo$data/templates/clean/class.html.twig? BW? Ĉ"data/templates/clean/htaccess.dist BWsc !data/templates/clean/template.xml BW i$)data/templates/clean/file.source.txt.twig BWIf`#data/templates/clean/file.html.twigY BWYɲֶ1data/templates/clean/reports/deprecated.html.twig BW -data/templates/clean/reports/errors.html.twig BW .data/templates/clean/reports/markers.html.twig BW 1%data/templates/clean/layout.html.twigO BWO DtR%data/templates/clean/css/template.css! BW!5=+data/templates/clean/css/jquery.iviewer.css  BW ,~be=data/templates/clean/css/phpdocumentor-clean-icons/lte-ie7.js BW;O;>data/templates/clean/css/phpdocumentor-clean-icons/Read Me.txtV BWVo Vdata/templates/clean/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.ttf  BW @fVdata/templates/clean/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.svgN BWN=Vdata/templates/clean/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.eot BW ˲Wdata/templates/clean/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.woff( BW(Zdata/templates/clean/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.dev.svg BW٩Ո<data/templates/clean/css/phpdocumentor-clean-icons/style.css? BW?DE<data/templates/clean/css/bootstrap-combined.no-icons.min.css2 BW26"data/templates/clean/css/prism.css BW Cy-data/templates/clean/css/font-awesome.min.cssDV BWDV (data/templates/clean/namespace.html.twigx BWx,$(data/templates/clean/interface.html.twig( BW(:data/templates/clean/elements/namespaces.sidebar.html.twig BWT0data/templates/clean/elements/constant.html.twig_ BW_ XR.data/templates/clean/elements/method.html.twigr BWrHb0data/templates/clean/elements/property.html.twig BW X$~(data/templates/clean/js/bootstrap.min.jsTp BWTpL[z,data/templates/clean/js/jquery-1.11.0.min.js}x BW}x*)data/templates/clean/js/jquery.iviewer.js9 BW91data/templates/clean/js/jquery.dotdotdot-1.5.9.js* BW* ,data/templates/clean/js/jquery.mousewheel.js BWR-data/templates/clean/js/jquery.iviewer.min.jsCF BWCFvb5data/templates/clean/js/jquery.dotdotdot-1.5.9.min.js BW"$ data/templates/clean/js/html5.js} BW} J9$data/templates/clean/js/prism.min.js. BW./data/templates/clean/js/jquery.smooth-scroll.js9 BW9c^2data/templates/clean/js/ui/1.10.4/jquery-ui.min.js| BW|q2data/templates/clean/font/fontawesome-webfont.woff0G BW0GDֶ1data/templates/clean/font/fontawesome-webfont.eot BW * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex; use Symfony\Component\Finder\Finder; use Symfony\Component\Process\Process; /** * The Compiler class compiles the Cilex framework. * * This is an adapted version of the Silex\Compiler class. * * @author Fabien Potencier * @author Mike van Riel */ class Compiler { protected $version; /** * Compiles the Cilex source code into one single Phar file. * * @param string $pharFile Name of the output Phar file */ public function compile($pharFile = 'cilex.phar') { if (file_exists($pharFile)) { unlink($pharFile); } $process = new Process('git log --pretty="%h %ci" -n1 HEAD'); if ($process->run() > 0) { throw new \RuntimeException('The git binary cannot be found.'); } $this->version = trim($process->getOutput()); $phar = new \Phar($pharFile, 0, 'cilex.phar'); $phar->setSignatureAlgorithm(\Phar::SHA1); $phar->startBuffering(); $finder = new Finder(); $finder->files() ->ignoreVCS(true) ->name('*.php') ->notName('Compiler.php') ->in(__DIR__.'/..') ->in(__DIR__.'/../../vendor/pimple/pimple/lib') ->in(__DIR__.'/../../vendor/cilex/console-service-provider') ->in(__DIR__.'/../../vendor/symfony/console/Symfony/Component/Console'); foreach ($finder as $file) { $this->addFile($phar, $file); } $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../LICENSE'), false); $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/autoload.php')); $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/ClassLoader.php')); $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_real.php')); $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_namespaces.php')); $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_classmap.php')); // Stubs $phar->setStub($this->getStub()); $phar->stopBuffering(); // $phar->compressFiles(\Phar::GZ); unset($phar); } protected function addFile(\Phar $phar, \splFileInfo $file, $strip = true) { $path = str_replace(dirname(dirname(__DIR__)).DIRECTORY_SEPARATOR, '', $file->getRealPath()); $content = file_get_contents($file); if ($strip) { $content = self::stripWhitespace($content); } $content = str_replace('v2.9.0', $this->version, $content); $phar->addFromString($path, $content); } protected function getStub() { return <<<'EOF' * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ Phar::mapPhar('cilex.phar'); require_once 'phar://cilex.phar/vendor/autoload.php'; if ('cli' === php_sapi_name() && basename(__FILE__) === basename($_SERVER['argv'][0]) && isset($_SERVER['argv'][1])) { switch ($_SERVER['argv'][1]) { case 'update': $remoteFilename = 'http://cilex.github.com/get/cilex.phar'; $localFilename = __DIR__.'/cilex.phar'; file_put_contents($localFilename, file_get_contents($remoteFilename)); break; case 'check': $latest = trim(file_get_contents('http://cilex.github.com/get/version')); if ($latest != Cilex\Application::VERSION) { printf("A newer Cilex version is available (%s).\n", $latest); } else { print("You are using the latest Cilex version.\n"); } break; case 'version': printf("Cilex version %s\n", Cilex\Application::VERSION); break; default: printf("Unknown command '%s' (available commands: version, check, and update).\n", $_SERVER['argv'][1]); } exit(0); } __HALT_COMPILER(); EOF; } /** * Removes whitespace from a PHP source string while preserving line numbers. * * Based on Kernel::stripComments(), but keeps line numbers intact. * * @param string $source A PHP string * * @return string The PHP string with the whitespace removed */ public static function stripWhitespace($source) { if (!function_exists('token_get_all')) { return $source; } $output = ''; foreach (token_get_all($source) as $token) { if (is_string($token)) { $output .= $token; } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) { $output .= str_repeat("\n", substr_count($token[1], "\n")); } elseif (T_WHITESPACE === $token[0]) { // reduce wide spaces $whitespace = preg_replace('{[ \t]+}', ' ', $token[1]); // normalize newlines to \n $whitespace = preg_replace('{(?:\r\n|\r|\n)}', "\n", $whitespace); // trim leading spaces $whitespace = preg_replace('{\n +}', "\n", $whitespace); $output .= $whitespace; } else { $output .= $token[1]; } } return $output; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex; /** * Interface that must implement all Cilex service providers. * * @author Mike van Riel */ interface ServiceProviderInterface { /** * Registers services on the given app. * * @param Application $app An Application instance */ public function register(Application $app); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Provider; use Monolog\Logger; use Monolog\Handler\StreamHandler; use Cilex\Application; use Cilex\ServiceProviderInterface; /** * Monolog Provider. * * This class is an adaptation of the Silex MonologServiceProvider written by * Fabien Potencier. * * @author Fabien Potencier * @author Mike van Riel */ class MonologServiceProvider implements ServiceProviderInterface { public function register(Application $app) { $app['monolog'] = $app->share( function () use ($app) { $log = new Logger(isset($app['monolog.name']) ? $app['monolog.name'] : 'myapp'); $app['monolog.configure']($log); return $log; } ); $app['monolog.configure'] = $app->protect( function ($log) use ($app) { $log->pushHandler($app['monolog.handler']); } ); $app['monolog.handler'] = function () use ($app) { return new StreamHandler($app['monolog.logfile'], $app['monolog.level']); }; if (!isset($app['monolog.level'])) { $app['monolog.level'] = function () { return Logger::DEBUG; }; } if (isset($app['monolog.class_path'])) { $app['autoloader']->registerNamespace('Monolog', $app['monolog.class_path']); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Provider; use Cilex\Application; use Cilex\ServiceProviderInterface; use Symfony\Component\Yaml; class ConfigServiceProvider implements ServiceProviderInterface { public function register(Application $app) { $app['config'] = $app->share( function () use ($app) { if (!file_exists($app['config.path'])) { throw new \InvalidArgumentException( $app['config.path'] . ' is not a valid path to the ' .'configuration' ); } $fullpath = explode('.', $app['config.path']); switch (strtolower(end($fullpath))) { case 'php': $result = include($app['config.path']); break; case 'yml': $parser = new Yaml\Parser(); $result = new \ArrayObject( $parser->parse(file_get_contents($app['config.path'])) ); break; case 'xml': $result = simplexml_load_file($app['config.path']); break; case 'json': $result = json_decode(file_get_contents($app['config.path'])); if (null == $result) { throw new \InvalidArgumentException( 'Unable to decode the configuration file: ' . $app['config.path'] ); } break; default: throw new \InvalidArgumentException( 'Unable to load configuration; the provided file extension was not recognized. ' .'Only yml, xml or json allowed' ); break; } return $result; } ); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Provider; use Cilex\Application; use Cilex\ServiceProviderInterface; use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Configuration; use Doctrine\Common\EventManager; /** * Doctrine DBAL Provider. * * This Service Provider is an adaptation of the DoctrineServiceProvider for * Silex written by Fabien Potencier. * * @author Fabien Potencier * @author Mike van Riel */ class DoctrineServiceProvider implements ServiceProviderInterface { public function register(Application $app) { $app['db.default_options'] = array( 'driver' => 'pdo_mysql', 'dbname' => null, 'host' => 'localhost', 'user' => 'root', 'password' => null, ); $app['dbs.options.initializer'] = $app->protect( function () use ($app) { static $initialized = false; if ($initialized) { return; } $initialized = true; if (!isset($app['dbs.options'])) { $app['dbs.options'] = array('default' => isset($app['db.options']) ? $app['db.options'] : array()); } $tmp = $app['dbs.options']; foreach ($tmp as $name => &$options) { $options = array_replace($app['db.default_options'], $options); if (!isset($app['dbs.default'])) { $app['dbs.default'] = $name; } } $app['dbs.options'] = $tmp; } ); $app['dbs'] = $app->share( function () use ($app) { $app['dbs.options.initializer'](); $dbs = new \Pimple(); foreach ($app['dbs.options'] as $name => $options) { if ($app['dbs.default'] === $name) { // we use shortcuts here in case the default has been overriden $config = $app['db.config']; $manager = $app['db.event_manager']; } else { $config = $app['dbs.config'][$name]; $manager = $app['dbs.event_manager'][$name]; } $dbs[$name] = DriverManager::getConnection($options, $config, $manager); } return $dbs; } ); $app['dbs.config'] = $app->share( function () use ($app) { $app['dbs.options.initializer'](); $configs = new \Pimple(); foreach ($app['dbs.options'] as $name => $options) { $configs[$name] = new Configuration(); } return $configs; } ); $app['dbs.event_manager'] = $app->share( function () use ($app) { $app['dbs.options.initializer'](); $managers = new \Pimple(); foreach ($app['dbs.options'] as $name => $options) { $managers[$name] = new EventManager(); } return $managers; } ); // shortcuts for the "first" DB $app['db'] = $app->share( function () use ($app) { $dbs = $app['dbs']; return $dbs[$app['dbs.default']]; } ); $app['db.config'] = $app->share( function () use ($app) { $dbs = $app['dbs.config']; return $dbs[$app['dbs.default']]; } ); $app['db.event_manager'] = $app->share( function () use ($app) { $dbs = $app['dbs.event_manager']; return $dbs[$app['dbs.default']]; } ); if (isset($app['db.dbal.class_path'])) { $app['autoloader']->registerNamespace('Doctrine\\DBAL', $app['db.dbal.class_path']); } if (isset($app['db.common.class_path'])) { $app['autoloader']->registerNamespace('Doctrine\\Common', $app['db.common.class_path']); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Provider; use Cilex\Application; use Cilex\ServiceProviderInterface; use Symfony\Component\Validator\Validator; use Symfony\Component\Validator\Mapping\ClassMetadataFactory; use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader; use Symfony\Component\Validator\ConstraintValidatorFactory; use Symfony\Component\Validator\DefaultTranslator; /** * Symfony Validator component Provider. * * This class is an adaptation of the Silex MonologServiceProvider written by * Fabien Potencier. * * @author Fabien Potencier * @author Mike van Riel */ class ValidatorServiceProvider implements ServiceProviderInterface { public function register(Application $app) { $app['validator'] = $app->share( function () use ($app) { return new Validator( $app['validator.mapping.class_metadata_factory'], $app['validator.validator_factory'], $app['validator.default_translator'] ); } ); $app['validator.mapping.class_metadata_factory'] = $app->share( function () use ($app) { return new ClassMetadataFactory(new StaticMethodLoader()); } ); $app['validator.validator_factory'] = $app->share( function () { return new ConstraintValidatorFactory(); } ); $app['validator.default_translator'] = $app->share( function () { if (!class_exists('Symfony\\Component\\Validator\\DefaultTranslator')){ return array(); } return new DefaultTranslator(); } ); if (isset($app['validator.class_path'])) { $app['autoloader']->registerNamespace('Symfony\\Component\\Validator', $app['validator.class_path']); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Example command for testing purposes. */ class GreetCommand extends Command { protected function configure() { $this ->setName('demo:greet') ->setDescription('Greet someone') ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?') ->addOption('yell', null, InputOption::VALUE_NONE, 'If set, the task will yell in uppercase letters'); } protected function execute(InputInterface $input, OutputInterface $output) { $text = 'Hello'; $name = $input->getArgument('name'); if ($name) { $text .= ' '.$name; } if ($input->getOption('yell')) { $text = strtoupper($text); } $output->writeln($text); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Command\Command as BaseCommand; /** * Example command for testing purposes. */ class DemoInfoCommand extends BaseCommand { protected function configure() { $this ->setName('demo:info') ->setDescription('Get Application Information'); } protected function execute(InputInterface $input, OutputInterface $output) { // This is a contrived example to show accessing services // from the container without needing the command itself // to extend from anything but Symfony Console's base Command. $app = $this->getApplication()->getService('console'); $output->writeln('Name: ' . $app->getName()); $output->writeln('Version: ' . $app->getVersion()); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Command; use \Symfony\Component\Console; /** * Base class for Cilex commands. * * @author Mike van Riel * * @api */ abstract class Command extends Console\Command\Command { /** * Returns the application container. * * @return \Cilex\Application */ public function getContainer() { return $this->getApplication()->getContainer(); } /** * Returns a service contained in the application container or null if none * is found with that name. * * This is a convenience method used to retrieve an element from the * Application container without having to assign the results of the * getContainer() method in every call. * * @param string $name Name of the service * * @see self::getContainer() * * @api * * @return \stdClass|null */ public function getService($name) { return $this->getApplication()->getService($name); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex; use \Symfony\Component\Console; use \Cilex\Provider\Console\ConsoleServiceProvider; /** * The Cilex framework class. * * @author Mike van Riel * * @api */ class Application extends \Pimple { /** * Version number for Cilex */ const VERSION = '1.0.0'; /** * Registers the autoloader and necessary components. * * @param string $name Name for this application. * @param string|null $version Version number for this application. */ public function __construct($name, $version = null, array $values = array()) { parent::__construct(); $consoleConfig = array('console.name' => $name); if (null !== $version) { $consoleConfig['console.version'] = $version; } $this->register(new ConsoleServiceProvider(), $consoleConfig); foreach ($values as $key => $value) { $this[$key] = $value; } } /** * Executes this application. * * @param bool $interactive runs in an interactive shell if true. * * @return void */ public function run($interactive = false) { $app = $this['console']; if ($interactive) { $app = new Console\Shell($app); } $app->run(); } /** * Adds a command object. * * If a command with the same name already exists, it will be overridden. * * @param \Cilex\Command\Command $command A Command object * * @api * * @return void */ public function command(Console\Command\Command $command) { $this['console']->add($command); } /** * Registers a service provider. * * @param \Cilex\ServiceProviderInterface|\Silex\ServiceProviderInterface $provider * A ServiceProviderInterface instance * @param mixed[] $values * An array of values that customizes the provider * * @return void */ public function register($provider, array $values = array()) { if ((!$provider instanceof \Cilex\ServiceProviderInterface) && (!$provider instanceof \Silex\ServiceProviderInterface) ) { throw new \InvalidArgumentException( 'Extensions should implement either Cilex or Silex\' ServiceProviderInterface' ); } $provider->register($this); foreach ($values as $key => $value) { $this[$key] = $value; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Provider\Console; use Symfony\Component\Console\Application; /** * Cilex Pimple Console Application * * @author Beau Simensen */ class ContainerAwareApplication extends Application { /** @var \Pimple */ private $container; /** * Constructor * * @param string $name The name of the application * @param string $version The version of the application */ public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') { parent::__construct($name, $version); } /** * Sets a container instance onto this application. * * @param \Pimple $container * * @return void */ public function setContainer(\Pimple $container) { $this->container = $container; } /** * Get the Container. * * @return \Pimple */ public function getContainer() { return $this->container; } /** * Returns a service contained in the application container or null if none is found with that name. * * This is a convenience method used to retrieve an element from the Application container without having to assign * the results of the getContainer() method in every call. * * @param string $name Name of the service. * * @see self::getContainer() * * @api * * @return mixed|null */ public function getService($name) { return isset($this->container[$name]) ? $this->container[$name] : null; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Provider\Console; use Cilex\Application; use Cilex\ServiceProviderInterface; /** * Cilex Console Service Provider * * @author Beau Simensen */ class ConsoleServiceProvider implements ServiceProviderInterface { /** * {@inheritdoc} */ public function register(Application $app) { $serviceProvider = new BaseConsoleServiceProvider(); $serviceProvider->register($app); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Provider\Console\Adapter\Silex; use Cilex\Provider\Console\BaseConsoleServiceProvider; use Silex\Application; use Silex\ServiceProviderInterface; /** * Silex Console Service Provider adapter * * @author Beau Simensen */ class ConsoleServiceProvider implements ServiceProviderInterface { /** * {@inheritdoc} */ public function boot(Application $app) { } /** * {@inheritdoc} */ public function register(Application $app) { $serviceProvider = new BaseConsoleServiceProvider; $serviceProvider->register($app); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Cilex\Provider\Console; /** * Pimple Console Service Provider * * @author Beau Simensen */ class BaseConsoleServiceProvider { /** * {@inheritdoc} */ public function register(\Pimple $container) { foreach ($this->getDefaults() as $key => $value) { if (!isset($container[$key])) { $container[$key] = $value; } } $container['console'] = $container->share(function() use ($container) { $class = $container['console.class']; $instance = new $class( isset($container['console.name']) ? $container['console.name'] : '', isset($container['console.version']) ? $container['console.version'] : null ); if ($instance instanceof ContainerAwareApplication) { $instance->setContainer($container); } return $instance; }); } protected function getDefaults() { return array( 'console.name' => 'Cilex Application', 'console.class' => 'Cilex\Provider\Console\ContainerAwareApplication', ); } } * Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Autoload; /** * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. * * $loader = new \Composer\Autoload\ClassLoader(); * * // register classes with namespaces * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * // activate the autoloader * $loader->register(); * * // to enable searching the include path (eg. for PEAR packages) * $loader->setUseIncludePath(true); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * This class is loosely based on the Symfony UniversalClassLoader. * * @author Fabien Potencier * @author Jordi Boggiano * @see http://www.php-fig.org/psr/psr-0/ * @see http://www.php-fig.org/psr/psr-4/ */ class ClassLoader { // PSR-4 private $prefixLengthsPsr4 = array(); private $prefixDirsPsr4 = array(); private $fallbackDirsPsr4 = array(); // PSR-0 private $prefixesPsr0 = array(); private $fallbackDirsPsr0 = array(); private $useIncludePath = false; private $classMap = array(); private $classMapAuthoritative = false; public function getPrefixes() { if (!empty($this->prefixesPsr0)) { return call_user_func_array('array_merge', $this->prefixesPsr0); } return array(); } public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } public function getFallbackDirs() { return $this->fallbackDirsPsr0; } public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } public function getClassMap() { return $this->classMap; } /** * @param array $classMap Class to filename map */ public function addClassMap(array $classMap) { if ($this->classMap) { $this->classMap = array_merge($this->classMap, $classMap); } else { $this->classMap = $classMap; } } /** * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * * @param string $prefix The prefix * @param array|string $paths The PSR-0 root directories * @param bool $prepend Whether to prepend the directories */ public function add($prefix, $paths, $prepend = false) { if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( (array) $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, (array) $paths ); } return; } $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { $this->prefixesPsr0[$first][$prefix] = (array) $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( (array) $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], (array) $paths ); } } /** * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-4 base directories * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException */ public function addPsr4($prefix, $paths, $prepend = false) { if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( (array) $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, (array) $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { // Register directories for a new namespace. $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) { throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; $this->prefixDirsPsr4[$prefix] = (array) $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( (array) $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], (array) $paths ); } } /** * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * * @param string $prefix The prefix * @param array|string $paths The PSR-0 base directories */ public function set($prefix, $paths) { if (!$prefix) { $this->fallbackDirsPsr0 = (array) $paths; } else { $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; } } /** * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException */ public function setPsr4($prefix, $paths) { if (!$prefix) { $this->fallbackDirsPsr4 = (array) $paths; } else { $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) { throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; $this->prefixDirsPsr4[$prefix] = (array) $paths; } } /** * Turns on searching the include path for class files. * * @param bool $useIncludePath */ public function setUseIncludePath($useIncludePath) { $this->useIncludePath = $useIncludePath; } /** * Can be used to check if the autoloader uses the include path to check * for classes. * * @return bool */ public function getUseIncludePath() { return $this->useIncludePath; } /** * Turns off searching the prefix and fallback directories for classes * that have not been registered with the class map. * * @param bool $classMapAuthoritative */ public function setClassMapAuthoritative($classMapAuthoritative) { $this->classMapAuthoritative = $classMapAuthoritative; } /** * Should class lookup fail if not found in the current class map? * * @return bool */ public function isClassMapAuthoritative() { return $this->classMapAuthoritative; } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * @return bool|null True if loaded, null otherwise */ public function loadClass($class) { if ($file = $this->findFile($class)) { includeFile($file); return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|false The path if found, false otherwise */ public function findFile($class) { // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 if ('\\' == $class[0]) { $class = substr($class, 1); } // class map lookup if (isset($this->classMap[$class])) { return $this->classMap[$class]; } if ($this->classMapAuthoritative) { return false; } $file = $this->findFileWithExtension($class, '.php'); // Search for Hack files if we are running on HHVM if ($file === null && defined('HHVM_VERSION')) { $file = $this->findFileWithExtension($class, '.hh'); } if ($file === null) { // Remember that this class does not exist. return $this->classMap[$class] = false; } return $file; } private function findFileWithExtension($class, $ext) { // PSR-4 lookup $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; $first = $class[0]; if (isset($this->prefixLengthsPsr4[$first])) { foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { if (0 === strpos($class, $prefix)) { foreach ($this->prefixDirsPsr4[$prefix] as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { return $file; } } } } } // PSR-4 fallback dirs foreach ($this->fallbackDirsPsr4 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { return $file; } } // PSR-0 lookup if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); } else { // PEAR-like class name $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; } if (isset($this->prefixesPsr0[$first])) { foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { if (0 === strpos($class, $prefix)) { foreach ($dirs as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } } } } // PSR-0 fallback dirs foreach ($this->fallbackDirsPsr0 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { return $file; } } // PSR-0 include paths. if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { return $file; } } } /** * Scope isolated include. * * Prevents access to $this/self from included files. */ function includeFile($file) { include $file; } array($vendorDir . '/zendframework/zend-stdlib/src'), 'Zend\\ServiceManager\\' => array($vendorDir . '/zendframework/zend-servicemanager/src'), 'Zend\\Serializer\\' => array($vendorDir . '/zendframework/zend-serializer/src'), 'Zend\\Math\\' => array($vendorDir . '/zendframework/zend-math/src'), 'Zend\\Json\\' => array($vendorDir . '/zendframework/zend-json/src'), 'Zend\\I18n\\' => array($vendorDir . '/zendframework/zend-i18n/src'), 'Zend\\Filter\\' => array($vendorDir . '/zendframework/zend-filter/src'), 'Zend\\EventManager\\' => array($vendorDir . '/zendframework/zend-eventmanager/src'), 'Zend\\Config\\' => array($vendorDir . '/zendframework/zend-config/src'), 'Zend\\Cache\\' => array($vendorDir . '/zendframework/zend-cache/src'), 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'), 'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'), 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'), ); $vendorDir . '/behat/behat/src/Behat/Behat/ApplicationFactory.php', 'Behat\\Behat\\Context\\Annotation\\AnnotationReader' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Annotation/AnnotationReader.php', 'Behat\\Behat\\Context\\Argument\\ArgumentResolver' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Argument/ArgumentResolver.php', 'Behat\\Behat\\Context\\Context' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Context.php', 'Behat\\Behat\\Context\\ContextClass\\ClassGenerator' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/ContextClass/ClassGenerator.php', 'Behat\\Behat\\Context\\ContextClass\\ClassResolver' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/ContextClass/ClassResolver.php', 'Behat\\Behat\\Context\\ContextClass\\SimpleClassGenerator' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/ContextClass/SimpleClassGenerator.php', 'Behat\\Behat\\Context\\ContextFactory' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/ContextFactory.php', 'Behat\\Behat\\Context\\CustomSnippetAcceptingContext' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/CustomSnippetAcceptingContext.php', 'Behat\\Behat\\Context\\Environment\\ContextEnvironment' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Environment/ContextEnvironment.php', 'Behat\\Behat\\Context\\Environment\\Handler\\ContextEnvironmentHandler' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Environment/Handler/ContextEnvironmentHandler.php', 'Behat\\Behat\\Context\\Environment\\InitializedContextEnvironment' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Environment/InitializedContextEnvironment.php', 'Behat\\Behat\\Context\\Environment\\Reader\\ContextEnvironmentReader' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Environment/Reader/ContextEnvironmentReader.php', 'Behat\\Behat\\Context\\Environment\\UninitializedContextEnvironment' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Environment/UninitializedContextEnvironment.php', 'Behat\\Behat\\Context\\Exception\\ContextException' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Exception/ContextException.php', 'Behat\\Behat\\Context\\Exception\\ContextNotFoundException' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Exception/ContextNotFoundException.php', 'Behat\\Behat\\Context\\Exception\\UnknownTranslationResourceException' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Exception/UnknownTranslationResourceException.php', 'Behat\\Behat\\Context\\Exception\\WrongContextClassException' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Exception/WrongContextClassException.php', 'Behat\\Behat\\Context\\Initializer\\ContextInitializer' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Initializer/ContextInitializer.php', 'Behat\\Behat\\Context\\Reader\\AnnotatedContextReader' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Reader/AnnotatedContextReader.php', 'Behat\\Behat\\Context\\Reader\\ContextReader' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Reader/ContextReader.php', 'Behat\\Behat\\Context\\Reader\\ContextReaderCachedPerContext' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Reader/ContextReaderCachedPerContext.php', 'Behat\\Behat\\Context\\Reader\\ContextReaderCachedPerSuite' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Reader/ContextReaderCachedPerSuite.php', 'Behat\\Behat\\Context\\Reader\\TranslatableContextReader' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Reader/TranslatableContextReader.php', 'Behat\\Behat\\Context\\ServiceContainer\\ContextExtension' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/ServiceContainer/ContextExtension.php', 'Behat\\Behat\\Context\\SnippetAcceptingContext' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/SnippetAcceptingContext.php', 'Behat\\Behat\\Context\\Snippet\\Appender\\ContextSnippetAppender' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Snippet/Appender/ContextSnippetAppender.php', 'Behat\\Behat\\Context\\Snippet\\ContextSnippet' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Snippet/ContextSnippet.php', 'Behat\\Behat\\Context\\Snippet\\Generator\\ContextSnippetGenerator' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextSnippetGenerator.php', 'Behat\\Behat\\Context\\Suite\\Setup\\SuiteWithContextsSetup' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/Suite/Setup/SuiteWithContextsSetup.php', 'Behat\\Behat\\Context\\TranslatableContext' => $vendorDir . '/behat/behat/src/Behat/Behat/Context/TranslatableContext.php', 'Behat\\Behat\\Definition\\Call\\DefinitionCall' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Call/DefinitionCall.php', 'Behat\\Behat\\Definition\\Call\\Given' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Call/Given.php', 'Behat\\Behat\\Definition\\Call\\RuntimeDefinition' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Call/RuntimeDefinition.php', 'Behat\\Behat\\Definition\\Call\\Then' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Call/Then.php', 'Behat\\Behat\\Definition\\Call\\When' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Call/When.php', 'Behat\\Behat\\Definition\\Cli\\AvailableDefinitionsController' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Cli/AvailableDefinitionsController.php', 'Behat\\Behat\\Definition\\Context\\Annotation\\DefinitionAnnotationReader' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Context/Annotation/DefinitionAnnotationReader.php', 'Behat\\Behat\\Definition\\Definition' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Definition.php', 'Behat\\Behat\\Definition\\DefinitionFinder' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/DefinitionFinder.php', 'Behat\\Behat\\Definition\\DefinitionRepository' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/DefinitionRepository.php', 'Behat\\Behat\\Definition\\DefinitionWriter' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/DefinitionWriter.php', 'Behat\\Behat\\Definition\\Exception\\AmbiguousMatchException' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Exception/AmbiguousMatchException.php', 'Behat\\Behat\\Definition\\Exception\\DefinitionException' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Exception/DefinitionException.php', 'Behat\\Behat\\Definition\\Exception\\InvalidPatternException' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Exception/InvalidPatternException.php', 'Behat\\Behat\\Definition\\Exception\\RedundantStepException' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Exception/RedundantStepException.php', 'Behat\\Behat\\Definition\\Exception\\SearchException' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Exception/SearchException.php', 'Behat\\Behat\\Definition\\Exception\\UnknownPatternException' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Exception/UnknownPatternException.php', 'Behat\\Behat\\Definition\\Exception\\UnsupportedPatternTypeException' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Exception/UnsupportedPatternTypeException.php', 'Behat\\Behat\\Definition\\Pattern\\Pattern' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Pattern/Pattern.php', 'Behat\\Behat\\Definition\\Pattern\\PatternTransformer' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Pattern/PatternTransformer.php', 'Behat\\Behat\\Definition\\Pattern\\Policy\\PatternPolicy' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/PatternPolicy.php', 'Behat\\Behat\\Definition\\Pattern\\Policy\\RegexPatternPolicy' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/RegexPatternPolicy.php', 'Behat\\Behat\\Definition\\Pattern\\Policy\\TurnipPatternPolicy' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/TurnipPatternPolicy.php', 'Behat\\Behat\\Definition\\Printer\\ConsoleDefinitionInformationPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionInformationPrinter.php', 'Behat\\Behat\\Definition\\Printer\\ConsoleDefinitionListPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionListPrinter.php', 'Behat\\Behat\\Definition\\Printer\\ConsoleDefinitionPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionPrinter.php', 'Behat\\Behat\\Definition\\Printer\\DefinitionPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Printer/DefinitionPrinter.php', 'Behat\\Behat\\Definition\\SearchResult' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/SearchResult.php', 'Behat\\Behat\\Definition\\Search\\RepositorySearchEngine' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Search/RepositorySearchEngine.php', 'Behat\\Behat\\Definition\\Search\\SearchEngine' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Search/SearchEngine.php', 'Behat\\Behat\\Definition\\ServiceContainer\\DefinitionExtension' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/ServiceContainer/DefinitionExtension.php', 'Behat\\Behat\\Definition\\Translator\\DefinitionTranslator' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Translator/DefinitionTranslator.php', 'Behat\\Behat\\Definition\\Translator\\TranslatedDefinition' => $vendorDir . '/behat/behat/src/Behat/Behat/Definition/Translator/TranslatedDefinition.php', 'Behat\\Behat\\EventDispatcher\\Cli\\StopOnFailureController' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Cli/StopOnFailureController.php', 'Behat\\Behat\\EventDispatcher\\Event\\AfterBackgroundSetup' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterBackgroundSetup.php', 'Behat\\Behat\\EventDispatcher\\Event\\AfterBackgroundTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterBackgroundTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\AfterFeatureSetup' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterFeatureSetup.php', 'Behat\\Behat\\EventDispatcher\\Event\\AfterFeatureTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterFeatureTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\AfterOutlineSetup' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterOutlineSetup.php', 'Behat\\Behat\\EventDispatcher\\Event\\AfterOutlineTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterOutlineTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\AfterScenarioSetup' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterScenarioSetup.php', 'Behat\\Behat\\EventDispatcher\\Event\\AfterScenarioTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterScenarioTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\AfterStepSetup' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterStepSetup.php', 'Behat\\Behat\\EventDispatcher\\Event\\AfterStepTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterStepTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\BackgroundTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BackgroundTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\BeforeBackgroundTeardown' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeBackgroundTeardown.php', 'Behat\\Behat\\EventDispatcher\\Event\\BeforeBackgroundTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeBackgroundTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\BeforeFeatureTeardown' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeFeatureTeardown.php', 'Behat\\Behat\\EventDispatcher\\Event\\BeforeFeatureTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeFeatureTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\BeforeOutlineTeardown' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeOutlineTeardown.php', 'Behat\\Behat\\EventDispatcher\\Event\\BeforeOutlineTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeOutlineTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\BeforeScenarioTeardown' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeScenarioTeardown.php', 'Behat\\Behat\\EventDispatcher\\Event\\BeforeScenarioTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeScenarioTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\BeforeStepTeardown' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeStepTeardown.php', 'Behat\\Behat\\EventDispatcher\\Event\\BeforeStepTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeStepTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\ExampleTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/ExampleTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\FeatureTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/FeatureTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\GherkinNodeTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/GherkinNodeTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\OutlineTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/OutlineTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\ScenarioLikeTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/ScenarioLikeTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\ScenarioTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/ScenarioTested.php', 'Behat\\Behat\\EventDispatcher\\Event\\StepTested' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Event/StepTested.php', 'Behat\\Behat\\EventDispatcher\\ServiceContainer\\EventDispatcherExtension' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/ServiceContainer/EventDispatcherExtension.php', 'Behat\\Behat\\EventDispatcher\\Tester\\EventDispatchingBackgroundTester' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingBackgroundTester.php', 'Behat\\Behat\\EventDispatcher\\Tester\\EventDispatchingFeatureTester' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingFeatureTester.php', 'Behat\\Behat\\EventDispatcher\\Tester\\EventDispatchingOutlineTester' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingOutlineTester.php', 'Behat\\Behat\\EventDispatcher\\Tester\\EventDispatchingScenarioTester' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingScenarioTester.php', 'Behat\\Behat\\EventDispatcher\\Tester\\EventDispatchingStepTester' => $vendorDir . '/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingStepTester.php', 'Behat\\Behat\\Gherkin\\Cli\\FilterController' => $vendorDir . '/behat/behat/src/Behat/Behat/Gherkin/Cli/FilterController.php', 'Behat\\Behat\\Gherkin\\Cli\\SyntaxController' => $vendorDir . '/behat/behat/src/Behat/Behat/Gherkin/Cli/SyntaxController.php', 'Behat\\Behat\\Gherkin\\ServiceContainer\\GherkinExtension' => $vendorDir . '/behat/behat/src/Behat/Behat/Gherkin/ServiceContainer/GherkinExtension.php', 'Behat\\Behat\\Gherkin\\Specification\\LazyFeatureIterator' => $vendorDir . '/behat/behat/src/Behat/Behat/Gherkin/Specification/LazyFeatureIterator.php', 'Behat\\Behat\\Gherkin\\Specification\\Locator\\FilesystemFeatureLocator' => $vendorDir . '/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemFeatureLocator.php', 'Behat\\Behat\\Gherkin\\Specification\\Locator\\FilesystemScenariosListLocator' => $vendorDir . '/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemScenariosListLocator.php', 'Behat\\Behat\\Gherkin\\Suite\\Setup\\SuiteWithPathsSetup' => $vendorDir . '/behat/behat/src/Behat/Behat/Gherkin/Suite/Setup/SuiteWithPathsSetup.php', 'Behat\\Behat\\Hook\\Call\\AfterFeature' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Call/AfterFeature.php', 'Behat\\Behat\\Hook\\Call\\AfterScenario' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Call/AfterScenario.php', 'Behat\\Behat\\Hook\\Call\\AfterStep' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Call/AfterStep.php', 'Behat\\Behat\\Hook\\Call\\BeforeFeature' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Call/BeforeFeature.php', 'Behat\\Behat\\Hook\\Call\\BeforeScenario' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Call/BeforeScenario.php', 'Behat\\Behat\\Hook\\Call\\BeforeStep' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Call/BeforeStep.php', 'Behat\\Behat\\Hook\\Call\\RuntimeFeatureHook' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Call/RuntimeFeatureHook.php', 'Behat\\Behat\\Hook\\Call\\RuntimeScenarioHook' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Call/RuntimeScenarioHook.php', 'Behat\\Behat\\Hook\\Call\\RuntimeStepHook' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Call/RuntimeStepHook.php', 'Behat\\Behat\\Hook\\Context\\Annotation\\HookAnnotationReader' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Context/Annotation/HookAnnotationReader.php', 'Behat\\Behat\\Hook\\Scope\\AfterFeatureScope' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Scope/AfterFeatureScope.php', 'Behat\\Behat\\Hook\\Scope\\AfterScenarioScope' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Scope/AfterScenarioScope.php', 'Behat\\Behat\\Hook\\Scope\\AfterStepScope' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Scope/AfterStepScope.php', 'Behat\\Behat\\Hook\\Scope\\BeforeFeatureScope' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Scope/BeforeFeatureScope.php', 'Behat\\Behat\\Hook\\Scope\\BeforeScenarioScope' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Scope/BeforeScenarioScope.php', 'Behat\\Behat\\Hook\\Scope\\BeforeStepScope' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Scope/BeforeStepScope.php', 'Behat\\Behat\\Hook\\Scope\\FeatureScope' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Scope/FeatureScope.php', 'Behat\\Behat\\Hook\\Scope\\ScenarioScope' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Scope/ScenarioScope.php', 'Behat\\Behat\\Hook\\Scope\\StepScope' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Scope/StepScope.php', 'Behat\\Behat\\Hook\\ServiceContainer\\HookExtension' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/ServiceContainer/HookExtension.php', 'Behat\\Behat\\Hook\\Tester\\HookableFeatureTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Tester/HookableFeatureTester.php', 'Behat\\Behat\\Hook\\Tester\\HookableScenarioTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Tester/HookableScenarioTester.php', 'Behat\\Behat\\Hook\\Tester\\HookableStepTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Hook/Tester/HookableStepTester.php', 'Behat\\Behat\\Output\\Exception\\NodeVisitorNotFoundException' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Exception/NodeVisitorNotFoundException.php', 'Behat\\Behat\\Output\\Node\\EventListener\\AST\\FeatureListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/FeatureListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\AST\\OutlineListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/OutlineListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\AST\\OutlineTableListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/OutlineTableListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\AST\\ScenarioNodeListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/ScenarioNodeListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\AST\\StepListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/StepListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\AST\\SuiteListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/SuiteListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\Flow\\FireOnlySiblingsListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/FireOnlySiblingsListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\Flow\\FirstBackgroundFiresFirstListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/FirstBackgroundFiresFirstListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\Flow\\OnlyFirstBackgroundFiresListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/OnlyFirstBackgroundFiresListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\Statistics\\HookStatsListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/HookStatsListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\Statistics\\ScenarioStatsListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/ScenarioStatsListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\Statistics\\StatisticsListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/StatisticsListener.php', 'Behat\\Behat\\Output\\Node\\EventListener\\Statistics\\StepStatsListener' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/StepStatsListener.php', 'Behat\\Behat\\Output\\Node\\Printer\\CounterPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/CounterPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\ExamplePrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/ExamplePrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\ExampleRowPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/ExampleRowPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\FeaturePrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/FeaturePrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Helper\\ResultToStringConverter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/ResultToStringConverter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Helper\\StepTextPainter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/StepTextPainter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Helper\\WidthCalculator' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/WidthCalculator.php', 'Behat\\Behat\\Output\\Node\\Printer\\ListPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/ListPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\OutlinePrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/OutlinePrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\OutlineTablePrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/OutlineTablePrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettyExamplePrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyExamplePrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettyExampleRowPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyExampleRowPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettyFeaturePrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyFeaturePrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettyOutlinePrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyOutlinePrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettyOutlineTablePrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyOutlineTablePrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettyPathPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyPathPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettyScenarioPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyScenarioPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettySetupPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettySetupPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettySkippedStepPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettySkippedStepPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettyStatisticsPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyStatisticsPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Pretty\\PrettyStepPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyStepPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Progress\\ProgressStatisticsPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Progress/ProgressStatisticsPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\Progress\\ProgressStepPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/Progress/ProgressStepPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\ScenarioPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/ScenarioPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\SetupPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/SetupPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\StatisticsPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/StatisticsPrinter.php', 'Behat\\Behat\\Output\\Node\\Printer\\StepPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Node/Printer/StepPrinter.php', 'Behat\\Behat\\Output\\Printer\\ConsoleOutputPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Printer/ConsoleOutputPrinter.php', 'Behat\\Behat\\Output\\Printer\\Formatter\\ConsoleFormatter' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Printer/Formatter/ConsoleFormatter.php', 'Behat\\Behat\\Output\\ServiceContainer\\Formatter\\PrettyFormatterFactory' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/PrettyFormatterFactory.php', 'Behat\\Behat\\Output\\ServiceContainer\\Formatter\\ProgressFormatterFactory' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/ProgressFormatterFactory.php', 'Behat\\Behat\\Output\\Statistics\\HookStat' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Statistics/HookStat.php', 'Behat\\Behat\\Output\\Statistics\\ScenarioStat' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Statistics/ScenarioStat.php', 'Behat\\Behat\\Output\\Statistics\\Statistics' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Statistics/Statistics.php', 'Behat\\Behat\\Output\\Statistics\\StepStat' => $vendorDir . '/behat/behat/src/Behat/Behat/Output/Statistics/StepStat.php', 'Behat\\Behat\\Snippet\\AggregateSnippet' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/AggregateSnippet.php', 'Behat\\Behat\\Snippet\\Appender\\SnippetAppender' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/Appender/SnippetAppender.php', 'Behat\\Behat\\Snippet\\Cli\\SnippetsController' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/Cli/SnippetsController.php', 'Behat\\Behat\\Snippet\\Exception\\EnvironmentSnippetGenerationException' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/Exception/EnvironmentSnippetGenerationException.php', 'Behat\\Behat\\Snippet\\Exception\\SnippetException' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/Exception/SnippetException.php', 'Behat\\Behat\\Snippet\\Generator\\SnippetGenerator' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/Generator/SnippetGenerator.php', 'Behat\\Behat\\Snippet\\Printer\\ConsoleSnippetPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/Printer/ConsoleSnippetPrinter.php', 'Behat\\Behat\\Snippet\\Printer\\SnippetPrinter' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/Printer/SnippetPrinter.php', 'Behat\\Behat\\Snippet\\ServiceContainer\\SnippetExtension' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/ServiceContainer/SnippetExtension.php', 'Behat\\Behat\\Snippet\\Snippet' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/Snippet.php', 'Behat\\Behat\\Snippet\\SnippetRegistry' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/SnippetRegistry.php', 'Behat\\Behat\\Snippet\\SnippetRepository' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/SnippetRepository.php', 'Behat\\Behat\\Snippet\\SnippetWriter' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/SnippetWriter.php', 'Behat\\Behat\\Snippet\\UndefinedStep' => $vendorDir . '/behat/behat/src/Behat/Behat/Snippet/UndefinedStep.php', 'Behat\\Behat\\Tester\\BackgroundTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/BackgroundTester.php', 'Behat\\Behat\\Tester\\Cli\\RerunController' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Cli/RerunController.php', 'Behat\\Behat\\Tester\\Exception\\FeatureHasNoBackgroundException' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Exception/FeatureHasNoBackgroundException.php', 'Behat\\Behat\\Tester\\Exception\\PendingException' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Exception/PendingException.php', 'Behat\\Behat\\Tester\\Exception\\Stringer\\PendingExceptionStringer' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Exception/Stringer/PendingExceptionStringer.php', 'Behat\\Behat\\Tester\\OutlineTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/OutlineTester.php', 'Behat\\Behat\\Tester\\Result\\DefinedStepResult' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Result/DefinedStepResult.php', 'Behat\\Behat\\Tester\\Result\\ExecutedStepResult' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Result/ExecutedStepResult.php', 'Behat\\Behat\\Tester\\Result\\FailedStepSearchResult' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Result/FailedStepSearchResult.php', 'Behat\\Behat\\Tester\\Result\\SkippedStepResult' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Result/SkippedStepResult.php', 'Behat\\Behat\\Tester\\Result\\StepResult' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Result/StepResult.php', 'Behat\\Behat\\Tester\\Result\\UndefinedStepResult' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Result/UndefinedStepResult.php', 'Behat\\Behat\\Tester\\Runtime\\RuntimeBackgroundTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeBackgroundTester.php', 'Behat\\Behat\\Tester\\Runtime\\RuntimeFeatureTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeFeatureTester.php', 'Behat\\Behat\\Tester\\Runtime\\RuntimeOutlineTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeOutlineTester.php', 'Behat\\Behat\\Tester\\Runtime\\RuntimeScenarioTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeScenarioTester.php', 'Behat\\Behat\\Tester\\Runtime\\RuntimeStepTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeStepTester.php', 'Behat\\Behat\\Tester\\ScenarioTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/ScenarioTester.php', 'Behat\\Behat\\Tester\\ServiceContainer\\TesterExtension' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/ServiceContainer/TesterExtension.php', 'Behat\\Behat\\Tester\\StepContainerTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/StepContainerTester.php', 'Behat\\Behat\\Tester\\StepTester' => $vendorDir . '/behat/behat/src/Behat/Behat/Tester/StepTester.php', 'Behat\\Behat\\Transformation\\Call\\Filter\\DefinitionArgumentsTransformer' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/Call/Filter/DefinitionArgumentsTransformer.php', 'Behat\\Behat\\Transformation\\Call\\RuntimeTransformation' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/Call/RuntimeTransformation.php', 'Behat\\Behat\\Transformation\\Call\\TransformationCall' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/Call/TransformationCall.php', 'Behat\\Behat\\Transformation\\Context\\Annotation\\TransformationAnnotationReader' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/Context/Annotation/TransformationAnnotationReader.php', 'Behat\\Behat\\Transformation\\Exception\\TransformationException' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/Exception/TransformationException.php', 'Behat\\Behat\\Transformation\\Exception\\UnsupportedCallException' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/Exception/UnsupportedCallException.php', 'Behat\\Behat\\Transformation\\ServiceContainer\\TransformationExtension' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/ServiceContainer/TransformationExtension.php', 'Behat\\Behat\\Transformation\\Transformation' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/Transformation.php', 'Behat\\Behat\\Transformation\\TransformationRepository' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/TransformationRepository.php', 'Behat\\Behat\\Transformation\\Transformer\\ArgumentTransformer' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/Transformer/ArgumentTransformer.php', 'Behat\\Behat\\Transformation\\Transformer\\RepositoryArgumentTransformer' => $vendorDir . '/behat/behat/src/Behat/Behat/Transformation/Transformer/RepositoryArgumentTransformer.php', 'Behat\\Behat\\Translator\\Cli\\GherkinTranslationsController' => $vendorDir . '/behat/behat/src/Behat/Behat/Translator/Cli/GherkinTranslationsController.php', 'Behat\\Behat\\Translator\\ServiceContainer\\GherkinTranslationsExtension' => $vendorDir . '/behat/behat/src/Behat/Behat/Translator/ServiceContainer/GherkinTranslationsExtension.php', 'Behat\\Gherkin\\Cache\\CacheInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Cache/CacheInterface.php', 'Behat\\Gherkin\\Cache\\FileCache' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Cache/FileCache.php', 'Behat\\Gherkin\\Cache\\MemoryCache' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Cache/MemoryCache.php', 'Behat\\Gherkin\\Exception\\CacheException' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Exception/CacheException.php', 'Behat\\Gherkin\\Exception\\Exception' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Exception/Exception.php', 'Behat\\Gherkin\\Exception\\LexerException' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Exception/LexerException.php', 'Behat\\Gherkin\\Exception\\NodeException' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Exception/NodeException.php', 'Behat\\Gherkin\\Exception\\ParserException' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Exception/ParserException.php', 'Behat\\Gherkin\\Filter\\ComplexFilter' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/ComplexFilter.php', 'Behat\\Gherkin\\Filter\\ComplexFilterInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/ComplexFilterInterface.php', 'Behat\\Gherkin\\Filter\\FeatureFilterInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/FeatureFilterInterface.php', 'Behat\\Gherkin\\Filter\\FilterInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/FilterInterface.php', 'Behat\\Gherkin\\Filter\\LineFilter' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/LineFilter.php', 'Behat\\Gherkin\\Filter\\LineRangeFilter' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/LineRangeFilter.php', 'Behat\\Gherkin\\Filter\\NameFilter' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/NameFilter.php', 'Behat\\Gherkin\\Filter\\NarrativeFilter' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/NarrativeFilter.php', 'Behat\\Gherkin\\Filter\\PathsFilter' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/PathsFilter.php', 'Behat\\Gherkin\\Filter\\RoleFilter' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/RoleFilter.php', 'Behat\\Gherkin\\Filter\\SimpleFilter' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/SimpleFilter.php', 'Behat\\Gherkin\\Filter\\TagFilter' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Filter/TagFilter.php', 'Behat\\Gherkin\\Gherkin' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Gherkin.php', 'Behat\\Gherkin\\Keywords\\ArrayKeywords' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Keywords/ArrayKeywords.php', 'Behat\\Gherkin\\Keywords\\CachedArrayKeywords' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Keywords/CachedArrayKeywords.php', 'Behat\\Gherkin\\Keywords\\CucumberKeywords' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Keywords/CucumberKeywords.php', 'Behat\\Gherkin\\Keywords\\KeywordsDumper' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Keywords/KeywordsDumper.php', 'Behat\\Gherkin\\Keywords\\KeywordsInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Keywords/KeywordsInterface.php', 'Behat\\Gherkin\\Lexer' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Lexer.php', 'Behat\\Gherkin\\Loader\\AbstractFileLoader' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Loader/AbstractFileLoader.php', 'Behat\\Gherkin\\Loader\\ArrayLoader' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Loader/ArrayLoader.php', 'Behat\\Gherkin\\Loader\\DirectoryLoader' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Loader/DirectoryLoader.php', 'Behat\\Gherkin\\Loader\\FileLoaderInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Loader/FileLoaderInterface.php', 'Behat\\Gherkin\\Loader\\GherkinFileLoader' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Loader/GherkinFileLoader.php', 'Behat\\Gherkin\\Loader\\LoaderInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Loader/LoaderInterface.php', 'Behat\\Gherkin\\Loader\\YamlFileLoader' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Loader/YamlFileLoader.php', 'Behat\\Gherkin\\Node\\ArgumentInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/ArgumentInterface.php', 'Behat\\Gherkin\\Node\\BackgroundNode' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/BackgroundNode.php', 'Behat\\Gherkin\\Node\\ExampleNode' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/ExampleNode.php', 'Behat\\Gherkin\\Node\\ExampleTableNode' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/ExampleTableNode.php', 'Behat\\Gherkin\\Node\\FeatureNode' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/FeatureNode.php', 'Behat\\Gherkin\\Node\\KeywordNodeInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/KeywordNodeInterface.php', 'Behat\\Gherkin\\Node\\NodeInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/NodeInterface.php', 'Behat\\Gherkin\\Node\\OutlineNode' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/OutlineNode.php', 'Behat\\Gherkin\\Node\\PyStringNode' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/PyStringNode.php', 'Behat\\Gherkin\\Node\\ScenarioInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/ScenarioInterface.php', 'Behat\\Gherkin\\Node\\ScenarioLikeInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/ScenarioLikeInterface.php', 'Behat\\Gherkin\\Node\\ScenarioNode' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/ScenarioNode.php', 'Behat\\Gherkin\\Node\\StepContainerInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/StepContainerInterface.php', 'Behat\\Gherkin\\Node\\StepNode' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/StepNode.php', 'Behat\\Gherkin\\Node\\TableNode' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/TableNode.php', 'Behat\\Gherkin\\Node\\TaggedNodeInterface' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Node/TaggedNodeInterface.php', 'Behat\\Gherkin\\Parser' => $vendorDir . '/behat/gherkin/src/Behat/Gherkin/Parser.php', 'Behat\\Testwork\\ApplicationFactory' => $vendorDir . '/behat/behat/src/Behat/Testwork/ApplicationFactory.php', 'Behat\\Testwork\\Argument\\ArgumentOrganiser' => $vendorDir . '/behat/behat/src/Behat/Testwork/Argument/ArgumentOrganiser.php', 'Behat\\Testwork\\Argument\\ConstructorArgumentOrganiser' => $vendorDir . '/behat/behat/src/Behat/Testwork/Argument/ConstructorArgumentOrganiser.php', 'Behat\\Testwork\\Argument\\Exception\\ArgumentException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Argument/Exception/ArgumentException.php', 'Behat\\Testwork\\Argument\\Exception\\UnknownParameterValueException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Argument/Exception/UnknownParameterValueException.php', 'Behat\\Testwork\\Argument\\Exception\\UnsupportedFunctionException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Argument/Exception/UnsupportedFunctionException.php', 'Behat\\Testwork\\Argument\\MixedArgumentOrganiser' => $vendorDir . '/behat/behat/src/Behat/Testwork/Argument/MixedArgumentOrganiser.php', 'Behat\\Testwork\\Argument\\PregMatchArgumentOrganiser' => $vendorDir . '/behat/behat/src/Behat/Testwork/Argument/PregMatchArgumentOrganiser.php', 'Behat\\Testwork\\Argument\\ServiceContainer\\ArgumentExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Argument/ServiceContainer/ArgumentExtension.php', 'Behat\\Testwork\\Autoloader\\Cli\\AutoloaderController' => $vendorDir . '/behat/behat/src/Behat/Testwork/Autoloader/Cli/AutoloaderController.php', 'Behat\\Testwork\\Autoloader\\ServiceContainer\\AutoloaderExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Autoloader/ServiceContainer/AutoloaderExtension.php', 'Behat\\Testwork\\Call\\Call' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/Call.php', 'Behat\\Testwork\\Call\\CallCenter' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/CallCenter.php', 'Behat\\Testwork\\Call\\CallResult' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/CallResult.php', 'Behat\\Testwork\\Call\\CallResults' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/CallResults.php', 'Behat\\Testwork\\Call\\Callee' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/Callee.php', 'Behat\\Testwork\\Call\\Exception\\BadCallbackException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/Exception/BadCallbackException.php', 'Behat\\Testwork\\Call\\Exception\\CallErrorException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/Exception/CallErrorException.php', 'Behat\\Testwork\\Call\\Exception\\CallException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/Exception/CallException.php', 'Behat\\Testwork\\Call\\Exception\\CallHandlingException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/Exception/CallHandlingException.php', 'Behat\\Testwork\\Call\\Filter\\CallFilter' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/Filter/CallFilter.php', 'Behat\\Testwork\\Call\\Filter\\ResultFilter' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/Filter/ResultFilter.php', 'Behat\\Testwork\\Call\\Handler\\CallHandler' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/Handler/CallHandler.php', 'Behat\\Testwork\\Call\\Handler\\RuntimeCallHandler' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/Handler/RuntimeCallHandler.php', 'Behat\\Testwork\\Call\\RuntimeCallee' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/RuntimeCallee.php', 'Behat\\Testwork\\Call\\ServiceContainer\\CallExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Call/ServiceContainer/CallExtension.php', 'Behat\\Testwork\\Cli\\Application' => $vendorDir . '/behat/behat/src/Behat/Testwork/Cli/Application.php', 'Behat\\Testwork\\Cli\\Command' => $vendorDir . '/behat/behat/src/Behat/Testwork/Cli/Command.php', 'Behat\\Testwork\\Cli\\Controller' => $vendorDir . '/behat/behat/src/Behat/Testwork/Cli/Controller.php', 'Behat\\Testwork\\Cli\\DumpReferenceCommand' => $vendorDir . '/behat/behat/src/Behat/Testwork/Cli/DumpReferenceCommand.php', 'Behat\\Testwork\\Cli\\ServiceContainer\\CliExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Cli/ServiceContainer/CliExtension.php', 'Behat\\Testwork\\Counter\\Exception\\TimerException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Counter/Exception/TimerException.php', 'Behat\\Testwork\\Counter\\Memory' => $vendorDir . '/behat/behat/src/Behat/Testwork/Counter/Memory.php', 'Behat\\Testwork\\Counter\\Timer' => $vendorDir . '/behat/behat/src/Behat/Testwork/Counter/Timer.php', 'Behat\\Testwork\\Environment\\Call\\EnvironmentCall' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/Call/EnvironmentCall.php', 'Behat\\Testwork\\Environment\\Environment' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/Environment.php', 'Behat\\Testwork\\Environment\\EnvironmentManager' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/EnvironmentManager.php', 'Behat\\Testwork\\Environment\\Exception\\EnvironmentBuildException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentBuildException.php', 'Behat\\Testwork\\Environment\\Exception\\EnvironmentException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentException.php', 'Behat\\Testwork\\Environment\\Exception\\EnvironmentIsolationException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentIsolationException.php', 'Behat\\Testwork\\Environment\\Exception\\EnvironmentReadException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentReadException.php', 'Behat\\Testwork\\Environment\\Handler\\EnvironmentHandler' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/Handler/EnvironmentHandler.php', 'Behat\\Testwork\\Environment\\Handler\\StaticEnvironmentHandler' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/Handler/StaticEnvironmentHandler.php', 'Behat\\Testwork\\Environment\\Reader\\EnvironmentReader' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/Reader/EnvironmentReader.php', 'Behat\\Testwork\\Environment\\ServiceContainer\\EnvironmentExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/ServiceContainer/EnvironmentExtension.php', 'Behat\\Testwork\\Environment\\StaticEnvironment' => $vendorDir . '/behat/behat/src/Behat/Testwork/Environment/StaticEnvironment.php', 'Behat\\Testwork\\EventDispatcher\\Cli\\SigintController' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Cli/SigintController.php', 'Behat\\Testwork\\EventDispatcher\\Event\\AfterExerciseAborted' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseAborted.php', 'Behat\\Testwork\\EventDispatcher\\Event\\AfterExerciseCompleted' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseCompleted.php', 'Behat\\Testwork\\EventDispatcher\\Event\\AfterExerciseSetup' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseSetup.php', 'Behat\\Testwork\\EventDispatcher\\Event\\AfterSetup' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSetup.php', 'Behat\\Testwork\\EventDispatcher\\Event\\AfterSuiteAborted' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteAborted.php', 'Behat\\Testwork\\EventDispatcher\\Event\\AfterSuiteSetup' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteSetup.php', 'Behat\\Testwork\\EventDispatcher\\Event\\AfterSuiteTested' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteTested.php', 'Behat\\Testwork\\EventDispatcher\\Event\\AfterTested' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterTested.php', 'Behat\\Testwork\\EventDispatcher\\Event\\BeforeExerciseCompleted' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeExerciseCompleted.php', 'Behat\\Testwork\\EventDispatcher\\Event\\BeforeExerciseTeardown' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeExerciseTeardown.php', 'Behat\\Testwork\\EventDispatcher\\Event\\BeforeSuiteTeardown' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeSuiteTeardown.php', 'Behat\\Testwork\\EventDispatcher\\Event\\BeforeSuiteTested' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeSuiteTested.php', 'Behat\\Testwork\\EventDispatcher\\Event\\BeforeTeardown' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeTeardown.php', 'Behat\\Testwork\\EventDispatcher\\Event\\BeforeTested' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeTested.php', 'Behat\\Testwork\\EventDispatcher\\Event\\ExerciseCompleted' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/ExerciseCompleted.php', 'Behat\\Testwork\\EventDispatcher\\Event\\LifecycleEvent' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/LifecycleEvent.php', 'Behat\\Testwork\\EventDispatcher\\Event\\SuiteTested' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Event/SuiteTested.php', 'Behat\\Testwork\\EventDispatcher\\ServiceContainer\\EventDispatcherExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/ServiceContainer/EventDispatcherExtension.php', 'Behat\\Testwork\\EventDispatcher\\Tester\\EventDispatchingExercise' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Tester/EventDispatchingExercise.php', 'Behat\\Testwork\\EventDispatcher\\Tester\\EventDispatchingSuiteTester' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/Tester/EventDispatchingSuiteTester.php', 'Behat\\Testwork\\EventDispatcher\\TestworkEventDispatcher' => $vendorDir . '/behat/behat/src/Behat/Testwork/EventDispatcher/TestworkEventDispatcher.php', 'Behat\\Testwork\\Exception\\Cli\\VerbosityController' => $vendorDir . '/behat/behat/src/Behat/Testwork/Exception/Cli/VerbosityController.php', 'Behat\\Testwork\\Exception\\ExceptionPresenter' => $vendorDir . '/behat/behat/src/Behat/Testwork/Exception/ExceptionPresenter.php', 'Behat\\Testwork\\Exception\\ServiceContainer\\ExceptionExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Exception/ServiceContainer/ExceptionExtension.php', 'Behat\\Testwork\\Exception\\Stringer\\ExceptionStringer' => $vendorDir . '/behat/behat/src/Behat/Testwork/Exception/Stringer/ExceptionStringer.php', 'Behat\\Testwork\\Exception\\Stringer\\PHPUnitExceptionStringer' => $vendorDir . '/behat/behat/src/Behat/Testwork/Exception/Stringer/PHPUnitExceptionStringer.php', 'Behat\\Testwork\\Exception\\Stringer\\TestworkExceptionStringer' => $vendorDir . '/behat/behat/src/Behat/Testwork/Exception/Stringer/TestworkExceptionStringer.php', 'Behat\\Testwork\\Exception\\TestworkException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Exception/TestworkException.php', 'Behat\\Testwork\\Filesystem\\ConsoleFilesystemLogger' => $vendorDir . '/behat/behat/src/Behat/Testwork/Filesystem/ConsoleFilesystemLogger.php', 'Behat\\Testwork\\Filesystem\\FilesystemLogger' => $vendorDir . '/behat/behat/src/Behat/Testwork/Filesystem/FilesystemLogger.php', 'Behat\\Testwork\\Filesystem\\ServiceContainer\\FilesystemExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Filesystem/ServiceContainer/FilesystemExtension.php', 'Behat\\Testwork\\Hook\\Call\\AfterSuite' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Call/AfterSuite.php', 'Behat\\Testwork\\Hook\\Call\\BeforeSuite' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Call/BeforeSuite.php', 'Behat\\Testwork\\Hook\\Call\\HookCall' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Call/HookCall.php', 'Behat\\Testwork\\Hook\\Call\\RuntimeFilterableHook' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeFilterableHook.php', 'Behat\\Testwork\\Hook\\Call\\RuntimeHook' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeHook.php', 'Behat\\Testwork\\Hook\\Call\\RuntimeSuiteHook' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeSuiteHook.php', 'Behat\\Testwork\\Hook\\FilterableHook' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/FilterableHook.php', 'Behat\\Testwork\\Hook\\Hook' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Hook.php', 'Behat\\Testwork\\Hook\\HookDispatcher' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/HookDispatcher.php', 'Behat\\Testwork\\Hook\\HookRepository' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/HookRepository.php', 'Behat\\Testwork\\Hook\\Scope\\AfterSuiteScope' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Scope/AfterSuiteScope.php', 'Behat\\Testwork\\Hook\\Scope\\AfterTestScope' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Scope/AfterTestScope.php', 'Behat\\Testwork\\Hook\\Scope\\BeforeSuiteScope' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Scope/BeforeSuiteScope.php', 'Behat\\Testwork\\Hook\\Scope\\HookScope' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Scope/HookScope.php', 'Behat\\Testwork\\Hook\\Scope\\SuiteScope' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Scope/SuiteScope.php', 'Behat\\Testwork\\Hook\\ServiceContainer\\HookExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/ServiceContainer/HookExtension.php', 'Behat\\Testwork\\Hook\\Tester\\HookableSuiteTester' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Tester/HookableSuiteTester.php', 'Behat\\Testwork\\Hook\\Tester\\Setup\\HookedSetup' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Tester/Setup/HookedSetup.php', 'Behat\\Testwork\\Hook\\Tester\\Setup\\HookedTeardown' => $vendorDir . '/behat/behat/src/Behat/Testwork/Hook/Tester/Setup/HookedTeardown.php', 'Behat\\Testwork\\Output\\Cli\\OutputController' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Cli/OutputController.php', 'Behat\\Testwork\\Output\\Exception\\BadOutputPathException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Exception/BadOutputPathException.php', 'Behat\\Testwork\\Output\\Exception\\FormatterNotFoundException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Exception/FormatterNotFoundException.php', 'Behat\\Testwork\\Output\\Exception\\OutputException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Exception/OutputException.php', 'Behat\\Testwork\\Output\\Exception\\PrinterException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Exception/PrinterException.php', 'Behat\\Testwork\\Output\\Formatter' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Formatter.php', 'Behat\\Testwork\\Output\\NodeEventListeningFormatter' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/NodeEventListeningFormatter.php', 'Behat\\Testwork\\Output\\Node\\EventListener\\ChainEventListener' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Node/EventListener/ChainEventListener.php', 'Behat\\Testwork\\Output\\Node\\EventListener\\EventListener' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Node/EventListener/EventListener.php', 'Behat\\Testwork\\Output\\Node\\EventListener\\Flow\\FireOnlyIfFormatterParameterListener' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Node/EventListener/Flow/FireOnlyIfFormatterParameterListener.php', 'Behat\\Testwork\\Output\\OutputManager' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/OutputManager.php', 'Behat\\Testwork\\Output\\Printer\\ConsoleOutputPrinter' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Printer/ConsoleOutputPrinter.php', 'Behat\\Testwork\\Output\\Printer\\OutputPrinter' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/Printer/OutputPrinter.php', 'Behat\\Testwork\\Output\\ServiceContainer\\Formatter\\FormatterFactory' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/ServiceContainer/Formatter/FormatterFactory.php', 'Behat\\Testwork\\Output\\ServiceContainer\\OutputExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Output/ServiceContainer/OutputExtension.php', 'Behat\\Testwork\\ServiceContainer\\Configuration\\ConfigurationLoader' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/Configuration/ConfigurationLoader.php', 'Behat\\Testwork\\ServiceContainer\\Configuration\\ConfigurationTree' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/Configuration/ConfigurationTree.php', 'Behat\\Testwork\\ServiceContainer\\ContainerLoader' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/ContainerLoader.php', 'Behat\\Testwork\\ServiceContainer\\Exception\\ConfigurationLoadingException' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ConfigurationLoadingException.php', 'Behat\\Testwork\\ServiceContainer\\Exception\\ExtensionException' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ExtensionException.php', 'Behat\\Testwork\\ServiceContainer\\Exception\\ExtensionInitializationException' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ExtensionInitializationException.php', 'Behat\\Testwork\\ServiceContainer\\Exception\\ProcessingException' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ProcessingException.php', 'Behat\\Testwork\\ServiceContainer\\Exception\\ServiceContainerException' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ServiceContainerException.php', 'Behat\\Testwork\\ServiceContainer\\Extension' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/Extension.php', 'Behat\\Testwork\\ServiceContainer\\ExtensionManager' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/ExtensionManager.php', 'Behat\\Testwork\\ServiceContainer\\ServiceProcessor' => $vendorDir . '/behat/behat/src/Behat/Testwork/ServiceContainer/ServiceProcessor.php', 'Behat\\Testwork\\Specification\\GroupedSpecificationIterator' => $vendorDir . '/behat/behat/src/Behat/Testwork/Specification/GroupedSpecificationIterator.php', 'Behat\\Testwork\\Specification\\Locator\\SpecificationLocator' => $vendorDir . '/behat/behat/src/Behat/Testwork/Specification/Locator/SpecificationLocator.php', 'Behat\\Testwork\\Specification\\NoSpecificationsIterator' => $vendorDir . '/behat/behat/src/Behat/Testwork/Specification/NoSpecificationsIterator.php', 'Behat\\Testwork\\Specification\\ServiceContainer\\SpecificationExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Specification/ServiceContainer/SpecificationExtension.php', 'Behat\\Testwork\\Specification\\SpecificationArrayIterator' => $vendorDir . '/behat/behat/src/Behat/Testwork/Specification/SpecificationArrayIterator.php', 'Behat\\Testwork\\Specification\\SpecificationFinder' => $vendorDir . '/behat/behat/src/Behat/Testwork/Specification/SpecificationFinder.php', 'Behat\\Testwork\\Specification\\SpecificationIterator' => $vendorDir . '/behat/behat/src/Behat/Testwork/Specification/SpecificationIterator.php', 'Behat\\Testwork\\Suite\\Cli\\InitializationController' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Cli/InitializationController.php', 'Behat\\Testwork\\Suite\\Cli\\SuiteController' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Cli/SuiteController.php', 'Behat\\Testwork\\Suite\\Exception\\ParameterNotFoundException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Exception/ParameterNotFoundException.php', 'Behat\\Testwork\\Suite\\Exception\\SuiteConfigurationException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteConfigurationException.php', 'Behat\\Testwork\\Suite\\Exception\\SuiteException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteException.php', 'Behat\\Testwork\\Suite\\Exception\\SuiteGenerationException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteGenerationException.php', 'Behat\\Testwork\\Suite\\Exception\\SuiteNotFoundException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteNotFoundException.php', 'Behat\\Testwork\\Suite\\Exception\\SuiteSetupException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteSetupException.php', 'Behat\\Testwork\\Suite\\Generator\\GenericSuiteGenerator' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Generator/GenericSuiteGenerator.php', 'Behat\\Testwork\\Suite\\Generator\\SuiteGenerator' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Generator/SuiteGenerator.php', 'Behat\\Testwork\\Suite\\GenericSuite' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/GenericSuite.php', 'Behat\\Testwork\\Suite\\ServiceContainer\\SuiteExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/ServiceContainer/SuiteExtension.php', 'Behat\\Testwork\\Suite\\Setup\\SuiteSetup' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Setup/SuiteSetup.php', 'Behat\\Testwork\\Suite\\Suite' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/Suite.php', 'Behat\\Testwork\\Suite\\SuiteBootstrapper' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/SuiteBootstrapper.php', 'Behat\\Testwork\\Suite\\SuiteRegistry' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/SuiteRegistry.php', 'Behat\\Testwork\\Suite\\SuiteRepository' => $vendorDir . '/behat/behat/src/Behat/Testwork/Suite/SuiteRepository.php', 'Behat\\Testwork\\Tester\\Cli\\ExerciseController' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Cli/ExerciseController.php', 'Behat\\Testwork\\Tester\\Cli\\StrictController' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Cli/StrictController.php', 'Behat\\Testwork\\Tester\\Exception\\TesterException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Exception/TesterException.php', 'Behat\\Testwork\\Tester\\Exception\\WrongPathsException' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Exception/WrongPathsException.php', 'Behat\\Testwork\\Tester\\Exercise' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Exercise.php', 'Behat\\Testwork\\Tester\\Result\\ExceptionResult' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Result/ExceptionResult.php', 'Behat\\Testwork\\Tester\\Result\\IntegerTestResult' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Result/IntegerTestResult.php', 'Behat\\Testwork\\Tester\\Result\\Interpretation\\ResultInterpretation' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/ResultInterpretation.php', 'Behat\\Testwork\\Tester\\Result\\Interpretation\\SoftInterpretation' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/SoftInterpretation.php', 'Behat\\Testwork\\Tester\\Result\\Interpretation\\StrictInterpretation' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/StrictInterpretation.php', 'Behat\\Testwork\\Tester\\Result\\ResultInterpreter' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Result/ResultInterpreter.php', 'Behat\\Testwork\\Tester\\Result\\TestResult' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Result/TestResult.php', 'Behat\\Testwork\\Tester\\Result\\TestResults' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Result/TestResults.php', 'Behat\\Testwork\\Tester\\Result\\TestWithSetupResult' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Result/TestWithSetupResult.php', 'Behat\\Testwork\\Tester\\Runtime\\RuntimeExercise' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Runtime/RuntimeExercise.php', 'Behat\\Testwork\\Tester\\Runtime\\RuntimeSuiteTester' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Runtime/RuntimeSuiteTester.php', 'Behat\\Testwork\\Tester\\ServiceContainer\\TesterExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/ServiceContainer/TesterExtension.php', 'Behat\\Testwork\\Tester\\Setup\\FailedSetup' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Setup/FailedSetup.php', 'Behat\\Testwork\\Tester\\Setup\\FailedTeardown' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Setup/FailedTeardown.php', 'Behat\\Testwork\\Tester\\Setup\\Setup' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Setup/Setup.php', 'Behat\\Testwork\\Tester\\Setup\\SuccessfulSetup' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Setup/SuccessfulSetup.php', 'Behat\\Testwork\\Tester\\Setup\\SuccessfulTeardown' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Setup/SuccessfulTeardown.php', 'Behat\\Testwork\\Tester\\Setup\\Teardown' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/Setup/Teardown.php', 'Behat\\Testwork\\Tester\\SpecificationTester' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/SpecificationTester.php', 'Behat\\Testwork\\Tester\\SuiteTester' => $vendorDir . '/behat/behat/src/Behat/Testwork/Tester/SuiteTester.php', 'Behat\\Testwork\\Translator\\Cli\\LanguageController' => $vendorDir . '/behat/behat/src/Behat/Testwork/Translator/Cli/LanguageController.php', 'Behat\\Testwork\\Translator\\ServiceContainer\\TranslatorExtension' => $vendorDir . '/behat/behat/src/Behat/Testwork/Translator/ServiceContainer/TranslatorExtension.php', 'Behat\\Transliterator\\Transliterator' => $vendorDir . '/behat/transliterator/src/Behat/Transliterator/Transliterator.php', 'Cilex\\Application' => $vendorDir . '/cilex/cilex/src/Cilex/Application.php', 'Cilex\\Command\\Command' => $vendorDir . '/cilex/cilex/src/Cilex/Command/Command.php', 'Cilex\\Command\\DemoInfoCommand' => $vendorDir . '/cilex/cilex/src/Cilex/Command/DemoInfoCommand.php', 'Cilex\\Command\\GreetCommand' => $vendorDir . '/cilex/cilex/src/Cilex/Command/GreetCommand.php', 'Cilex\\Compiler' => $vendorDir . '/cilex/cilex/src/Cilex/Compiler.php', 'Cilex\\Provider\\ConfigServiceProvider' => $vendorDir . '/cilex/cilex/src/Cilex/Provider/ConfigServiceProvider.php', 'Cilex\\Provider\\Console\\Adapter\\Silex\\ConsoleServiceProvider' => $vendorDir . '/cilex/console-service-provider/src/Cilex/Provider/Console/Adapter/Silex/ConsoleServiceProvider.php', 'Cilex\\Provider\\Console\\BaseConsoleServiceProvider' => $vendorDir . '/cilex/console-service-provider/src/Cilex/Provider/Console/BaseConsoleServiceProvider.php', 'Cilex\\Provider\\Console\\ConsoleServiceProvider' => $vendorDir . '/cilex/console-service-provider/src/Cilex/Provider/Console/ConsoleServiceProvider.php', 'Cilex\\Provider\\Console\\ContainerAwareApplication' => $vendorDir . '/cilex/console-service-provider/src/Cilex/Provider/Console/ContainerAwareApplication.php', 'Cilex\\Provider\\DoctrineServiceProvider' => $vendorDir . '/cilex/cilex/src/Cilex/Provider/DoctrineServiceProvider.php', 'Cilex\\Provider\\JmsSerializerServiceProvider' => $baseDir . '/src/Cilex/Provider/JmsSerializerServiceProvider.php', 'Cilex\\Provider\\MonologServiceProvider' => $vendorDir . '/cilex/cilex/src/Cilex/Provider/MonologServiceProvider.php', 'Cilex\\Provider\\ValidatorServiceProvider' => $vendorDir . '/cilex/cilex/src/Cilex/Provider/ValidatorServiceProvider.php', 'Cilex\\ServiceProviderInterface' => $vendorDir . '/cilex/cilex/src/Cilex/ServiceProviderInterface.php', 'Doctrine\\Common\\Annotations\\Annotation' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php', 'Doctrine\\Common\\Annotations\\AnnotationException' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php', 'Doctrine\\Common\\Annotations\\AnnotationReader' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php', 'Doctrine\\Common\\Annotations\\AnnotationRegistry' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php', 'Doctrine\\Common\\Annotations\\Annotation\\Attribute' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php', 'Doctrine\\Common\\Annotations\\Annotation\\Attributes' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php', 'Doctrine\\Common\\Annotations\\Annotation\\Enum' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php', 'Doctrine\\Common\\Annotations\\Annotation\\IgnoreAnnotation' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php', 'Doctrine\\Common\\Annotations\\Annotation\\Required' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php', 'Doctrine\\Common\\Annotations\\Annotation\\Target' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php', 'Doctrine\\Common\\Annotations\\CachedReader' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php', 'Doctrine\\Common\\Annotations\\DocLexer' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php', 'Doctrine\\Common\\Annotations\\DocParser' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php', 'Doctrine\\Common\\Annotations\\FileCacheReader' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php', 'Doctrine\\Common\\Annotations\\IndexedReader' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php', 'Doctrine\\Common\\Annotations\\PhpParser' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php', 'Doctrine\\Common\\Annotations\\Reader' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php', 'Doctrine\\Common\\Annotations\\SimpleAnnotationReader' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php', 'Doctrine\\Common\\Annotations\\TokenParser' => $vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php', 'Doctrine\\Common\\Lexer\\AbstractLexer' => $vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php', 'Doctrine\\Instantiator\\Exception\\ExceptionInterface' => $vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php', 'Doctrine\\Instantiator\\Exception\\InvalidArgumentException' => $vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php', 'Doctrine\\Instantiator\\Exception\\UnexpectedValueException' => $vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php', 'Doctrine\\Instantiator\\Instantiator' => $vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php', 'Doctrine\\Instantiator\\InstantiatorInterface' => $vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php', 'File_Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php', 'File_Iterator_Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php', 'File_Iterator_Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php', 'Generic_Sniffs_Classes_DuplicateClassNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php', 'Generic_Sniffs_CodeAnalysis_EmptyStatementSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php', 'Generic_Sniffs_CodeAnalysis_ForLoopShouldBeWhileLoopSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php', 'Generic_Sniffs_CodeAnalysis_ForLoopWithTestFunctionCallSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php', 'Generic_Sniffs_CodeAnalysis_JumbledIncrementerSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php', 'Generic_Sniffs_CodeAnalysis_UnconditionalIfStatementSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php', 'Generic_Sniffs_CodeAnalysis_UnnecessaryFinalModifierSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php', 'Generic_Sniffs_CodeAnalysis_UnusedFunctionParameterSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php', 'Generic_Sniffs_CodeAnalysis_UselessOverridingMethodSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php', 'Generic_Sniffs_Commenting_FixmeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Commenting/FixmeSniff.php', 'Generic_Sniffs_Commenting_TodoSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Commenting/TodoSniff.php', 'Generic_Sniffs_ControlStructures_InlineControlStructureSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php', 'Generic_Sniffs_Debug_CSSLintSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Debug/CSSLintSniff.php', 'Generic_Sniffs_Debug_ClosureLinterSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php', 'Generic_Sniffs_Debug_JSHintSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Debug/JSHintSniff.php', 'Generic_Sniffs_Files_ByteOrderMarkSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php', 'Generic_Sniffs_Files_EndFileNewlineSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php', 'Generic_Sniffs_Files_EndFileNoNewlineSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php', 'Generic_Sniffs_Files_InlineHTMLSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php', 'Generic_Sniffs_Files_LineEndingsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/LineEndingsSniff.php', 'Generic_Sniffs_Files_LineLengthSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/LineLengthSniff.php', 'Generic_Sniffs_Files_LowercasedFilenameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php', 'Generic_Sniffs_Files_OneClassPerFileSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php', 'Generic_Sniffs_Files_OneInterfacePerFileSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php', 'Generic_Sniffs_Formatting_DisallowMultipleStatementsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php', 'Generic_Sniffs_Formatting_MultipleStatementAlignmentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php', 'Generic_Sniffs_Formatting_NoSpaceAfterCastSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php', 'Generic_Sniffs_Formatting_SpaceAfterCastSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php', 'Generic_Sniffs_Functions_CallTimePassByReferenceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php', 'Generic_Sniffs_Functions_FunctionCallArgumentSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php', 'Generic_Sniffs_Functions_OpeningFunctionBraceBsdAllmanSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php', 'Generic_Sniffs_Functions_OpeningFunctionBraceKernighanRitchieSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php', 'Generic_Sniffs_Metrics_CyclomaticComplexitySniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php', 'Generic_Sniffs_Metrics_NestingLevelSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php', 'Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php', 'Generic_Sniffs_NamingConventions_ConstructorNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php', 'Generic_Sniffs_NamingConventions_UpperCaseConstantNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php', 'Generic_Sniffs_PHP_CharacterBeforePHPOpeningTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php', 'Generic_Sniffs_PHP_ClosingPHPTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php', 'Generic_Sniffs_PHP_DeprecatedFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php', 'Generic_Sniffs_PHP_DisallowShortOpenTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/DisallowShortOpenTagSniff.php', 'Generic_Sniffs_PHP_ForbiddenFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/ForbiddenFunctionsSniff.php', 'Generic_Sniffs_PHP_LowerCaseConstantSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/LowerCaseConstantSniff.php', 'Generic_Sniffs_PHP_LowerCaseKeywordSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/LowerCaseKeywordSniff.php', 'Generic_Sniffs_PHP_NoSilencedErrorsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/NoSilencedErrorsSniff.php', 'Generic_Sniffs_PHP_SAPIUsageSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/SAPIUsageSniff.php', 'Generic_Sniffs_PHP_SyntaxSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/SyntaxSniff.php', 'Generic_Sniffs_PHP_UpperCaseConstantSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/UpperCaseConstantSniff.php', 'Generic_Sniffs_Strings_UnnecessaryStringConcatSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Strings/UnnecessaryStringConcatSniff.php', 'Generic_Sniffs_VersionControl_SubversionPropertiesSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/VersionControl/SubversionPropertiesSniff.php', 'Generic_Sniffs_WhiteSpace_DisallowSpaceIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php', 'Generic_Sniffs_WhiteSpace_DisallowTabIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/DisallowTabIndentSniff.php', 'Generic_Sniffs_WhiteSpace_ScopeIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php', 'Hamcrest\\Arrays\\IsArray' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArray.php', 'Hamcrest\\Arrays\\IsArrayContaining' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContaining.php', 'Hamcrest\\Arrays\\IsArrayContainingInAnyOrder' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInAnyOrder.php', 'Hamcrest\\Arrays\\IsArrayContainingInOrder' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingInOrder.php', 'Hamcrest\\Arrays\\IsArrayContainingKey' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKey.php', 'Hamcrest\\Arrays\\IsArrayContainingKeyValuePair' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayContainingKeyValuePair.php', 'Hamcrest\\Arrays\\IsArrayWithSize' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/IsArrayWithSize.php', 'Hamcrest\\Arrays\\MatchingOnce' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/MatchingOnce.php', 'Hamcrest\\Arrays\\SeriesMatchingOnce' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Arrays/SeriesMatchingOnce.php', 'Hamcrest\\AssertionError' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/AssertionError.php', 'Hamcrest\\BaseDescription' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseDescription.php', 'Hamcrest\\BaseMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/BaseMatcher.php', 'Hamcrest\\Collection\\IsEmptyTraversable' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsEmptyTraversable.php', 'Hamcrest\\Collection\\IsTraversableWithSize' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Collection/IsTraversableWithSize.php', 'Hamcrest\\Core\\AllOf' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AllOf.php', 'Hamcrest\\Core\\AnyOf' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/AnyOf.php', 'Hamcrest\\Core\\CombinableMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/CombinableMatcher.php', 'Hamcrest\\Core\\DescribedAs' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/DescribedAs.php', 'Hamcrest\\Core\\Every' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Every.php', 'Hamcrest\\Core\\HasToString' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/HasToString.php', 'Hamcrest\\Core\\Is' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Is.php', 'Hamcrest\\Core\\IsAnything' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsAnything.php', 'Hamcrest\\Core\\IsCollectionContaining' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsCollectionContaining.php', 'Hamcrest\\Core\\IsEqual' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsEqual.php', 'Hamcrest\\Core\\IsIdentical' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsIdentical.php', 'Hamcrest\\Core\\IsInstanceOf' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsInstanceOf.php', 'Hamcrest\\Core\\IsNot' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNot.php', 'Hamcrest\\Core\\IsNull' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsNull.php', 'Hamcrest\\Core\\IsSame' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsSame.php', 'Hamcrest\\Core\\IsTypeOf' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/IsTypeOf.php', 'Hamcrest\\Core\\Set' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/Set.php', 'Hamcrest\\Core\\ShortcutCombination' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Core/ShortcutCombination.php', 'Hamcrest\\Description' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Description.php', 'Hamcrest\\DiagnosingMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/DiagnosingMatcher.php', 'Hamcrest\\FeatureMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/FeatureMatcher.php', 'Hamcrest\\Internal\\SelfDescribingValue' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Internal/SelfDescribingValue.php', 'Hamcrest\\Matcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matcher.php', 'Hamcrest\\MatcherAssert' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/MatcherAssert.php', 'Hamcrest\\Matchers' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Matchers.php', 'Hamcrest\\NullDescription' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/NullDescription.php', 'Hamcrest\\Number\\IsCloseTo' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/IsCloseTo.php', 'Hamcrest\\Number\\OrderingComparison' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Number/OrderingComparison.php', 'Hamcrest\\SelfDescribing' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/SelfDescribing.php', 'Hamcrest\\StringDescription' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/StringDescription.php', 'Hamcrest\\Text\\IsEmptyString' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEmptyString.php', 'Hamcrest\\Text\\IsEqualIgnoringCase' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringCase.php', 'Hamcrest\\Text\\IsEqualIgnoringWhiteSpace' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/IsEqualIgnoringWhiteSpace.php', 'Hamcrest\\Text\\MatchesPattern' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/MatchesPattern.php', 'Hamcrest\\Text\\StringContains' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContains.php', 'Hamcrest\\Text\\StringContainsIgnoringCase' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsIgnoringCase.php', 'Hamcrest\\Text\\StringContainsInOrder' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringContainsInOrder.php', 'Hamcrest\\Text\\StringEndsWith' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringEndsWith.php', 'Hamcrest\\Text\\StringStartsWith' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/StringStartsWith.php', 'Hamcrest\\Text\\SubstringMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Text/SubstringMatcher.php', 'Hamcrest\\TypeSafeDiagnosingMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeDiagnosingMatcher.php', 'Hamcrest\\TypeSafeMatcher' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/TypeSafeMatcher.php', 'Hamcrest\\Type\\IsArray' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsArray.php', 'Hamcrest\\Type\\IsBoolean' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsBoolean.php', 'Hamcrest\\Type\\IsCallable' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsCallable.php', 'Hamcrest\\Type\\IsDouble' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsDouble.php', 'Hamcrest\\Type\\IsInteger' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsInteger.php', 'Hamcrest\\Type\\IsNumeric' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsNumeric.php', 'Hamcrest\\Type\\IsObject' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsObject.php', 'Hamcrest\\Type\\IsResource' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsResource.php', 'Hamcrest\\Type\\IsScalar' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsScalar.php', 'Hamcrest\\Type\\IsString' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Type/IsString.php', 'Hamcrest\\Util' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Util.php', 'Hamcrest\\Xml\\HasXPath' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest/Xml/HasXPath.php', 'Herrera\\Json\\Exception\\Exception' => $vendorDir . '/herrera-io/json/src/lib/Herrera/Json/Exception/Exception.php', 'Herrera\\Json\\Exception\\ExceptionInterface' => $vendorDir . '/herrera-io/json/src/lib/Herrera/Json/Exception/ExceptionInterface.php', 'Herrera\\Json\\Exception\\FileException' => $vendorDir . '/herrera-io/json/src/lib/Herrera/Json/Exception/FileException.php', 'Herrera\\Json\\Exception\\JsonException' => $vendorDir . '/herrera-io/json/src/lib/Herrera/Json/Exception/JsonException.php', 'Herrera\\Json\\Json' => $vendorDir . '/herrera-io/json/src/lib/Herrera/Json/Json.php', 'Herrera\\Phar\\Update\\Exception\\Exception' => $vendorDir . '/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Exception/Exception.php', 'Herrera\\Phar\\Update\\Exception\\ExceptionInterface' => $vendorDir . '/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Exception/ExceptionInterface.php', 'Herrera\\Phar\\Update\\Exception\\FileException' => $vendorDir . '/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Exception/FileException.php', 'Herrera\\Phar\\Update\\Exception\\InvalidArgumentException' => $vendorDir . '/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Exception/InvalidArgumentException.php', 'Herrera\\Phar\\Update\\Exception\\LogicException' => $vendorDir . '/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Exception/LogicException.php', 'Herrera\\Phar\\Update\\Manager' => $vendorDir . '/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Manager.php', 'Herrera\\Phar\\Update\\Manifest' => $vendorDir . '/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Manifest.php', 'Herrera\\Phar\\Update\\Update' => $vendorDir . '/herrera-io/phar-update/src/lib/Herrera/Phar/Update/Update.php', 'JMS\\Parser\\AbstractLexer' => $vendorDir . '/jms/parser-lib/src/JMS/Parser/AbstractLexer.php', 'JMS\\Parser\\AbstractParser' => $vendorDir . '/jms/parser-lib/src/JMS/Parser/AbstractParser.php', 'JMS\\Parser\\SimpleLexer' => $vendorDir . '/jms/parser-lib/src/JMS/Parser/SimpleLexer.php', 'JMS\\Parser\\SyntaxErrorException' => $vendorDir . '/jms/parser-lib/src/JMS/Parser/SyntaxErrorException.php', 'JMS\\Serializer\\AbstractVisitor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/AbstractVisitor.php', 'JMS\\Serializer\\Annotation\\AccessType' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/AccessType.php', 'JMS\\Serializer\\Annotation\\Accessor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/Accessor.php', 'JMS\\Serializer\\Annotation\\AccessorOrder' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/AccessorOrder.php', 'JMS\\Serializer\\Annotation\\Discriminator' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/Discriminator.php', 'JMS\\Serializer\\Annotation\\Exclude' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/Exclude.php', 'JMS\\Serializer\\Annotation\\ExclusionPolicy' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/ExclusionPolicy.php', 'JMS\\Serializer\\Annotation\\Expose' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/Expose.php', 'JMS\\Serializer\\Annotation\\Groups' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/Groups.php', 'JMS\\Serializer\\Annotation\\HandlerCallback' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/HandlerCallback.php', 'JMS\\Serializer\\Annotation\\Inline' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/Inline.php', 'JMS\\Serializer\\Annotation\\PostDeserialize' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/PostDeserialize.php', 'JMS\\Serializer\\Annotation\\PostSerialize' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/PostSerialize.php', 'JMS\\Serializer\\Annotation\\PreSerialize' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/PreSerialize.php', 'JMS\\Serializer\\Annotation\\ReadOnly' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/ReadOnly.php', 'JMS\\Serializer\\Annotation\\SerializedName' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/SerializedName.php', 'JMS\\Serializer\\Annotation\\Since' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/Since.php', 'JMS\\Serializer\\Annotation\\Type' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/Type.php', 'JMS\\Serializer\\Annotation\\Until' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/Until.php', 'JMS\\Serializer\\Annotation\\Version' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/Version.php', 'JMS\\Serializer\\Annotation\\VirtualProperty' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/VirtualProperty.php', 'JMS\\Serializer\\Annotation\\XmlAttribute' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/XmlAttribute.php', 'JMS\\Serializer\\Annotation\\XmlAttributeMap' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/XmlAttributeMap.php', 'JMS\\Serializer\\Annotation\\XmlCollection' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/XmlCollection.php', 'JMS\\Serializer\\Annotation\\XmlKeyValuePairs' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/XmlKeyValuePairs.php', 'JMS\\Serializer\\Annotation\\XmlList' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/XmlList.php', 'JMS\\Serializer\\Annotation\\XmlMap' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/XmlMap.php', 'JMS\\Serializer\\Annotation\\XmlRoot' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/XmlRoot.php', 'JMS\\Serializer\\Annotation\\XmlValue' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Annotation/XmlValue.php', 'JMS\\Serializer\\Construction\\DoctrineObjectConstructor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Construction/DoctrineObjectConstructor.php', 'JMS\\Serializer\\Construction\\ObjectConstructorInterface' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Construction/ObjectConstructorInterface.php', 'JMS\\Serializer\\Construction\\UnserializeObjectConstructor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Construction/UnserializeObjectConstructor.php', 'JMS\\Serializer\\Context' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Context.php', 'JMS\\Serializer\\DeserializationContext' => $vendorDir . '/jms/serializer/src/JMS/Serializer/DeserializationContext.php', 'JMS\\Serializer\\EventDispatcher\\Event' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/Event.php', 'JMS\\Serializer\\EventDispatcher\\EventDispatcher' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/EventDispatcher.php', 'JMS\\Serializer\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/EventDispatcherInterface.php', 'JMS\\Serializer\\EventDispatcher\\EventSubscriberInterface' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/EventSubscriberInterface.php', 'JMS\\Serializer\\EventDispatcher\\Events' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/Events.php', 'JMS\\Serializer\\EventDispatcher\\LazyEventDispatcher' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/LazyEventDispatcher.php', 'JMS\\Serializer\\EventDispatcher\\ObjectEvent' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/ObjectEvent.php', 'JMS\\Serializer\\EventDispatcher\\PreDeserializeEvent' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/PreDeserializeEvent.php', 'JMS\\Serializer\\EventDispatcher\\PreSerializeEvent' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/PreSerializeEvent.php', 'JMS\\Serializer\\EventDispatcher\\Subscriber\\DoctrineProxySubscriber' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/Subscriber/DoctrineProxySubscriber.php', 'JMS\\Serializer\\EventDispatcher\\Subscriber\\SymfonyValidatorSubscriber' => $vendorDir . '/jms/serializer/src/JMS/Serializer/EventDispatcher/Subscriber/SymfonyValidatorSubscriber.php', 'JMS\\Serializer\\Exception\\Exception' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exception/Exception.php', 'JMS\\Serializer\\Exception\\InvalidArgumentException' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exception/InvalidArgumentException.php', 'JMS\\Serializer\\Exception\\LogicException' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exception/LogicException.php', 'JMS\\Serializer\\Exception\\RuntimeException' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exception/RuntimeException.php', 'JMS\\Serializer\\Exception\\UnsupportedFormatException' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exception/UnsupportedFormatException.php', 'JMS\\Serializer\\Exception\\ValidationFailedException' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exception/ValidationFailedException.php', 'JMS\\Serializer\\Exception\\XmlErrorException' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exception/XmlErrorException.php', 'JMS\\Serializer\\Exclusion\\DisjunctExclusionStrategy' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exclusion/DisjunctExclusionStrategy.php', 'JMS\\Serializer\\Exclusion\\ExclusionStrategyInterface' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exclusion/ExclusionStrategyInterface.php', 'JMS\\Serializer\\Exclusion\\GroupsExclusionStrategy' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exclusion/GroupsExclusionStrategy.php', 'JMS\\Serializer\\Exclusion\\VersionExclusionStrategy' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Exclusion/VersionExclusionStrategy.php', 'JMS\\Serializer\\GenericDeserializationVisitor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/GenericDeserializationVisitor.php', 'JMS\\Serializer\\GenericSerializationVisitor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/GenericSerializationVisitor.php', 'JMS\\Serializer\\GraphNavigator' => $vendorDir . '/jms/serializer/src/JMS/Serializer/GraphNavigator.php', 'JMS\\Serializer\\Handler\\ArrayCollectionHandler' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Handler/ArrayCollectionHandler.php', 'JMS\\Serializer\\Handler\\ConstraintViolationHandler' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Handler/ConstraintViolationHandler.php', 'JMS\\Serializer\\Handler\\DateHandler' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Handler/DateHandler.php', 'JMS\\Serializer\\Handler\\FormErrorHandler' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Handler/FormErrorHandler.php', 'JMS\\Serializer\\Handler\\HandlerRegistry' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Handler/HandlerRegistry.php', 'JMS\\Serializer\\Handler\\HandlerRegistryInterface' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Handler/HandlerRegistryInterface.php', 'JMS\\Serializer\\Handler\\LazyHandlerRegistry' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Handler/LazyHandlerRegistry.php', 'JMS\\Serializer\\Handler\\PhpCollectionHandler' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Handler/PhpCollectionHandler.php', 'JMS\\Serializer\\Handler\\SubscribingHandlerInterface' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Handler/SubscribingHandlerInterface.php', 'JMS\\Serializer\\JsonDeserializationVisitor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/JsonDeserializationVisitor.php', 'JMS\\Serializer\\JsonSerializationVisitor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/JsonSerializationVisitor.php', 'JMS\\Serializer\\Metadata\\ClassMetadata' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Metadata/ClassMetadata.php', 'JMS\\Serializer\\Metadata\\Driver\\AnnotationDriver' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Metadata/Driver/AnnotationDriver.php', 'JMS\\Serializer\\Metadata\\Driver\\DoctrineTypeDriver' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Metadata/Driver/DoctrineTypeDriver.php', 'JMS\\Serializer\\Metadata\\Driver\\PhpDriver' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Metadata/Driver/PhpDriver.php', 'JMS\\Serializer\\Metadata\\Driver\\XmlDriver' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Metadata/Driver/XmlDriver.php', 'JMS\\Serializer\\Metadata\\Driver\\YamlDriver' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Metadata/Driver/YamlDriver.php', 'JMS\\Serializer\\Metadata\\PropertyMetadata' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Metadata/PropertyMetadata.php', 'JMS\\Serializer\\Metadata\\StaticPropertyMetadata' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Metadata/StaticPropertyMetadata.php', 'JMS\\Serializer\\Metadata\\VirtualPropertyMetadata' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Metadata/VirtualPropertyMetadata.php', 'JMS\\Serializer\\Naming\\CacheNamingStrategy' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Naming/CacheNamingStrategy.php', 'JMS\\Serializer\\Naming\\CamelCaseNamingStrategy' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Naming/CamelCaseNamingStrategy.php', 'JMS\\Serializer\\Naming\\IdenticalPropertyNamingStrategy' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Naming/IdenticalPropertyNamingStrategy.php', 'JMS\\Serializer\\Naming\\PropertyNamingStrategyInterface' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Naming/PropertyNamingStrategyInterface.php', 'JMS\\Serializer\\Naming\\SerializedNameAnnotationStrategy' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Naming/SerializedNameAnnotationStrategy.php', 'JMS\\Serializer\\SerializationContext' => $vendorDir . '/jms/serializer/src/JMS/Serializer/SerializationContext.php', 'JMS\\Serializer\\Serializer' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Serializer.php', 'JMS\\Serializer\\SerializerBuilder' => $vendorDir . '/jms/serializer/src/JMS/Serializer/SerializerBuilder.php', 'JMS\\Serializer\\SerializerInterface' => $vendorDir . '/jms/serializer/src/JMS/Serializer/SerializerInterface.php', 'JMS\\Serializer\\Twig\\SerializerExtension' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Twig/SerializerExtension.php', 'JMS\\Serializer\\TypeParser' => $vendorDir . '/jms/serializer/src/JMS/Serializer/TypeParser.php', 'JMS\\Serializer\\Util\\Writer' => $vendorDir . '/jms/serializer/src/JMS/Serializer/Util/Writer.php', 'JMS\\Serializer\\VisitorInterface' => $vendorDir . '/jms/serializer/src/JMS/Serializer/VisitorInterface.php', 'JMS\\Serializer\\XmlDeserializationVisitor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/XmlDeserializationVisitor.php', 'JMS\\Serializer\\XmlSerializationVisitor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/XmlSerializationVisitor.php', 'JMS\\Serializer\\YamlSerializationVisitor' => $vendorDir . '/jms/serializer/src/JMS/Serializer/YamlSerializationVisitor.php', 'JsonSchema\\Constraints\\CollectionConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php', 'JsonSchema\\Constraints\\Constraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php', 'JsonSchema\\Constraints\\ConstraintInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php', 'JsonSchema\\Constraints\\EnumConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php', 'JsonSchema\\Constraints\\FormatConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php', 'JsonSchema\\Constraints\\NumberConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/NumberConstraint.php', 'JsonSchema\\Constraints\\ObjectConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.php', 'JsonSchema\\Constraints\\SchemaConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.php', 'JsonSchema\\Constraints\\StringConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php', 'JsonSchema\\Constraints\\TypeConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php', 'JsonSchema\\Constraints\\UndefinedConstraint' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php', 'JsonSchema\\Exception\\InvalidArgumentException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php', 'JsonSchema\\Exception\\InvalidSchemaMediaTypeException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.php', 'JsonSchema\\Exception\\InvalidSourceUriException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.php', 'JsonSchema\\Exception\\JsonDecodingException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.php', 'JsonSchema\\Exception\\ResourceNotFoundException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.php', 'JsonSchema\\Exception\\UriResolverException' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.php', 'JsonSchema\\RefResolver' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/RefResolver.php', 'JsonSchema\\Uri\\Retrievers\\AbstractRetriever' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.php', 'JsonSchema\\Uri\\Retrievers\\Curl' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php', 'JsonSchema\\Uri\\Retrievers\\FileGetContents' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php', 'JsonSchema\\Uri\\Retrievers\\PredefinedArray' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php', 'JsonSchema\\Uri\\Retrievers\\UriRetrieverInterface' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php', 'JsonSchema\\Uri\\UriResolver' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php', 'JsonSchema\\Uri\\UriRetriever' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php', 'JsonSchema\\Validator' => $vendorDir . '/justinrainbow/json-schema/src/JsonSchema/Validator.php', 'KevinGH\\Version\\Version' => $vendorDir . '/kherge/version/src/lib/KevinGH/Version/Version.php', 'Metadata\\AdvancedMetadataFactoryInterface' => $vendorDir . '/jms/metadata/src/Metadata/AdvancedMetadataFactoryInterface.php', 'Metadata\\Cache\\CacheInterface' => $vendorDir . '/jms/metadata/src/Metadata/Cache/CacheInterface.php', 'Metadata\\Cache\\DoctrineCacheAdapter' => $vendorDir . '/jms/metadata/src/Metadata/Cache/DoctrineCacheAdapter.php', 'Metadata\\Cache\\FileCache' => $vendorDir . '/jms/metadata/src/Metadata/Cache/FileCache.php', 'Metadata\\ClassHierarchyMetadata' => $vendorDir . '/jms/metadata/src/Metadata/ClassHierarchyMetadata.php', 'Metadata\\ClassMetadata' => $vendorDir . '/jms/metadata/src/Metadata/ClassMetadata.php', 'Metadata\\Driver\\AbstractFileDriver' => $vendorDir . '/jms/metadata/src/Metadata/Driver/AbstractFileDriver.php', 'Metadata\\Driver\\AdvancedDriverInterface' => $vendorDir . '/jms/metadata/src/Metadata/Driver/AdvancedDriverInterface.php', 'Metadata\\Driver\\AdvancedFileLocatorInterface' => $vendorDir . '/jms/metadata/src/Metadata/Driver/AdvancedFileLocatorInterface.php', 'Metadata\\Driver\\DriverChain' => $vendorDir . '/jms/metadata/src/Metadata/Driver/DriverChain.php', 'Metadata\\Driver\\DriverInterface' => $vendorDir . '/jms/metadata/src/Metadata/Driver/DriverInterface.php', 'Metadata\\Driver\\FileLocator' => $vendorDir . '/jms/metadata/src/Metadata/Driver/FileLocator.php', 'Metadata\\Driver\\FileLocatorInterface' => $vendorDir . '/jms/metadata/src/Metadata/Driver/FileLocatorInterface.php', 'Metadata\\Driver\\LazyLoadingDriver' => $vendorDir . '/jms/metadata/src/Metadata/Driver/LazyLoadingDriver.php', 'Metadata\\MergeableClassMetadata' => $vendorDir . '/jms/metadata/src/Metadata/MergeableClassMetadata.php', 'Metadata\\MergeableInterface' => $vendorDir . '/jms/metadata/src/Metadata/MergeableInterface.php', 'Metadata\\MetadataFactory' => $vendorDir . '/jms/metadata/src/Metadata/MetadataFactory.php', 'Metadata\\MetadataFactoryInterface' => $vendorDir . '/jms/metadata/src/Metadata/MetadataFactoryInterface.php', 'Metadata\\MethodMetadata' => $vendorDir . '/jms/metadata/src/Metadata/MethodMetadata.php', 'Metadata\\NullMetadata' => $vendorDir . '/jms/metadata/src/Metadata/NullMetadata.php', 'Metadata\\PropertyMetadata' => $vendorDir . '/jms/metadata/src/Metadata/PropertyMetadata.php', 'Metadata\\Version' => $vendorDir . '/jms/metadata/src/Metadata/Version.php', 'Mockery' => $vendorDir . '/mockery/mockery/library/Mockery.php', 'Mockery\\Adapter\\Phpunit\\MockeryPHPUnitIntegration' => $vendorDir . '/mockery/mockery/library/Mockery/Adapter/Phpunit/MockeryPHPUnitIntegration.php', 'Mockery\\Adapter\\Phpunit\\MockeryTestCase' => $vendorDir . '/mockery/mockery/library/Mockery/Adapter/Phpunit/MockeryTestCase.php', 'Mockery\\Adapter\\Phpunit\\TestListener' => $vendorDir . '/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php', 'Mockery\\CompositeExpectation' => $vendorDir . '/mockery/mockery/library/Mockery/CompositeExpectation.php', 'Mockery\\Configuration' => $vendorDir . '/mockery/mockery/library/Mockery/Configuration.php', 'Mockery\\Container' => $vendorDir . '/mockery/mockery/library/Mockery/Container.php', 'Mockery\\CountValidator\\AtLeast' => $vendorDir . '/mockery/mockery/library/Mockery/CountValidator/AtLeast.php', 'Mockery\\CountValidator\\AtMost' => $vendorDir . '/mockery/mockery/library/Mockery/CountValidator/AtMost.php', 'Mockery\\CountValidator\\CountValidatorAbstract' => $vendorDir . '/mockery/mockery/library/Mockery/CountValidator/CountValidatorAbstract.php', 'Mockery\\CountValidator\\Exact' => $vendorDir . '/mockery/mockery/library/Mockery/CountValidator/Exact.php', 'Mockery\\CountValidator\\Exception' => $vendorDir . '/mockery/mockery/library/Mockery/CountValidator/Exception.php', 'Mockery\\Exception' => $vendorDir . '/mockery/mockery/library/Mockery/Exception.php', 'Mockery\\Exception\\InvalidCountException' => $vendorDir . '/mockery/mockery/library/Mockery/Exception/InvalidCountException.php', 'Mockery\\Exception\\InvalidOrderException' => $vendorDir . '/mockery/mockery/library/Mockery/Exception/InvalidOrderException.php', 'Mockery\\Exception\\NoMatchingExpectationException' => $vendorDir . '/mockery/mockery/library/Mockery/Exception/NoMatchingExpectationException.php', 'Mockery\\Exception\\RuntimeException' => $vendorDir . '/mockery/mockery/library/Mockery/Exception/RuntimeException.php', 'Mockery\\Expectation' => $vendorDir . '/mockery/mockery/library/Mockery/Expectation.php', 'Mockery\\ExpectationDirector' => $vendorDir . '/mockery/mockery/library/Mockery/ExpectationDirector.php', 'Mockery\\ExpectationInterface' => $vendorDir . '/mockery/mockery/library/Mockery/ExpectationInterface.php', 'Mockery\\Generator\\CachingGenerator' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/CachingGenerator.php', 'Mockery\\Generator\\DefinedTargetClass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/DefinedTargetClass.php', 'Mockery\\Generator\\Generator' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/Generator.php', 'Mockery\\Generator\\Method' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/Method.php', 'Mockery\\Generator\\MockConfiguration' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/MockConfiguration.php', 'Mockery\\Generator\\MockConfigurationBuilder' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/MockConfigurationBuilder.php', 'Mockery\\Generator\\MockDefinition' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/MockDefinition.php', 'Mockery\\Generator\\Parameter' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/Parameter.php', 'Mockery\\Generator\\StringManipulationGenerator' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/StringManipulationGenerator.php', 'Mockery\\Generator\\StringManipulation\\Pass\\CallTypeHintPass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/CallTypeHintPass.php', 'Mockery\\Generator\\StringManipulation\\Pass\\ClassNamePass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ClassNamePass.php', 'Mockery\\Generator\\StringManipulation\\Pass\\ClassPass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/ClassPass.php', 'Mockery\\Generator\\StringManipulation\\Pass\\InstanceMockPass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/InstanceMockPass.php', 'Mockery\\Generator\\StringManipulation\\Pass\\InterfacePass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/InterfacePass.php', 'Mockery\\Generator\\StringManipulation\\Pass\\MethodDefinitionPass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/MethodDefinitionPass.php', 'Mockery\\Generator\\StringManipulation\\Pass\\Pass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/Pass.php', 'Mockery\\Generator\\StringManipulation\\Pass\\RemoveBuiltinMethodsThatAreFinalPass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/RemoveBuiltinMethodsThatAreFinalPass.php', 'Mockery\\Generator\\StringManipulation\\Pass\\RemoveUnserializeForInternalSerializableClassesPass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/StringManipulation/Pass/RemoveUnserializeForInternalSerializableClassesPass.php', 'Mockery\\Generator\\TargetClass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/TargetClass.php', 'Mockery\\Generator\\UndefinedTargetClass' => $vendorDir . '/mockery/mockery/library/Mockery/Generator/UndefinedTargetClass.php', 'Mockery\\Instantiator' => $vendorDir . '/mockery/mockery/library/Mockery/Instantiator.php', 'Mockery\\Loader' => $vendorDir . '/mockery/mockery/library/Mockery/Loader.php', 'Mockery\\Loader\\EvalLoader' => $vendorDir . '/mockery/mockery/library/Mockery/Loader/EvalLoader.php', 'Mockery\\Loader\\Loader' => $vendorDir . '/mockery/mockery/library/Mockery/Loader/Loader.php', 'Mockery\\Loader\\RequireLoader' => $vendorDir . '/mockery/mockery/library/Mockery/Loader/RequireLoader.php', 'Mockery\\Matcher\\Any' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/Any.php', 'Mockery\\Matcher\\AnyOf' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/AnyOf.php', 'Mockery\\Matcher\\Closure' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/Closure.php', 'Mockery\\Matcher\\Contains' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/Contains.php', 'Mockery\\Matcher\\Ducktype' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/Ducktype.php', 'Mockery\\Matcher\\HasKey' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/HasKey.php', 'Mockery\\Matcher\\HasValue' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/HasValue.php', 'Mockery\\Matcher\\MatcherAbstract' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/MatcherAbstract.php', 'Mockery\\Matcher\\MustBe' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/MustBe.php', 'Mockery\\Matcher\\Not' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/Not.php', 'Mockery\\Matcher\\NotAnyOf' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/NotAnyOf.php', 'Mockery\\Matcher\\Subset' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/Subset.php', 'Mockery\\Matcher\\Type' => $vendorDir . '/mockery/mockery/library/Mockery/Matcher/Type.php', 'Mockery\\MethodCall' => $vendorDir . '/mockery/mockery/library/Mockery/MethodCall.php', 'Mockery\\Mock' => $vendorDir . '/mockery/mockery/library/Mockery/Mock.php', 'Mockery\\MockInterface' => $vendorDir . '/mockery/mockery/library/Mockery/MockInterface.php', 'Mockery\\ReceivedMethodCalls' => $vendorDir . '/mockery/mockery/library/Mockery/ReceivedMethodCalls.php', 'Mockery\\Recorder' => $vendorDir . '/mockery/mockery/library/Mockery/Recorder.php', 'Mockery\\Undefined' => $vendorDir . '/mockery/mockery/library/Mockery/Undefined.php', 'Mockery\\VerificationDirector' => $vendorDir . '/mockery/mockery/library/Mockery/VerificationDirector.php', 'Mockery\\VerificationExpectation' => $vendorDir . '/mockery/mockery/library/Mockery/VerificationExpectation.php', 'Monolog\\ErrorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/ErrorHandler.php', 'Monolog\\Formatter\\ChromePHPFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php', 'Monolog\\Formatter\\ElasticaFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php', 'Monolog\\Formatter\\FlowdockFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php', 'Monolog\\Formatter\\FluentdFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php', 'Monolog\\Formatter\\FormatterInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php', 'Monolog\\Formatter\\GelfMessageFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php', 'Monolog\\Formatter\\HtmlFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php', 'Monolog\\Formatter\\JsonFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php', 'Monolog\\Formatter\\LineFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LineFormatter.php', 'Monolog\\Formatter\\LogglyFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php', 'Monolog\\Formatter\\LogstashFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php', 'Monolog\\Formatter\\MongoDBFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php', 'Monolog\\Formatter\\NormalizerFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php', 'Monolog\\Formatter\\ScalarFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php', 'Monolog\\Formatter\\WildfireFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php', 'Monolog\\Handler\\AbstractHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php', 'Monolog\\Handler\\AbstractProcessingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php', 'Monolog\\Handler\\AbstractSyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php', 'Monolog\\Handler\\AmqpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AmqpHandler.php', 'Monolog\\Handler\\BrowserConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php', 'Monolog\\Handler\\BufferHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BufferHandler.php', 'Monolog\\Handler\\ChromePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php', 'Monolog\\Handler\\CouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php', 'Monolog\\Handler\\CubeHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CubeHandler.php', 'Monolog\\Handler\\Curl\\Util' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Curl/Util.php', 'Monolog\\Handler\\DeduplicationHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php', 'Monolog\\Handler\\DoctrineCouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php', 'Monolog\\Handler\\DynamoDbHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php', 'Monolog\\Handler\\ElasticSearchHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php', 'Monolog\\Handler\\ErrorLogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php', 'Monolog\\Handler\\FilterHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FilterHandler.php', 'Monolog\\Handler\\FingersCrossedHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php', 'Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php', 'Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php', 'Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php', 'Monolog\\Handler\\FirePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php', 'Monolog\\Handler\\FleepHookHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php', 'Monolog\\Handler\\FlowdockHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php', 'Monolog\\Handler\\GelfHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GelfHandler.php', 'Monolog\\Handler\\GroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GroupHandler.php', 'Monolog\\Handler\\HandlerInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerInterface.php', 'Monolog\\Handler\\HandlerWrapper' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php', 'Monolog\\Handler\\HipChatHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HipChatHandler.php', 'Monolog\\Handler\\IFTTTHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php', 'Monolog\\Handler\\LogEntriesHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php', 'Monolog\\Handler\\LogglyHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php', 'Monolog\\Handler\\MailHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MailHandler.php', 'Monolog\\Handler\\MandrillHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MandrillHandler.php', 'Monolog\\Handler\\MissingExtensionException' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php', 'Monolog\\Handler\\MongoDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php', 'Monolog\\Handler\\NativeMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php', 'Monolog\\Handler\\NewRelicHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php', 'Monolog\\Handler\\NullHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NullHandler.php', 'Monolog\\Handler\\PHPConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php', 'Monolog\\Handler\\PsrHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PsrHandler.php', 'Monolog\\Handler\\PushoverHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PushoverHandler.php', 'Monolog\\Handler\\RavenHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RavenHandler.php', 'Monolog\\Handler\\RedisHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RedisHandler.php', 'Monolog\\Handler\\RollbarHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RollbarHandler.php', 'Monolog\\Handler\\RotatingFileHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php', 'Monolog\\Handler\\SamplingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SamplingHandler.php', 'Monolog\\Handler\\SlackHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackHandler.php', 'Monolog\\Handler\\SocketHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php', 'Monolog\\Handler\\StreamHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php', 'Monolog\\Handler\\SwiftMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php', 'Monolog\\Handler\\SyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php', 'Monolog\\Handler\\SyslogUdpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php', 'Monolog\\Handler\\SyslogUdp\\UdpSocket' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php', 'Monolog\\Handler\\TestHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/TestHandler.php', 'Monolog\\Handler\\WhatFailureGroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php', 'Monolog\\Handler\\ZendMonitorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php', 'Monolog\\Logger' => $vendorDir . '/monolog/monolog/src/Monolog/Logger.php', 'Monolog\\Processor\\GitProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/GitProcessor.php', 'Monolog\\Processor\\IntrospectionProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php', 'Monolog\\Processor\\MemoryPeakUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php', 'Monolog\\Processor\\MemoryProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php', 'Monolog\\Processor\\MemoryUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php', 'Monolog\\Processor\\ProcessIdProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php', 'Monolog\\Processor\\PsrLogMessageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php', 'Monolog\\Processor\\TagProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php', 'Monolog\\Processor\\UidProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php', 'Monolog\\Processor\\WebProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php', 'Monolog\\Registry' => $vendorDir . '/monolog/monolog/src/Monolog/Registry.php', 'MySource_Sniffs_CSS_BrowserSpecificStylesSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php', 'MySource_Sniffs_Channels_ChannelExceptionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/ChannelExceptionSniff.php', 'MySource_Sniffs_Channels_DisallowSelfActionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php', 'MySource_Sniffs_Channels_IncludeOwnSystemSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php', 'MySource_Sniffs_Channels_IncludeSystemSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php', 'MySource_Sniffs_Channels_UnusedSystemSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php', 'MySource_Sniffs_Commenting_FunctionCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php', 'MySource_Sniffs_Debug_DebugCodeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php', 'MySource_Sniffs_Debug_FirebugConsoleSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php', 'MySource_Sniffs_Objects_AssignThisSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Objects/AssignThisSniff.php', 'MySource_Sniffs_Objects_CreateWidgetTypeCallbackSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php', 'MySource_Sniffs_Objects_DisallowNewWidgetSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php', 'MySource_Sniffs_PHP_AjaxNullComparisonSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php', 'MySource_Sniffs_PHP_EvalObjectFactorySniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php', 'MySource_Sniffs_PHP_GetRequestDataSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php', 'MySource_Sniffs_PHP_ReturnFunctionValueSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php', 'MySource_Sniffs_Strings_JoinStringsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php', 'PEAR_Sniffs_Classes_ClassDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php', 'PEAR_Sniffs_Commenting_ClassCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php', 'PEAR_Sniffs_Commenting_FileCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php', 'PEAR_Sniffs_Commenting_FunctionCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php', 'PEAR_Sniffs_Commenting_InlineCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php', 'PEAR_Sniffs_ControlStructures_ControlSignatureSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php', 'PEAR_Sniffs_ControlStructures_MultiLineConditionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php', 'PEAR_Sniffs_Files_IncludingFileSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php', 'PEAR_Sniffs_Formatting_MultiLineAssignmentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php', 'PEAR_Sniffs_Functions_FunctionCallSignatureSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php', 'PEAR_Sniffs_Functions_FunctionDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php', 'PEAR_Sniffs_Functions_ValidDefaultValueSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php', 'PEAR_Sniffs_NamingConventions_ValidClassNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php', 'PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php', 'PEAR_Sniffs_NamingConventions_ValidVariableNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php', 'PEAR_Sniffs_WhiteSpace_ObjectOperatorIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php', 'PEAR_Sniffs_WhiteSpace_ScopeClosingBraceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php', 'PEAR_Sniffs_WhiteSpace_ScopeIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php', 'PHPUnit_Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php', 'PHPUnit_Extensions_GroupTestSuite' => $vendorDir . '/phpunit/phpunit/src/Extensions/GroupTestSuite.php', 'PHPUnit_Extensions_PhptTestCase' => $vendorDir . '/phpunit/phpunit/src/Extensions/PhptTestCase.php', 'PHPUnit_Extensions_PhptTestSuite' => $vendorDir . '/phpunit/phpunit/src/Extensions/PhptTestSuite.php', 'PHPUnit_Extensions_RepeatedTest' => $vendorDir . '/phpunit/phpunit/src/Extensions/RepeatedTest.php', 'PHPUnit_Extensions_TestDecorator' => $vendorDir . '/phpunit/phpunit/src/Extensions/TestDecorator.php', 'PHPUnit_Extensions_TicketListener' => $vendorDir . '/phpunit/phpunit/src/Extensions/TicketListener.php', 'PHPUnit_Framework_Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php', 'PHPUnit_Framework_AssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/AssertionFailedError.php', 'PHPUnit_Framework_BaseTestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/BaseTestListener.php', 'PHPUnit_Framework_CodeCoverageException' => $vendorDir . '/phpunit/phpunit/src/Framework/CodeCoverageException.php', 'PHPUnit_Framework_Constraint' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint.php', 'PHPUnit_Framework_Constraint_And' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/And.php', 'PHPUnit_Framework_Constraint_ArrayHasKey' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ArrayHasKey.php', 'PHPUnit_Framework_Constraint_ArraySubset' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ArraySubset.php', 'PHPUnit_Framework_Constraint_Attribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Attribute.php', 'PHPUnit_Framework_Constraint_Callback' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Callback.php', 'PHPUnit_Framework_Constraint_ClassHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ClassHasAttribute.php', 'PHPUnit_Framework_Constraint_ClassHasStaticAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ClassHasStaticAttribute.php', 'PHPUnit_Framework_Constraint_Composite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Composite.php', 'PHPUnit_Framework_Constraint_Count' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Count.php', 'PHPUnit_Framework_Constraint_Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception.php', 'PHPUnit_Framework_Constraint_ExceptionCode' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionCode.php', 'PHPUnit_Framework_Constraint_ExceptionMessage' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessage.php', 'PHPUnit_Framework_Constraint_ExceptionMessageRegExp' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessageRegExp.php', 'PHPUnit_Framework_Constraint_FileExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/FileExists.php', 'PHPUnit_Framework_Constraint_GreaterThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/GreaterThan.php', 'PHPUnit_Framework_Constraint_IsAnything' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php', 'PHPUnit_Framework_Constraint_IsEmpty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsEmpty.php', 'PHPUnit_Framework_Constraint_IsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsEqual.php', 'PHPUnit_Framework_Constraint_IsFalse' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsFalse.php', 'PHPUnit_Framework_Constraint_IsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php', 'PHPUnit_Framework_Constraint_IsInstanceOf' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsInstanceOf.php', 'PHPUnit_Framework_Constraint_IsJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsJson.php', 'PHPUnit_Framework_Constraint_IsNull' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsNull.php', 'PHPUnit_Framework_Constraint_IsTrue' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsTrue.php', 'PHPUnit_Framework_Constraint_IsType' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsType.php', 'PHPUnit_Framework_Constraint_JsonMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php', 'PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches/ErrorMessageProvider.php', 'PHPUnit_Framework_Constraint_LessThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/LessThan.php', 'PHPUnit_Framework_Constraint_Not' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Not.php', 'PHPUnit_Framework_Constraint_ObjectHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ObjectHasAttribute.php', 'PHPUnit_Framework_Constraint_Or' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Or.php', 'PHPUnit_Framework_Constraint_PCREMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/PCREMatch.php', 'PHPUnit_Framework_Constraint_SameSize' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/SameSize.php', 'PHPUnit_Framework_Constraint_StringContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringContains.php', 'PHPUnit_Framework_Constraint_StringEndsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringEndsWith.php', 'PHPUnit_Framework_Constraint_StringMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringMatches.php', 'PHPUnit_Framework_Constraint_StringStartsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringStartsWith.php', 'PHPUnit_Framework_Constraint_TraversableContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContains.php', 'PHPUnit_Framework_Constraint_TraversableContainsOnly' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsOnly.php', 'PHPUnit_Framework_Constraint_Xor' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Xor.php', 'PHPUnit_Framework_Error' => $vendorDir . '/phpunit/phpunit/src/Framework/Error.php', 'PHPUnit_Framework_Error_Deprecated' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Deprecated.php', 'PHPUnit_Framework_Error_Notice' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Notice.php', 'PHPUnit_Framework_Error_Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Warning.php', 'PHPUnit_Framework_Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception.php', 'PHPUnit_Framework_ExceptionWrapper' => $vendorDir . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php', 'PHPUnit_Framework_ExpectationFailedException' => $vendorDir . '/phpunit/phpunit/src/Framework/ExpectationFailedException.php', 'PHPUnit_Framework_IncompleteTest' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTest.php', 'PHPUnit_Framework_IncompleteTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php', 'PHPUnit_Framework_IncompleteTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestError.php', 'PHPUnit_Framework_InvalidCoversTargetError' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidCoversTargetError.php', 'PHPUnit_Framework_InvalidCoversTargetException' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidCoversTargetException.php', 'PHPUnit_Framework_MockObject_BadMethodCallException' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/BadMethodCallException.php', 'PHPUnit_Framework_MockObject_Builder_Identity' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Identity.php', 'PHPUnit_Framework_MockObject_Builder_InvocationMocker' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/InvocationMocker.php', 'PHPUnit_Framework_MockObject_Builder_Match' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Match.php', 'PHPUnit_Framework_MockObject_Builder_MethodNameMatch' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/MethodNameMatch.php', 'PHPUnit_Framework_MockObject_Builder_Namespace' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Namespace.php', 'PHPUnit_Framework_MockObject_Builder_ParametersMatch' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/ParametersMatch.php', 'PHPUnit_Framework_MockObject_Builder_Stub' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Stub.php', 'PHPUnit_Framework_MockObject_Exception' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/Exception.php', 'PHPUnit_Framework_MockObject_Generator' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Generator.php', 'PHPUnit_Framework_MockObject_Invocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation.php', 'PHPUnit_Framework_MockObject_InvocationMocker' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/InvocationMocker.php', 'PHPUnit_Framework_MockObject_Invocation_Object' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation/Object.php', 'PHPUnit_Framework_MockObject_Invocation_Static' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation/Static.php', 'PHPUnit_Framework_MockObject_Invokable' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invokable.php', 'PHPUnit_Framework_MockObject_Matcher' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher.php', 'PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/AnyInvokedCount.php', 'PHPUnit_Framework_MockObject_Matcher_AnyParameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/AnyParameters.php', 'PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/ConsecutiveParameters.php', 'PHPUnit_Framework_MockObject_Matcher_Invocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/Invocation.php', 'PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtIndex.php', 'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtLeastCount.php', 'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtLeastOnce.php', 'PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtMostCount.php', 'PHPUnit_Framework_MockObject_Matcher_InvokedCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedCount.php', 'PHPUnit_Framework_MockObject_Matcher_InvokedRecorder' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedRecorder.php', 'PHPUnit_Framework_MockObject_Matcher_MethodName' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/MethodName.php', 'PHPUnit_Framework_MockObject_Matcher_Parameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/Parameters.php', 'PHPUnit_Framework_MockObject_Matcher_StatelessInvocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/StatelessInvocation.php', 'PHPUnit_Framework_MockObject_MockBuilder' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/MockBuilder.php', 'PHPUnit_Framework_MockObject_MockObject' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/MockObject.php', 'PHPUnit_Framework_MockObject_RuntimeException' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/RuntimeException.php', 'PHPUnit_Framework_MockObject_Stub' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub.php', 'PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ConsecutiveCalls.php', 'PHPUnit_Framework_MockObject_Stub_Exception' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/Exception.php', 'PHPUnit_Framework_MockObject_Stub_MatcherCollection' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/MatcherCollection.php', 'PHPUnit_Framework_MockObject_Stub_Return' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/Return.php', 'PHPUnit_Framework_MockObject_Stub_ReturnArgument' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnArgument.php', 'PHPUnit_Framework_MockObject_Stub_ReturnCallback' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnCallback.php', 'PHPUnit_Framework_MockObject_Stub_ReturnSelf' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnSelf.php', 'PHPUnit_Framework_MockObject_Stub_ReturnValueMap' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnValueMap.php', 'PHPUnit_Framework_MockObject_Verifiable' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Verifiable.php', 'PHPUnit_Framework_OutputError' => $vendorDir . '/phpunit/phpunit/src/Framework/OutputError.php', 'PHPUnit_Framework_RiskyTest' => $vendorDir . '/phpunit/phpunit/src/Framework/RiskyTest.php', 'PHPUnit_Framework_RiskyTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/RiskyTestError.php', 'PHPUnit_Framework_SelfDescribing' => $vendorDir . '/phpunit/phpunit/src/Framework/SelfDescribing.php', 'PHPUnit_Framework_SkippedTest' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTest.php', 'PHPUnit_Framework_SkippedTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestCase.php', 'PHPUnit_Framework_SkippedTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestError.php', 'PHPUnit_Framework_SkippedTestSuiteError' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestSuiteError.php', 'PHPUnit_Framework_SyntheticError' => $vendorDir . '/phpunit/phpunit/src/Framework/SyntheticError.php', 'PHPUnit_Framework_Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Test.php', 'PHPUnit_Framework_TestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/TestCase.php', 'PHPUnit_Framework_TestFailure' => $vendorDir . '/phpunit/phpunit/src/Framework/TestFailure.php', 'PHPUnit_Framework_TestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/TestListener.php', 'PHPUnit_Framework_TestResult' => $vendorDir . '/phpunit/phpunit/src/Framework/TestResult.php', 'PHPUnit_Framework_TestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite.php', 'PHPUnit_Framework_TestSuite_DataProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite/DataProvider.php', 'PHPUnit_Framework_UnintentionallyCoveredCodeError' => $vendorDir . '/phpunit/phpunit/src/Framework/UnintentionallyCoveredCodeError.php', 'PHPUnit_Framework_Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Warning.php', 'PHPUnit_Runner_BaseTestRunner' => $vendorDir . '/phpunit/phpunit/src/Runner/BaseTestRunner.php', 'PHPUnit_Runner_Exception' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception.php', 'PHPUnit_Runner_Filter_Factory' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Factory.php', 'PHPUnit_Runner_Filter_GroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group.php', 'PHPUnit_Runner_Filter_Group_Exclude' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group/Exclude.php', 'PHPUnit_Runner_Filter_Group_Include' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group/Include.php', 'PHPUnit_Runner_Filter_Test' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Test.php', 'PHPUnit_Runner_StandardTestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php', 'PHPUnit_Runner_TestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php', 'PHPUnit_Runner_Version' => $vendorDir . '/phpunit/phpunit/src/Runner/Version.php', 'PHPUnit_TextUI_Command' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command.php', 'PHPUnit_TextUI_ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/ResultPrinter.php', 'PHPUnit_TextUI_TestRunner' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestRunner.php', 'PHPUnit_Util_Blacklist' => $vendorDir . '/phpunit/phpunit/src/Util/Blacklist.php', 'PHPUnit_Util_Configuration' => $vendorDir . '/phpunit/phpunit/src/Util/Configuration.php', 'PHPUnit_Util_ErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Util/ErrorHandler.php', 'PHPUnit_Util_Fileloader' => $vendorDir . '/phpunit/phpunit/src/Util/Fileloader.php', 'PHPUnit_Util_Filesystem' => $vendorDir . '/phpunit/phpunit/src/Util/Filesystem.php', 'PHPUnit_Util_Filter' => $vendorDir . '/phpunit/phpunit/src/Util/Filter.php', 'PHPUnit_Util_Getopt' => $vendorDir . '/phpunit/phpunit/src/Util/Getopt.php', 'PHPUnit_Util_GlobalState' => $vendorDir . '/phpunit/phpunit/src/Util/GlobalState.php', 'PHPUnit_Util_InvalidArgumentHelper' => $vendorDir . '/phpunit/phpunit/src/Util/InvalidArgumentHelper.php', 'PHPUnit_Util_Log_JSON' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JSON.php', 'PHPUnit_Util_Log_JUnit' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JUnit.php', 'PHPUnit_Util_Log_TAP' => $vendorDir . '/phpunit/phpunit/src/Util/Log/TAP.php', 'PHPUnit_Util_PHP' => $vendorDir . '/phpunit/phpunit/src/Util/PHP.php', 'PHPUnit_Util_PHP_Default' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/Default.php', 'PHPUnit_Util_PHP_Windows' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/Windows.php', 'PHPUnit_Util_Printer' => $vendorDir . '/phpunit/phpunit/src/Util/Printer.php', 'PHPUnit_Util_Regex' => $vendorDir . '/phpunit/phpunit/src/Util/Regex.php', 'PHPUnit_Util_String' => $vendorDir . '/phpunit/phpunit/src/Util/String.php', 'PHPUnit_Util_Test' => $vendorDir . '/phpunit/phpunit/src/Util/Test.php', 'PHPUnit_Util_TestDox_NamePrettifier' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php', 'PHPUnit_Util_TestDox_ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php', 'PHPUnit_Util_TestDox_ResultPrinter_HTML' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter/HTML.php', 'PHPUnit_Util_TestDox_ResultPrinter_Text' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter/Text.php', 'PHPUnit_Util_TestSuiteIterator' => $vendorDir . '/phpunit/phpunit/src/Util/TestSuiteIterator.php', 'PHPUnit_Util_Type' => $vendorDir . '/phpunit/phpunit/src/Util/Type.php', 'PHPUnit_Util_XML' => $vendorDir . '/phpunit/phpunit/src/Util/XML.php', 'PHP_CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage.php', 'PHP_CodeCoverage_Driver' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver.php', 'PHP_CodeCoverage_Driver_HHVM' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/HHVM.php', 'PHP_CodeCoverage_Driver_PHPDBG' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/PHPDBG.php', 'PHP_CodeCoverage_Driver_Xdebug' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/Xdebug.php', 'PHP_CodeCoverage_Exception' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Exception.php', 'PHP_CodeCoverage_Exception_UnintentionallyCoveredCode' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Exception/UnintentionallyCoveredCode.php', 'PHP_CodeCoverage_Filter' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Filter.php', 'PHP_CodeCoverage_Report_Clover' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Clover.php', 'PHP_CodeCoverage_Report_Crap4j' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Crap4j.php', 'PHP_CodeCoverage_Report_Factory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Factory.php', 'PHP_CodeCoverage_Report_HTML' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML.php', 'PHP_CodeCoverage_Report_HTML_Renderer' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer.php', 'PHP_CodeCoverage_Report_HTML_Renderer_Dashboard' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Dashboard.php', 'PHP_CodeCoverage_Report_HTML_Renderer_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Directory.php', 'PHP_CodeCoverage_Report_HTML_Renderer_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/File.php', 'PHP_CodeCoverage_Report_Node' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node.php', 'PHP_CodeCoverage_Report_Node_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/Directory.php', 'PHP_CodeCoverage_Report_Node_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/File.php', 'PHP_CodeCoverage_Report_Node_Iterator' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/Iterator.php', 'PHP_CodeCoverage_Report_PHP' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/PHP.php', 'PHP_CodeCoverage_Report_Text' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Text.php', 'PHP_CodeCoverage_Report_XML' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML.php', 'PHP_CodeCoverage_Report_XML_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Directory.php', 'PHP_CodeCoverage_Report_XML_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File.php', 'PHP_CodeCoverage_Report_XML_File_Coverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Coverage.php', 'PHP_CodeCoverage_Report_XML_File_Method' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Method.php', 'PHP_CodeCoverage_Report_XML_File_Report' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Report.php', 'PHP_CodeCoverage_Report_XML_File_Unit' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Unit.php', 'PHP_CodeCoverage_Report_XML_Node' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Node.php', 'PHP_CodeCoverage_Report_XML_Project' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Project.php', 'PHP_CodeCoverage_Report_XML_Tests' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Tests.php', 'PHP_CodeCoverage_Report_XML_Totals' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Totals.php', 'PHP_CodeCoverage_Util' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Util.php', 'PHP_CodeCoverage_Util_InvalidArgumentHelper' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Util/InvalidArgumentHelper.php', 'PHP_CodeSniffer' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer.php', 'PHP_CodeSniffer_CLI' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CLI.php', 'PHP_CodeSniffer_CommentParser_AbstractDocElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/AbstractDocElement.php', 'PHP_CodeSniffer_CommentParser_AbstractParser' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/AbstractParser.php', 'PHP_CodeSniffer_CommentParser_ClassCommentParser' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/ClassCommentParser.php', 'PHP_CodeSniffer_CommentParser_CommentElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/CommentElement.php', 'PHP_CodeSniffer_CommentParser_DocElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/DocElement.php', 'PHP_CodeSniffer_CommentParser_FunctionCommentParser' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/FunctionCommentParser.php', 'PHP_CodeSniffer_CommentParser_MemberCommentParser' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/MemberCommentParser.php', 'PHP_CodeSniffer_CommentParser_PairElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/PairElement.php', 'PHP_CodeSniffer_CommentParser_ParameterElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/ParameterElement.php', 'PHP_CodeSniffer_CommentParser_ParserException' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/ParserException.php', 'PHP_CodeSniffer_CommentParser_SingleElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/SingleElement.php', 'PHP_CodeSniffer_DocGenerators_Generator' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/DocGenerators/Generator.php', 'PHP_CodeSniffer_DocGenerators_HTML' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/DocGenerators/HTML.php', 'PHP_CodeSniffer_DocGenerators_Text' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/DocGenerators/Text.php', 'PHP_CodeSniffer_Exception' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Exception.php', 'PHP_CodeSniffer_File' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/File.php', 'PHP_CodeSniffer_Report' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Report.php', 'PHP_CodeSniffer_Reporting' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reporting.php', 'PHP_CodeSniffer_Reports_Checkstyle' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Checkstyle.php', 'PHP_CodeSniffer_Reports_Csv' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Csv.php', 'PHP_CodeSniffer_Reports_Emacs' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Emacs.php', 'PHP_CodeSniffer_Reports_Full' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Full.php', 'PHP_CodeSniffer_Reports_Gitblame' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Gitblame.php', 'PHP_CodeSniffer_Reports_Hgblame' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Hgblame.php', 'PHP_CodeSniffer_Reports_Json' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Json.php', 'PHP_CodeSniffer_Reports_Junit' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Junit.php', 'PHP_CodeSniffer_Reports_Notifysend' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Notifysend.php', 'PHP_CodeSniffer_Reports_Source' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Source.php', 'PHP_CodeSniffer_Reports_Summary' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Summary.php', 'PHP_CodeSniffer_Reports_Svnblame' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Svnblame.php', 'PHP_CodeSniffer_Reports_VersionControl' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/VersionControl.php', 'PHP_CodeSniffer_Reports_Xml' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Xml.php', 'PHP_CodeSniffer_Sniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Sniff.php', 'PHP_CodeSniffer_Standards_AbstractPatternSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/AbstractPatternSniff.php', 'PHP_CodeSniffer_Standards_AbstractScopeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/AbstractScopeSniff.php', 'PHP_CodeSniffer_Standards_AbstractVariableSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/AbstractVariableSniff.php', 'PHP_CodeSniffer_Standards_IncorrectPatternException' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/IncorrectPatternException.php', 'PHP_CodeSniffer_Tokenizers_CSS' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/CSS.php', 'PHP_CodeSniffer_Tokenizers_JS' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/JS.php', 'PHP_CodeSniffer_Tokenizers_PHP' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/PHP.php', 'PHP_CodeSniffer_Tokens' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Tokens.php', 'PHP_Timer' => $vendorDir . '/phpunit/php-timer/src/Timer.php', 'PHP_Token' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_TokenWithScope' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_TokenWithScopeAndVisibility' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ABSTRACT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_AMPERSAND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_AND_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ARRAY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ARRAY_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_AS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ASYNC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_AT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_AWAIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_BACKTICK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_BAD_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_BOOLEAN_AND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_BOOLEAN_OR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_BOOL_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_BREAK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CALLABLE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CARET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CASE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CATCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CLASS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CLASS_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CLASS_NAME_CONSTANT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CLONE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CLOSE_BRACKET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CLOSE_CURLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CLOSE_SQUARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CLOSE_TAG' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_COALESCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_COLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_COMMA' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_COMMENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_COMPILER_HALT_OFFSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CONCAT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CONST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CONSTANT_ENCAPSED_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CONTINUE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_CURLY_OPEN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DEC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DECLARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DEFAULT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DIR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DIV' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DIV_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DOC_COMMENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DOLLAR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DOLLAR_OPEN_CURLY_BRACES' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DOT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DOUBLE_ARROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DOUBLE_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DOUBLE_COLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_DOUBLE_QUOTES' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ECHO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ELLIPSIS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ELSE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ELSEIF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_EMPTY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ENCAPSED_AND_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ENDDECLARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ENDFOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ENDFOREACH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ENDIF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ENDSWITCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ENDWHILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_END_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ENUM' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_EQUALS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_EVAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_EXCLAMATION_MARK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_EXIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_EXTENDS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_FILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_FINAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_FINALLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_FOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_FOREACH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_FUNCTION' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_FUNC_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_GLOBAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_GOTO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_HALT_COMPILER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_IF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_IMPLEMENTS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_IN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_INC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_INCLUDE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_INCLUDE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_INLINE_HTML' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_INSTANCEOF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_INSTEADOF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_INTERFACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_INT_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ISSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_IS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_IS_GREATER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_IS_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_IS_NOT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_IS_NOT_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_IS_SMALLER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_Includes' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_JOIN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_LAMBDA_ARROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_LAMBDA_CP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_LAMBDA_OP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_LINE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_LIST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_LNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_LOGICAL_AND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_LOGICAL_OR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_LOGICAL_XOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_METHOD_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_MINUS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_MINUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_MOD_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_MULT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_MUL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_NAMESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_NEW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_NS_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_NS_SEPARATOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_NUM_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_OBJECT_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_OBJECT_OPERATOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_ONUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_OPEN_BRACKET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_OPEN_CURLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_OPEN_SQUARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_OPEN_TAG' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_OPEN_TAG_WITH_ECHO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_PAAMAYIM_NEKUDOTAYIM' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_PERCENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_PIPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_PLUS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_PLUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_POW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_POW_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_PRINT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_PRIVATE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_PROTECTED' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_PUBLIC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_QUESTION_MARK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_REQUIRE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_REQUIRE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_RETURN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_SEMICOLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_SHAPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_SL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_SL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_SPACESHIP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_SR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_SR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_START_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_STATIC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_STRING_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_STRING_VARNAME' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_SWITCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_Stream' => $vendorDir . '/phpunit/php-token-stream/src/Token/Stream.php', 'PHP_Token_Stream_CachingFactory' => $vendorDir . '/phpunit/php-token-stream/src/Token/Stream/CachingFactory.php', 'PHP_Token_THROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_TILDE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_TRAIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_TRAIT_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_TRY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_TYPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_TYPELIST_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_TYPELIST_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_UNSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_UNSET_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_USE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_VAR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_VARIABLE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_WHERE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_WHILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_XHP_ATTRIBUTE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_XHP_CATEGORY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_XHP_CATEGORY_LABEL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_XHP_CHILDREN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_XHP_LABEL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_XHP_REQUIRED' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_XHP_TAG_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_XHP_TAG_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_XHP_TEXT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_XOR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_YIELD' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PHP_Token_YIELD_FROM' => $vendorDir . '/phpunit/php-token-stream/src/Token.php', 'PSR1_Sniffs_Classes_ClassDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php', 'PSR1_Sniffs_Files_SideEffectsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php', 'PSR1_Sniffs_Methods_CamelCapsMethodNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php', 'PSR2_Sniffs_Classes_ClassDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php', 'PSR2_Sniffs_Classes_PropertyDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php', 'PSR2_Sniffs_ControlStructures_ControlStructureSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php', 'PSR2_Sniffs_ControlStructures_ElseIfDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php', 'PSR2_Sniffs_ControlStructures_SwitchDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php', 'PSR2_Sniffs_Files_EndFileNewlineSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php', 'PSR2_Sniffs_Methods_FunctionCallSignatureSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php', 'PSR2_Sniffs_Methods_MethodDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php', 'PSR2_Sniffs_Namespaces_NamespaceDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php', 'PSR2_Sniffs_Namespaces_UseDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php', 'Parsedown' => $vendorDir . '/erusev/parsedown/Parsedown.php', 'ParsedownTest' => $vendorDir . '/erusev/parsedown/test/ParsedownTest.php', 'PhpCollection\\AbstractCollection' => $vendorDir . '/phpcollection/phpcollection/src/PhpCollection/AbstractCollection.php', 'PhpCollection\\AbstractMap' => $vendorDir . '/phpcollection/phpcollection/src/PhpCollection/AbstractMap.php', 'PhpCollection\\AbstractSequence' => $vendorDir . '/phpcollection/phpcollection/src/PhpCollection/AbstractSequence.php', 'PhpCollection\\CollectionInterface' => $vendorDir . '/phpcollection/phpcollection/src/PhpCollection/CollectionInterface.php', 'PhpCollection\\Map' => $vendorDir . '/phpcollection/phpcollection/src/PhpCollection/Map.php', 'PhpCollection\\MapInterface' => $vendorDir . '/phpcollection/phpcollection/src/PhpCollection/MapInterface.php', 'PhpCollection\\Sequence' => $vendorDir . '/phpcollection/phpcollection/src/PhpCollection/Sequence.php', 'PhpCollection\\SequenceInterface' => $vendorDir . '/phpcollection/phpcollection/src/PhpCollection/SequenceInterface.php', 'PhpCollection\\SortableInterface' => $vendorDir . '/phpcollection/phpcollection/src/PhpCollection/SortableInterface.php', 'PhpCollection\\SortedSequence' => $vendorDir . '/phpcollection/phpcollection/src/PhpCollection/SortedSequence.php', 'PhpOption\\LazyOption' => $vendorDir . '/phpoption/phpoption/src/PhpOption/LazyOption.php', 'PhpOption\\None' => $vendorDir . '/phpoption/phpoption/src/PhpOption/None.php', 'PhpOption\\Option' => $vendorDir . '/phpoption/phpoption/src/PhpOption/Option.php', 'PhpOption\\Some' => $vendorDir . '/phpoption/phpoption/src/PhpOption/Some.php', 'Pimple' => $vendorDir . '/pimple/pimple/lib/Pimple.php', 'Prophecy\\Argument' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument.php', 'Prophecy\\Argument\\ArgumentsWildcard' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/ArgumentsWildcard.php', 'Prophecy\\Argument\\Token\\AnyValueToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/AnyValueToken.php', 'Prophecy\\Argument\\Token\\AnyValuesToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/AnyValuesToken.php', 'Prophecy\\Argument\\Token\\ApproximateValueToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/ApproximateValueToken.php', 'Prophecy\\Argument\\Token\\ArrayCountToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayCountToken.php', 'Prophecy\\Argument\\Token\\ArrayEntryToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayEntryToken.php', 'Prophecy\\Argument\\Token\\ArrayEveryEntryToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/ArrayEveryEntryToken.php', 'Prophecy\\Argument\\Token\\CallbackToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/CallbackToken.php', 'Prophecy\\Argument\\Token\\ExactValueToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/ExactValueToken.php', 'Prophecy\\Argument\\Token\\IdenticalValueToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/IdenticalValueToken.php', 'Prophecy\\Argument\\Token\\LogicalAndToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/LogicalAndToken.php', 'Prophecy\\Argument\\Token\\LogicalNotToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/LogicalNotToken.php', 'Prophecy\\Argument\\Token\\ObjectStateToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/ObjectStateToken.php', 'Prophecy\\Argument\\Token\\StringContainsToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/StringContainsToken.php', 'Prophecy\\Argument\\Token\\TokenInterface' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/TokenInterface.php', 'Prophecy\\Argument\\Token\\TypeToken' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Argument/Token/TypeToken.php', 'Prophecy\\Call\\Call' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Call/Call.php', 'Prophecy\\Call\\CallCenter' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Call/CallCenter.php', 'Prophecy\\Comparator\\ClosureComparator' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Comparator/ClosureComparator.php', 'Prophecy\\Comparator\\Factory' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Comparator/Factory.php', 'Prophecy\\Comparator\\ProphecyComparator' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Comparator/ProphecyComparator.php', 'Prophecy\\Doubler\\CachedDoubler' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/CachedDoubler.php', 'Prophecy\\Doubler\\ClassPatch\\ClassPatchInterface' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ClassPatchInterface.php', 'Prophecy\\Doubler\\ClassPatch\\DisableConstructorPatch' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/DisableConstructorPatch.php', 'Prophecy\\Doubler\\ClassPatch\\HhvmExceptionPatch' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/HhvmExceptionPatch.php', 'Prophecy\\Doubler\\ClassPatch\\KeywordPatch' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/KeywordPatch.php', 'Prophecy\\Doubler\\ClassPatch\\MagicCallPatch' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/MagicCallPatch.php', 'Prophecy\\Doubler\\ClassPatch\\ProphecySubjectPatch' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php', 'Prophecy\\Doubler\\ClassPatch\\ReflectionClassNewInstancePatch' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/ReflectionClassNewInstancePatch.php', 'Prophecy\\Doubler\\ClassPatch\\SplFileInfoPatch' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/SplFileInfoPatch.php', 'Prophecy\\Doubler\\ClassPatch\\TraversablePatch' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/ClassPatch/TraversablePatch.php', 'Prophecy\\Doubler\\DoubleInterface' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/DoubleInterface.php', 'Prophecy\\Doubler\\Doubler' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/Doubler.php', 'Prophecy\\Doubler\\Generator\\ClassCodeGenerator' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCodeGenerator.php', 'Prophecy\\Doubler\\Generator\\ClassCreator' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCreator.php', 'Prophecy\\Doubler\\Generator\\ClassMirror' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassMirror.php', 'Prophecy\\Doubler\\Generator\\Node\\ArgumentNode' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ArgumentNode.php', 'Prophecy\\Doubler\\Generator\\Node\\ClassNode' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/ClassNode.php', 'Prophecy\\Doubler\\Generator\\Node\\MethodNode' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/Generator/Node/MethodNode.php', 'Prophecy\\Doubler\\Generator\\ReflectionInterface' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/Generator/ReflectionInterface.php', 'Prophecy\\Doubler\\LazyDouble' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/LazyDouble.php', 'Prophecy\\Doubler\\NameGenerator' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Doubler/NameGenerator.php', 'Prophecy\\Exception\\Call\\UnexpectedCallException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Call/UnexpectedCallException.php', 'Prophecy\\Exception\\Doubler\\ClassCreatorException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassCreatorException.php', 'Prophecy\\Exception\\Doubler\\ClassMirrorException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassMirrorException.php', 'Prophecy\\Exception\\Doubler\\ClassNotFoundException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Doubler/ClassNotFoundException.php', 'Prophecy\\Exception\\Doubler\\DoubleException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Doubler/DoubleException.php', 'Prophecy\\Exception\\Doubler\\DoublerException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Doubler/DoublerException.php', 'Prophecy\\Exception\\Doubler\\InterfaceNotFoundException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Doubler/InterfaceNotFoundException.php', 'Prophecy\\Exception\\Doubler\\MethodNotExtendableException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Doubler/MethodNotExtendableException.php', 'Prophecy\\Exception\\Doubler\\MethodNotFoundException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Doubler/MethodNotFoundException.php', 'Prophecy\\Exception\\Doubler\\ReturnByReferenceException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Doubler/ReturnByReferenceException.php', 'Prophecy\\Exception\\Exception' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Exception.php', 'Prophecy\\Exception\\InvalidArgumentException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/InvalidArgumentException.php', 'Prophecy\\Exception\\Prediction\\AggregateException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Prediction/AggregateException.php', 'Prophecy\\Exception\\Prediction\\FailedPredictionException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Prediction/FailedPredictionException.php', 'Prophecy\\Exception\\Prediction\\NoCallsException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Prediction/NoCallsException.php', 'Prophecy\\Exception\\Prediction\\PredictionException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Prediction/PredictionException.php', 'Prophecy\\Exception\\Prediction\\UnexpectedCallsCountException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Prediction/UnexpectedCallsCountException.php', 'Prophecy\\Exception\\Prediction\\UnexpectedCallsException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Prediction/UnexpectedCallsException.php', 'Prophecy\\Exception\\Prophecy\\MethodProphecyException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Prophecy/MethodProphecyException.php', 'Prophecy\\Exception\\Prophecy\\ObjectProphecyException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Prophecy/ObjectProphecyException.php', 'Prophecy\\Exception\\Prophecy\\ProphecyException' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Exception/Prophecy/ProphecyException.php', 'Prophecy\\Prediction\\CallPrediction' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prediction/CallPrediction.php', 'Prophecy\\Prediction\\CallTimesPrediction' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prediction/CallTimesPrediction.php', 'Prophecy\\Prediction\\CallbackPrediction' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prediction/CallbackPrediction.php', 'Prophecy\\Prediction\\NoCallsPrediction' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prediction/NoCallsPrediction.php', 'Prophecy\\Prediction\\PredictionInterface' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prediction/PredictionInterface.php', 'Prophecy\\Promise\\CallbackPromise' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Promise/CallbackPromise.php', 'Prophecy\\Promise\\PromiseInterface' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Promise/PromiseInterface.php', 'Prophecy\\Promise\\ReturnArgumentPromise' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Promise/ReturnArgumentPromise.php', 'Prophecy\\Promise\\ReturnPromise' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Promise/ReturnPromise.php', 'Prophecy\\Promise\\ThrowPromise' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Promise/ThrowPromise.php', 'Prophecy\\Prophecy\\MethodProphecy' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prophecy/MethodProphecy.php', 'Prophecy\\Prophecy\\ObjectProphecy' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prophecy/ObjectProphecy.php', 'Prophecy\\Prophecy\\ProphecyInterface' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prophecy/ProphecyInterface.php', 'Prophecy\\Prophecy\\ProphecySubjectInterface' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prophecy/ProphecySubjectInterface.php', 'Prophecy\\Prophecy\\Revealer' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prophecy/Revealer.php', 'Prophecy\\Prophecy\\RevealerInterface' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prophecy/RevealerInterface.php', 'Prophecy\\Prophet' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Prophet.php', 'Prophecy\\Util\\ExportUtil' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Util/ExportUtil.php', 'Prophecy\\Util\\StringUtil' => $vendorDir . '/phpspec/prophecy/src/Prophecy/Util/StringUtil.php', 'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php', 'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php', 'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php', 'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareInterface.php', 'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareTrait.php', 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', 'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', 'SebastianBergmann\\Comparator\\ArrayComparator' => $vendorDir . '/sebastian/comparator/src/ArrayComparator.php', 'SebastianBergmann\\Comparator\\Comparator' => $vendorDir . '/sebastian/comparator/src/Comparator.php', 'SebastianBergmann\\Comparator\\ComparisonFailure' => $vendorDir . '/sebastian/comparator/src/ComparisonFailure.php', 'SebastianBergmann\\Comparator\\DOMNodeComparator' => $vendorDir . '/sebastian/comparator/src/DOMNodeComparator.php', 'SebastianBergmann\\Comparator\\DateTimeComparator' => $vendorDir . '/sebastian/comparator/src/DateTimeComparator.php', 'SebastianBergmann\\Comparator\\DoubleComparator' => $vendorDir . '/sebastian/comparator/src/DoubleComparator.php', 'SebastianBergmann\\Comparator\\ExceptionComparator' => $vendorDir . '/sebastian/comparator/src/ExceptionComparator.php', 'SebastianBergmann\\Comparator\\Factory' => $vendorDir . '/sebastian/comparator/src/Factory.php', 'SebastianBergmann\\Comparator\\MockObjectComparator' => $vendorDir . '/sebastian/comparator/src/MockObjectComparator.php', 'SebastianBergmann\\Comparator\\NumericComparator' => $vendorDir . '/sebastian/comparator/src/NumericComparator.php', 'SebastianBergmann\\Comparator\\ObjectComparator' => $vendorDir . '/sebastian/comparator/src/ObjectComparator.php', 'SebastianBergmann\\Comparator\\ResourceComparator' => $vendorDir . '/sebastian/comparator/src/ResourceComparator.php', 'SebastianBergmann\\Comparator\\ScalarComparator' => $vendorDir . '/sebastian/comparator/src/ScalarComparator.php', 'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => $vendorDir . '/sebastian/comparator/src/SplObjectStorageComparator.php', 'SebastianBergmann\\Comparator\\TypeComparator' => $vendorDir . '/sebastian/comparator/src/TypeComparator.php', 'SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php', 'SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php', 'SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php', 'SebastianBergmann\\Diff\\LCS\\LongestCommonSubsequence' => $vendorDir . '/sebastian/diff/src/LCS/LongestCommonSubsequence.php', 'SebastianBergmann\\Diff\\LCS\\MemoryEfficientImplementation' => $vendorDir . '/sebastian/diff/src/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php', 'SebastianBergmann\\Diff\\LCS\\TimeEfficientImplementation' => $vendorDir . '/sebastian/diff/src/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php', 'SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php', 'SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php', 'SebastianBergmann\\Environment\\Console' => $vendorDir . '/sebastian/environment/src/Console.php', 'SebastianBergmann\\Environment\\Runtime' => $vendorDir . '/sebastian/environment/src/Runtime.php', 'SebastianBergmann\\Exporter\\Exporter' => $vendorDir . '/sebastian/exporter/src/Exporter.php', 'SebastianBergmann\\GlobalState\\Blacklist' => $vendorDir . '/sebastian/global-state/src/Blacklist.php', 'SebastianBergmann\\GlobalState\\CodeExporter' => $vendorDir . '/sebastian/global-state/src/CodeExporter.php', 'SebastianBergmann\\GlobalState\\Exception' => $vendorDir . '/sebastian/global-state/src/Exception.php', 'SebastianBergmann\\GlobalState\\Restorer' => $vendorDir . '/sebastian/global-state/src/Restorer.php', 'SebastianBergmann\\GlobalState\\RuntimeException' => $vendorDir . '/sebastian/global-state/src/RuntimeException.php', 'SebastianBergmann\\GlobalState\\Snapshot' => $vendorDir . '/sebastian/global-state/src/Snapshot.php', 'SebastianBergmann\\RecursionContext\\Context' => $vendorDir . '/sebastian/recursion-context/src/Context.php', 'SebastianBergmann\\RecursionContext\\Exception' => $vendorDir . '/sebastian/recursion-context/src/Exception.php', 'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => $vendorDir . '/sebastian/recursion-context/src/InvalidArgumentException.php', 'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php', 'Seld\\JsonLint\\JsonParser' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/JsonParser.php', 'Seld\\JsonLint\\Lexer' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/Lexer.php', 'Seld\\JsonLint\\ParsingException' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/ParsingException.php', 'Seld\\JsonLint\\Undefined' => $vendorDir . '/seld/jsonlint/src/Seld/JsonLint/Undefined.php', 'Squiz_Sniffs_Arrays_ArrayBracketSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php', 'Squiz_Sniffs_Arrays_ArrayDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php', 'Squiz_Sniffs_CSS_ClassDefinitionClosingBraceSpaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php', 'Squiz_Sniffs_CSS_ClassDefinitionNameSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php', 'Squiz_Sniffs_CSS_ClassDefinitionOpeningBraceSpaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php', 'Squiz_Sniffs_CSS_ColonSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php', 'Squiz_Sniffs_CSS_ColourDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php', 'Squiz_Sniffs_CSS_DisallowMultipleStyleDefinitionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php', 'Squiz_Sniffs_CSS_DuplicateClassDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php', 'Squiz_Sniffs_CSS_DuplicateStyleDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php', 'Squiz_Sniffs_CSS_EmptyClassDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php', 'Squiz_Sniffs_CSS_EmptyStyleDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php', 'Squiz_Sniffs_CSS_ForbiddenStylesSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php', 'Squiz_Sniffs_CSS_IndentationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/IndentationSniff.php', 'Squiz_Sniffs_CSS_LowercaseStyleDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php', 'Squiz_Sniffs_CSS_MissingColonSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php', 'Squiz_Sniffs_CSS_NamedColoursSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php', 'Squiz_Sniffs_CSS_OpacitySniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/OpacitySniff.php', 'Squiz_Sniffs_CSS_SemicolonSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php', 'Squiz_Sniffs_CSS_ShorthandSizeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php', 'Squiz_Sniffs_Classes_ClassDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php', 'Squiz_Sniffs_Classes_ClassFileNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php', 'Squiz_Sniffs_Classes_DuplicatePropertySniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php', 'Squiz_Sniffs_Classes_LowercaseClassKeywordsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php', 'Squiz_Sniffs_Classes_SelfMemberReferenceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php', 'Squiz_Sniffs_Classes_ValidClassNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php', 'Squiz_Sniffs_CodeAnalysis_EmptyStatementSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CodeAnalysis/EmptyStatementSniff.php', 'Squiz_Sniffs_Commenting_BlockCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php', 'Squiz_Sniffs_Commenting_ClassCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php', 'Squiz_Sniffs_Commenting_ClosingDeclarationCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php', 'Squiz_Sniffs_Commenting_DocCommentAlignmentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php', 'Squiz_Sniffs_Commenting_EmptyCatchCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php', 'Squiz_Sniffs_Commenting_FileCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php', 'Squiz_Sniffs_Commenting_FunctionCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php', 'Squiz_Sniffs_Commenting_FunctionCommentThrowTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php', 'Squiz_Sniffs_Commenting_InlineCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php', 'Squiz_Sniffs_Commenting_LongConditionClosingCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php', 'Squiz_Sniffs_Commenting_PostStatementCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php', 'Squiz_Sniffs_Commenting_VariableCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php', 'Squiz_Sniffs_ControlStructures_ControlSignatureSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php', 'Squiz_Sniffs_ControlStructures_ElseIfDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php', 'Squiz_Sniffs_ControlStructures_ForEachLoopDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php', 'Squiz_Sniffs_ControlStructures_ForLoopDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php', 'Squiz_Sniffs_ControlStructures_InlineIfDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php', 'Squiz_Sniffs_ControlStructures_LowercaseDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php', 'Squiz_Sniffs_ControlStructures_SwitchDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php', 'Squiz_Sniffs_Debug_JSLintSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Debug/JSLintSniff.php', 'Squiz_Sniffs_Debug_JavaScriptLintSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php', 'Squiz_Sniffs_Files_FileExtensionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php', 'Squiz_Sniffs_Formatting_OperatorBracketSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php', 'Squiz_Sniffs_Functions_FunctionDeclarationArgumentSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php', 'Squiz_Sniffs_Functions_FunctionDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php', 'Squiz_Sniffs_Functions_FunctionDuplicateArgumentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php', 'Squiz_Sniffs_Functions_GlobalFunctionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php', 'Squiz_Sniffs_Functions_LowercaseFunctionKeywordsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php', 'Squiz_Sniffs_Functions_MultiLineFunctionDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php', 'Squiz_Sniffs_NamingConventions_ConstantCaseSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/NamingConventions/ConstantCaseSniff.php', 'Squiz_Sniffs_NamingConventions_ValidFunctionNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php', 'Squiz_Sniffs_NamingConventions_ValidVariableNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php', 'Squiz_Sniffs_Objects_DisallowObjectStringIndexSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php', 'Squiz_Sniffs_Objects_ObjectInstantiationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php', 'Squiz_Sniffs_Objects_ObjectMemberCommaSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php', 'Squiz_Sniffs_Operators_ComparisonOperatorUsageSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php', 'Squiz_Sniffs_Operators_IncrementDecrementUsageSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php', 'Squiz_Sniffs_Operators_ValidLogicalOperatorsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php', 'Squiz_Sniffs_PHP_CommentedOutCodeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php', 'Squiz_Sniffs_PHP_DisallowBooleanStatementSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php', 'Squiz_Sniffs_PHP_DisallowComparisonAssignmentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php', 'Squiz_Sniffs_PHP_DisallowInlineIfSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php', 'Squiz_Sniffs_PHP_DisallowMultipleAssignmentsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php', 'Squiz_Sniffs_PHP_DisallowObEndFlushSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowObEndFlushSniff.php', 'Squiz_Sniffs_PHP_DisallowSizeFunctionsInLoopsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php', 'Squiz_Sniffs_PHP_DiscouragedFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php', 'Squiz_Sniffs_PHP_EmbeddedPhpSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php', 'Squiz_Sniffs_PHP_EvalSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/EvalSniff.php', 'Squiz_Sniffs_PHP_ForbiddenFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/ForbiddenFunctionsSniff.php', 'Squiz_Sniffs_PHP_GlobalKeywordSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php', 'Squiz_Sniffs_PHP_HeredocSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/HeredocSniff.php', 'Squiz_Sniffs_PHP_InnerFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php', 'Squiz_Sniffs_PHP_LowercasePHPFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php', 'Squiz_Sniffs_PHP_NonExecutableCodeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php', 'Squiz_Sniffs_Scope_MemberVarScopeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php', 'Squiz_Sniffs_Scope_MethodScopeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php', 'Squiz_Sniffs_Scope_StaticThisUsageSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php', 'Squiz_Sniffs_Strings_ConcatenationSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php', 'Squiz_Sniffs_Strings_DoubleQuoteUsageSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php', 'Squiz_Sniffs_Strings_EchoedStringsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php', 'Squiz_Sniffs_WhiteSpace_CastSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_ControlStructureSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_FunctionClosingBraceSpaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php', 'Squiz_Sniffs_WhiteSpace_FunctionOpeningBraceSpaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php', 'Squiz_Sniffs_WhiteSpace_FunctionSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_LanguageConstructSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_LogicalOperatorSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_MemberVarSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_ObjectOperatorSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_OperatorSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_PropertyLabelSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_ScopeClosingBraceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php', 'Squiz_Sniffs_WhiteSpace_ScopeKeywordSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_SemicolonSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php', 'Squiz_Sniffs_WhiteSpace_SuperfluousWhitespaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php', 'Symfony\\Component\\ClassLoader\\ApcClassLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/ApcClassLoader.php', 'Symfony\\Component\\ClassLoader\\ApcUniversalClassLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php', 'Symfony\\Component\\ClassLoader\\ClassCollectionLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/ClassCollectionLoader.php', 'Symfony\\Component\\ClassLoader\\ClassLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/ClassLoader.php', 'Symfony\\Component\\ClassLoader\\ClassMapGenerator' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/ClassMapGenerator.php', 'Symfony\\Component\\ClassLoader\\DebugClassLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/DebugClassLoader.php', 'Symfony\\Component\\ClassLoader\\DebugUniversalClassLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php', 'Symfony\\Component\\ClassLoader\\MapClassLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/MapClassLoader.php', 'Symfony\\Component\\ClassLoader\\Psr4ClassLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/Psr4ClassLoader.php', 'Symfony\\Component\\ClassLoader\\Tests\\ClassCollectionLoaderTest' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php', 'Symfony\\Component\\ClassLoader\\Tests\\ClassLoaderTest' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php', 'Symfony\\Component\\ClassLoader\\Tests\\ClassMapGeneratorTest' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php', 'Symfony\\Component\\ClassLoader\\Tests\\LegacyApcUniversalClassLoaderTest' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/Tests/LegacyApcUniversalClassLoaderTest.php', 'Symfony\\Component\\ClassLoader\\Tests\\LegacyUniversalClassLoaderTest' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/Tests/LegacyUniversalClassLoaderTest.php', 'Symfony\\Component\\ClassLoader\\Tests\\Psr4ClassLoaderTest' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/Tests/Psr4ClassLoaderTest.php', 'Symfony\\Component\\ClassLoader\\UniversalClassLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php', 'Symfony\\Component\\ClassLoader\\WinCacheClassLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/WinCacheClassLoader.php', 'Symfony\\Component\\ClassLoader\\XcacheClassLoader' => $vendorDir . '/symfony/class-loader/Symfony/Component/ClassLoader/XcacheClassLoader.php', 'Symfony\\Component\\Config\\ConfigCache' => $vendorDir . '/symfony/config/Symfony/Component/Config/ConfigCache.php', 'Symfony\\Component\\Config\\Definition\\ArrayNode' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/ArrayNode.php', 'Symfony\\Component\\Config\\Definition\\BaseNode' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/BaseNode.php', 'Symfony\\Component\\Config\\Definition\\BooleanNode' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/BooleanNode.php', 'Symfony\\Component\\Config\\Definition\\Builder\\ArrayNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php', 'Symfony\\Component\\Config\\Definition\\Builder\\BooleanNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.php', 'Symfony\\Component\\Config\\Definition\\Builder\\EnumNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php', 'Symfony\\Component\\Config\\Definition\\Builder\\ExprBuilder' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/ExprBuilder.php', 'Symfony\\Component\\Config\\Definition\\Builder\\FloatNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/FloatNodeDefinition.php', 'Symfony\\Component\\Config\\Definition\\Builder\\IntegerNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.php', 'Symfony\\Component\\Config\\Definition\\Builder\\MergeBuilder' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/MergeBuilder.php', 'Symfony\\Component\\Config\\Definition\\Builder\\NodeBuilder' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/NodeBuilder.php', 'Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/NodeDefinition.php', 'Symfony\\Component\\Config\\Definition\\Builder\\NodeParentInterface' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/NodeParentInterface.php', 'Symfony\\Component\\Config\\Definition\\Builder\\NormalizationBuilder' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php', 'Symfony\\Component\\Config\\Definition\\Builder\\NumericNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/NumericNodeDefinition.php', 'Symfony\\Component\\Config\\Definition\\Builder\\ParentNodeDefinitionInterface' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php', 'Symfony\\Component\\Config\\Definition\\Builder\\ScalarNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/ScalarNodeDefinition.php', 'Symfony\\Component\\Config\\Definition\\Builder\\TreeBuilder' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/TreeBuilder.php', 'Symfony\\Component\\Config\\Definition\\Builder\\ValidationBuilder' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/ValidationBuilder.php', 'Symfony\\Component\\Config\\Definition\\Builder\\VariableNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php', 'Symfony\\Component\\Config\\Definition\\ConfigurationInterface' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/ConfigurationInterface.php', 'Symfony\\Component\\Config\\Definition\\Dumper\\XmlReferenceDumper' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php', 'Symfony\\Component\\Config\\Definition\\Dumper\\YamlReferenceDumper' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php', 'Symfony\\Component\\Config\\Definition\\EnumNode' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/EnumNode.php', 'Symfony\\Component\\Config\\Definition\\Exception\\DuplicateKeyException' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Exception/DuplicateKeyException.php', 'Symfony\\Component\\Config\\Definition\\Exception\\Exception' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Exception/Exception.php', 'Symfony\\Component\\Config\\Definition\\Exception\\ForbiddenOverwriteException' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.php', 'Symfony\\Component\\Config\\Definition\\Exception\\InvalidConfigurationException' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.php', 'Symfony\\Component\\Config\\Definition\\Exception\\InvalidDefinitionException' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.php', 'Symfony\\Component\\Config\\Definition\\Exception\\InvalidTypeException' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Exception/InvalidTypeException.php', 'Symfony\\Component\\Config\\Definition\\Exception\\UnsetKeyException' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Exception/UnsetKeyException.php', 'Symfony\\Component\\Config\\Definition\\FloatNode' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/FloatNode.php', 'Symfony\\Component\\Config\\Definition\\IntegerNode' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/IntegerNode.php', 'Symfony\\Component\\Config\\Definition\\NodeInterface' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/NodeInterface.php', 'Symfony\\Component\\Config\\Definition\\NumericNode' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/NumericNode.php', 'Symfony\\Component\\Config\\Definition\\Processor' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/Processor.php', 'Symfony\\Component\\Config\\Definition\\PrototypeNodeInterface' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/PrototypeNodeInterface.php', 'Symfony\\Component\\Config\\Definition\\PrototypedArrayNode' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/PrototypedArrayNode.php', 'Symfony\\Component\\Config\\Definition\\ReferenceDumper' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/ReferenceDumper.php', 'Symfony\\Component\\Config\\Definition\\ScalarNode' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/ScalarNode.php', 'Symfony\\Component\\Config\\Definition\\VariableNode' => $vendorDir . '/symfony/config/Symfony/Component/Config/Definition/VariableNode.php', 'Symfony\\Component\\Config\\Exception\\FileLoaderImportCircularReferenceException' => $vendorDir . '/symfony/config/Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.php', 'Symfony\\Component\\Config\\Exception\\FileLoaderLoadException' => $vendorDir . '/symfony/config/Symfony/Component/Config/Exception/FileLoaderLoadException.php', 'Symfony\\Component\\Config\\FileLocator' => $vendorDir . '/symfony/config/Symfony/Component/Config/FileLocator.php', 'Symfony\\Component\\Config\\FileLocatorInterface' => $vendorDir . '/symfony/config/Symfony/Component/Config/FileLocatorInterface.php', 'Symfony\\Component\\Config\\Loader\\DelegatingLoader' => $vendorDir . '/symfony/config/Symfony/Component/Config/Loader/DelegatingLoader.php', 'Symfony\\Component\\Config\\Loader\\FileLoader' => $vendorDir . '/symfony/config/Symfony/Component/Config/Loader/FileLoader.php', 'Symfony\\Component\\Config\\Loader\\Loader' => $vendorDir . '/symfony/config/Symfony/Component/Config/Loader/Loader.php', 'Symfony\\Component\\Config\\Loader\\LoaderInterface' => $vendorDir . '/symfony/config/Symfony/Component/Config/Loader/LoaderInterface.php', 'Symfony\\Component\\Config\\Loader\\LoaderResolver' => $vendorDir . '/symfony/config/Symfony/Component/Config/Loader/LoaderResolver.php', 'Symfony\\Component\\Config\\Loader\\LoaderResolverInterface' => $vendorDir . '/symfony/config/Symfony/Component/Config/Loader/LoaderResolverInterface.php', 'Symfony\\Component\\Config\\Resource\\DirectoryResource' => $vendorDir . '/symfony/config/Symfony/Component/Config/Resource/DirectoryResource.php', 'Symfony\\Component\\Config\\Resource\\FileResource' => $vendorDir . '/symfony/config/Symfony/Component/Config/Resource/FileResource.php', 'Symfony\\Component\\Config\\Resource\\ResourceInterface' => $vendorDir . '/symfony/config/Symfony/Component/Config/Resource/ResourceInterface.php', 'Symfony\\Component\\Config\\Tests\\ConfigCacheTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/ConfigCacheTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\ArrayNodeTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\BooleanNodeTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/BooleanNodeTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Builder\\ArrayNodeDefinitionTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Builder\\BarNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Builder\\EnumNodeDefinitionTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Builder\\ExprBuilderTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Builder\\NodeBuilder' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Builder\\NodeBuilderTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Builder\\NumericNodeDefinitionTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Builder\\SomeNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Builder\\TreeBuilderTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Builder\\VariableNodeDefinition' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Dumper\\XmlReferenceDumperTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\Dumper\\YamlReferenceDumperTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\EnumNodeTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/EnumNodeTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\FinalizationTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/FinalizationTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\FloatNodeTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/FloatNodeTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\IntegerNodeTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/IntegerNodeTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\MergeTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/MergeTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\NormalizationTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/NormalizationTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\PrototypedArrayNodeTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.php', 'Symfony\\Component\\Config\\Tests\\Definition\\ScalarNodeTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php', 'Symfony\\Component\\Config\\Tests\\Exception\\FileLoaderLoadExceptionTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Exception/FileLoaderLoadExceptionTest.php', 'Symfony\\Component\\Config\\Tests\\FileLocatorTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/FileLocatorTest.php', 'Symfony\\Component\\Config\\Tests\\Fixtures\\Configuration\\ExampleConfiguration' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.php', 'Symfony\\Component\\Config\\Tests\\Loader\\DelegatingLoaderTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Loader/DelegatingLoaderTest.php', 'Symfony\\Component\\Config\\Tests\\Loader\\FileLoaderTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php', 'Symfony\\Component\\Config\\Tests\\Loader\\LoaderResolverTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Loader/LoaderResolverTest.php', 'Symfony\\Component\\Config\\Tests\\Loader\\LoaderTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Loader/LoaderTest.php', 'Symfony\\Component\\Config\\Tests\\Loader\\ProjectLoader1' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Loader/LoaderTest.php', 'Symfony\\Component\\Config\\Tests\\Loader\\TestFileLoader' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php', 'Symfony\\Component\\Config\\Tests\\Loader\\Validator' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php', 'Symfony\\Component\\Config\\Tests\\Loader\\XmlUtilsTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php', 'Symfony\\Component\\Config\\Tests\\Resource\\DirectoryResourceTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.php', 'Symfony\\Component\\Config\\Tests\\Resource\\FileResourceTest' => $vendorDir . '/symfony/config/Symfony/Component/Config/Tests/Resource/FileResourceTest.php', 'Symfony\\Component\\Config\\Util\\XmlUtils' => $vendorDir . '/symfony/config/Symfony/Component/Config/Util/XmlUtils.php', 'Symfony\\Component\\Console\\Application' => $vendorDir . '/symfony/console/Symfony/Component/Console/Application.php', 'Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/symfony/console/Symfony/Component/Console/Command/Command.php', 'Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/symfony/console/Symfony/Component/Console/Command/HelpCommand.php', 'Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/symfony/console/Symfony/Component/Console/Command/ListCommand.php', 'Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/symfony/console/Symfony/Component/Console/ConsoleEvents.php', 'Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/ApplicationDescription.php', 'Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/Descriptor.php', 'Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/DescriptorInterface.php', 'Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/JsonDescriptor.php', 'Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php', 'Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/TextDescriptor.php', 'Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/symfony/console/Symfony/Component/Console/Descriptor/XmlDescriptor.php', 'Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/symfony/console/Symfony/Component/Console/Event/ConsoleCommandEvent.php', 'Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/symfony/console/Symfony/Component/Console/Event/ConsoleEvent.php', 'Symfony\\Component\\Console\\Event\\ConsoleExceptionEvent' => $vendorDir . '/symfony/console/Symfony/Component/Console/Event/ConsoleExceptionEvent.php', 'Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/symfony/console/Symfony/Component/Console/Event/ConsoleTerminateEvent.php', 'Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php', 'Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterInterface.php', 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyle.php', 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php', 'Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php', 'Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/DebugFormatterHelper.php', 'Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/DescriptorHelper.php', 'Symfony\\Component\\Console\\Helper\\DialogHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/DialogHelper.php', 'Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/FormatterHelper.php', 'Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/Helper.php', 'Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/HelperInterface.php', 'Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/HelperSet.php', 'Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/InputAwareHelper.php', 'Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/ProcessHelper.php', 'Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/ProgressBar.php', 'Symfony\\Component\\Console\\Helper\\ProgressHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/ProgressHelper.php', 'Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/QuestionHelper.php', 'Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/Table.php', 'Symfony\\Component\\Console\\Helper\\TableHelper' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/TableHelper.php', 'Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/TableSeparator.php', 'Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/symfony/console/Symfony/Component/Console/Helper/TableStyle.php', 'Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/ArgvInput.php', 'Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/ArrayInput.php', 'Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/Input.php', 'Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/InputArgument.php', 'Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/InputAwareInterface.php', 'Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/InputDefinition.php', 'Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/InputInterface.php', 'Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/InputOption.php', 'Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Input/StringInput.php', 'Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/symfony/console/Symfony/Component/Console/Logger/ConsoleLogger.php', 'Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/BufferedOutput.php', 'Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php', 'Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/ConsoleOutputInterface.php', 'Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/NullOutput.php', 'Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/Output.php', 'Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/OutputInterface.php', 'Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Output/StreamOutput.php', 'Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/symfony/console/Symfony/Component/Console/Question/ChoiceQuestion.php', 'Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/symfony/console/Symfony/Component/Console/Question/ConfirmationQuestion.php', 'Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/symfony/console/Symfony/Component/Console/Question/Question.php', 'Symfony\\Component\\Console\\Shell' => $vendorDir . '/symfony/console/Symfony/Component/Console/Shell.php', 'Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tester/ApplicationTester.php', 'Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tester/CommandTester.php', 'Symfony\\Component\\Console\\Tests\\ApplicationTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/ApplicationTest.php', 'Symfony\\Component\\Console\\Tests\\Command\\CommandTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Command/CommandTest.php', 'Symfony\\Component\\Console\\Tests\\Command\\HelpCommandTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Command/HelpCommandTest.php', 'Symfony\\Component\\Console\\Tests\\Command\\ListCommandTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Command/ListCommandTest.php', 'Symfony\\Component\\Console\\Tests\\CustomApplication' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/ApplicationTest.php', 'Symfony\\Component\\Console\\Tests\\CustomDefaultCommandApplication' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/ApplicationTest.php', 'Symfony\\Component\\Console\\Tests\\Descriptor\\AbstractDescriptorTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.php', 'Symfony\\Component\\Console\\Tests\\Descriptor\\JsonDescriptorTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php', 'Symfony\\Component\\Console\\Tests\\Descriptor\\MarkdownDescriptorTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.php', 'Symfony\\Component\\Console\\Tests\\Descriptor\\ObjectsProvider' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php', 'Symfony\\Component\\Console\\Tests\\Descriptor\\TextDescriptorTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.php', 'Symfony\\Component\\Console\\Tests\\Descriptor\\XmlDescriptorTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.php', 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorApplication1' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php', 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorApplication2' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.php', 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorCommand1' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php', 'Symfony\\Component\\Console\\Tests\\Fixtures\\DescriptorCommand2' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php', 'Symfony\\Component\\Console\\Tests\\Fixtures\\DummyOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Fixtures/DummyOutput.php', 'Symfony\\Component\\Console\\Tests\\Formatter\\OutputFormatterStyleStackTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleStackTest.php', 'Symfony\\Component\\Console\\Tests\\Formatter\\OutputFormatterStyleTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleTest.php', 'Symfony\\Component\\Console\\Tests\\Formatter\\OutputFormatterTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php', 'Symfony\\Component\\Console\\Tests\\Formatter\\TableCell' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php', 'Symfony\\Component\\Console\\Tests\\Helper\\FormatterHelperTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Helper/FormatterHelperTest.php', 'Symfony\\Component\\Console\\Tests\\Helper\\HelperSetTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Helper/HelperSetTest.php', 'Symfony\\Component\\Console\\Tests\\Helper\\LegacyDialogHelperTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Helper/LegacyDialogHelperTest.php', 'Symfony\\Component\\Console\\Tests\\Helper\\LegacyProgressHelperTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Helper/LegacyProgressHelperTest.php', 'Symfony\\Component\\Console\\Tests\\Helper\\LegacyTableHelperTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Helper/LegacyTableHelperTest.php', 'Symfony\\Component\\Console\\Tests\\Helper\\ProcessHelperTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Helper/ProcessHelperTest.php', 'Symfony\\Component\\Console\\Tests\\Helper\\ProgressBarTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php', 'Symfony\\Component\\Console\\Tests\\Helper\\QuestionHelperTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php', 'Symfony\\Component\\Console\\Tests\\Helper\\TableTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Helper/TableTest.php', 'Symfony\\Component\\Console\\Tests\\Input\\ArgvInputTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Input/ArgvInputTest.php', 'Symfony\\Component\\Console\\Tests\\Input\\ArrayInputTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Input/ArrayInputTest.php', 'Symfony\\Component\\Console\\Tests\\Input\\InputArgumentTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Input/InputArgumentTest.php', 'Symfony\\Component\\Console\\Tests\\Input\\InputDefinitionTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Input/InputDefinitionTest.php', 'Symfony\\Component\\Console\\Tests\\Input\\InputOptionTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Input/InputOptionTest.php', 'Symfony\\Component\\Console\\Tests\\Input\\InputTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Input/InputTest.php', 'Symfony\\Component\\Console\\Tests\\Input\\StringInputTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Input/StringInputTest.php', 'Symfony\\Component\\Console\\Tests\\Logger\\ConsoleLoggerTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Logger/ConsoleLoggerTest.php', 'Symfony\\Component\\Console\\Tests\\Output\\ConsoleOutputTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php', 'Symfony\\Component\\Console\\Tests\\Output\\NullOutputTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Output/NullOutputTest.php', 'Symfony\\Component\\Console\\Tests\\Output\\OutputTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Output/OutputTest.php', 'Symfony\\Component\\Console\\Tests\\Output\\StreamOutputTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Output/StreamOutputTest.php', 'Symfony\\Component\\Console\\Tests\\Output\\TestOutput' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Output/OutputTest.php', 'Symfony\\Component\\Console\\Tests\\Tester\\ApplicationTesterTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.php', 'Symfony\\Component\\Console\\Tests\\Tester\\CommandTesterTest' => $vendorDir . '/symfony/console/Symfony/Component/Console/Tests/Tester/CommandTesterTest.php', 'Symfony\\Component\\DependencyInjection\\Alias' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Alias.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\AnalyzeServiceReferencesPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckCircularReferencesPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckDefinitionValidityPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckExceptionOnInvalidReferenceBehaviorPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CheckReferenceValidityPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\Compiler' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/Compiler.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\CompilerPassInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CompilerPassInterface.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\DecoratorServicePass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\InlineServiceDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\LoggingFormatter' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\MergeExtensionConfigurationPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\PassConfig' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/PassConfig.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\RemoveAbstractDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\RemovePrivateAliasesPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\RemoveUnusedDefinitionsPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\RepeatablePassInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\RepeatedPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ReplaceAliasByActualDefinitionPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveDefinitionTemplatesPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveInvalidReferencesPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveParameterPlaceHoldersPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ResolveReferencesToAliasesPass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraph' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphEdge' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php', 'Symfony\\Component\\DependencyInjection\\Compiler\\ServiceReferenceGraphNode' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php', 'Symfony\\Component\\DependencyInjection\\Container' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Container.php', 'Symfony\\Component\\DependencyInjection\\ContainerAware' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerAware.php', 'Symfony\\Component\\DependencyInjection\\ContainerAwareInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerAwareInterface.php', 'Symfony\\Component\\DependencyInjection\\ContainerAwareTrait' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerAwareTrait.php', 'Symfony\\Component\\DependencyInjection\\ContainerBuilder' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerBuilder.php', 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerInterface.php', 'Symfony\\Component\\DependencyInjection\\Definition' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Definition.php', 'Symfony\\Component\\DependencyInjection\\DefinitionDecorator' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/DefinitionDecorator.php', 'Symfony\\Component\\DependencyInjection\\Dump\\Container' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php', 'Symfony\\Component\\DependencyInjection\\Dumper\\Dumper' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/Dumper.php', 'Symfony\\Component\\DependencyInjection\\Dumper\\DumperInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/DumperInterface.php', 'Symfony\\Component\\DependencyInjection\\Dumper\\GraphvizDumper' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php', 'Symfony\\Component\\DependencyInjection\\Dumper\\PhpDumper' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php', 'Symfony\\Component\\DependencyInjection\\Dumper\\XmlDumper' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php', 'Symfony\\Component\\DependencyInjection\\Dumper\\YamlDumper' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php', 'Symfony\\Component\\DependencyInjection\\Exception\\BadMethodCallException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ExceptionInterface.php', 'Symfony\\Component\\DependencyInjection\\Exception\\InactiveScopeException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/InvalidArgumentException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\LogicException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/LogicException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\ParameterCircularReferenceException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\ParameterNotFoundException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ParameterNotFoundException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/RuntimeException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\ScopeCrossingInjectionException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\ScopeWideningInjectionException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\ServiceCircularReferenceException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.php', 'Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php', 'Symfony\\Component\\DependencyInjection\\ExpressionLanguage' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ExpressionLanguage.php', 'Symfony\\Component\\DependencyInjection\\ExpressionLanguageProvider' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ExpressionLanguageProvider.php', 'Symfony\\Component\\DependencyInjection\\Extension\\ConfigurationExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.php', 'Symfony\\Component\\DependencyInjection\\Extension\\Extension' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/Extension.php', 'Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php', 'Symfony\\Component\\DependencyInjection\\Extension\\PrependExtensionInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/PrependExtensionInterface.php', 'Symfony\\Component\\DependencyInjection\\IntrospectableContainerInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/IntrospectableContainerInterface.php', 'Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\InstantiatorInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.php', 'Symfony\\Component\\DependencyInjection\\LazyProxy\\Instantiator\\RealServiceInstantiator' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.php', 'Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\DumperInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php', 'Symfony\\Component\\DependencyInjection\\LazyProxy\\PhpDumper\\NullDumper' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php', 'Symfony\\Component\\DependencyInjection\\Loader\\ClosureLoader' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/ClosureLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\FileLoader' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/FileLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\IniFileLoader' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/IniFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php', 'Symfony\\Component\\DependencyInjection\\Parameter' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Parameter.php', 'Symfony\\Component\\DependencyInjection\\ParameterBag\\FrozenParameterBag' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.php', 'Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php', 'Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php', 'Symfony\\Component\\DependencyInjection\\Reference' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Reference.php', 'Symfony\\Component\\DependencyInjection\\Scope' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Scope.php', 'Symfony\\Component\\DependencyInjection\\ScopeInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/ScopeInterface.php', 'Symfony\\Component\\DependencyInjection\\SimpleXMLElement' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/SimpleXMLElement.php', 'Symfony\\Component\\DependencyInjection\\TaggedContainerInterface' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/TaggedContainerInterface.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\AnalyzeServiceReferencesPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\CheckCircularReferencesPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\CheckDefinitionValidityPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\CheckExceptionOnInvalidReferenceBehaviorPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\CheckReferenceValidityPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\DecoratorServicePassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\InlineServiceDefinitionsPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\IntegrationTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\LegacyResolveParameterPlaceHoldersPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/LegacyResolveParameterPlaceHoldersPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\MergeExtensionConfigurationPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\RemoveUnusedDefinitionsPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\ReplaceAliasByActualDefinitionPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\ResolveDefinitionTemplatesPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\ResolveInvalidReferencesPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\ResolveParameterPlaceHoldersPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\ResolveReferencesToAliasesPassTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\ContainerBuilderTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\ContainerTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ContainerTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\CrossCheckTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\DefinitionDecoratorTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\DefinitionTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Dumper\\GraphvizDumperTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Dumper\\PhpDumperTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Dumper\\XmlDumperTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Dumper\\YamlDumperTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Extension\\ExtensionTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\FooClass' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\LazyProxy\\Instantiator\\RealServiceInstantiatorTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\LazyProxy\\PhpDumper\\NullDumperTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\LegacyContainerBuilderTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/LegacyContainerBuilderTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\LegacyDefinitionTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/LegacyDefinitionTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Loader\\ClosureLoaderTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Loader\\IniFileLoaderTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Loader\\PhpFileLoaderTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Loader\\XmlFileLoaderTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\Loader\\YamlFileLoaderTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\ParameterBag\\FrozenParameterBagTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\ParameterBag\\ParameterBagTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\ParameterTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ParameterTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\ProjectContainer' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\ProjectServiceContainer' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ContainerTest.php', 'Symfony\\Component\\DependencyInjection\\Tests\\ReferenceTest' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ReferenceTest.php', 'Symfony\\Component\\DependencyInjection\\Variable' => $vendorDir . '/symfony/dependency-injection/Symfony/Component/DependencyInjection/Variable.php', 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php', 'Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/WrappedListener.php', 'Symfony\\Component\\EventDispatcher\\DependencyInjection\\RegisterListenersPass' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php', 'Symfony\\Component\\EventDispatcher\\Event' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Event.php', 'Symfony\\Component\\EventDispatcher\\EventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcherInterface.php', 'Symfony\\Component\\EventDispatcher\\EventSubscriberInterface' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventSubscriberInterface.php', 'Symfony\\Component\\EventDispatcher\\GenericEvent' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/GenericEvent.php', 'Symfony\\Component\\EventDispatcher\\ImmutableEventDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php', 'Symfony\\Component\\EventDispatcher\\Tests\\AbstractEventDispatcherTest' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\CallableClass' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\ContainerAwareEventDispatcherTest' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\Debug\\EventSubscriber' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\Debug\\TraceableEventDispatcherTest' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\DependencyInjection\\RegisterListenersPassTest' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\DependencyInjection\\SubscriberService' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\EventDispatcherTest' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\EventTest' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/EventTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\GenericEventTest' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/GenericEventTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\ImmutableEventDispatcherTest' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/ImmutableEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\Service' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\SubscriberService' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\TestEventListener' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\TestEventSubscriber' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\TestEventSubscriberWithMultipleListeners' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\TestEventSubscriberWithPriorities' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php', 'Symfony\\Component\\EventDispatcher\\Tests\\TestWithDispatcher' => $vendorDir . '/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php', 'Symfony\\Component\\ExpressionLanguage\\Compiler' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Compiler.php', 'Symfony\\Component\\ExpressionLanguage\\Expression' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Expression.php', 'Symfony\\Component\\ExpressionLanguage\\ExpressionFunction' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/ExpressionFunction.php', 'Symfony\\Component\\ExpressionLanguage\\ExpressionFunctionProviderInterface' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/ExpressionFunctionProviderInterface.php', 'Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php', 'Symfony\\Component\\ExpressionLanguage\\Lexer' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Lexer.php', 'Symfony\\Component\\ExpressionLanguage\\Node\\ArgumentsNode' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/ArgumentsNode.php', 'Symfony\\Component\\ExpressionLanguage\\Node\\ArrayNode' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/ArrayNode.php', 'Symfony\\Component\\ExpressionLanguage\\Node\\BinaryNode' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php', 'Symfony\\Component\\ExpressionLanguage\\Node\\ConditionalNode' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/ConditionalNode.php', 'Symfony\\Component\\ExpressionLanguage\\Node\\ConstantNode' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/ConstantNode.php', 'Symfony\\Component\\ExpressionLanguage\\Node\\FunctionNode' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/FunctionNode.php', 'Symfony\\Component\\ExpressionLanguage\\Node\\GetAttrNode' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php', 'Symfony\\Component\\ExpressionLanguage\\Node\\NameNode' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/NameNode.php', 'Symfony\\Component\\ExpressionLanguage\\Node\\Node' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/Node.php', 'Symfony\\Component\\ExpressionLanguage\\Node\\UnaryNode' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Node/UnaryNode.php', 'Symfony\\Component\\ExpressionLanguage\\ParsedExpression' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/ParsedExpression.php', 'Symfony\\Component\\ExpressionLanguage\\Parser' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Parser.php', 'Symfony\\Component\\ExpressionLanguage\\ParserCache\\ArrayParserCache' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/ParserCache/ArrayParserCache.php', 'Symfony\\Component\\ExpressionLanguage\\ParserCache\\ParserCacheInterface' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/ParserCache/ParserCacheInterface.php', 'Symfony\\Component\\ExpressionLanguage\\SerializedParsedExpression' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/SerializedParsedExpression.php', 'Symfony\\Component\\ExpressionLanguage\\SyntaxError' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/SyntaxError.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\ExpressionLanguageTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\ExpressionTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/ExpressionTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Fixtures\\TestProvider' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Fixtures/TestProvider.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\LexerTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\AbstractNodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/AbstractNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\ArgumentsNodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/ArgumentsNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\ArrayNodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/ArrayNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\BinaryNodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/BinaryNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\ConditionalNodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/ConditionalNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\ConstantNodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/ConstantNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\FunctionNodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/FunctionNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\GetAttrNodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/GetAttrNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\NameNodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/NameNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\NodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/NodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\Obj' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/GetAttrNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\Node\\UnaryNodeTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/Node/UnaryNodeTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\ParsedExpressionTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/ParsedExpressionTest.php', 'Symfony\\Component\\ExpressionLanguage\\Tests\\ParserTest' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php', 'Symfony\\Component\\ExpressionLanguage\\Token' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/Token.php', 'Symfony\\Component\\ExpressionLanguage\\TokenStream' => $vendorDir . '/symfony/expression-language/Symfony/Component/ExpressionLanguage/TokenStream.php', 'Symfony\\Component\\Filesystem\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/filesystem/Symfony/Component/Filesystem/Exception/ExceptionInterface.php', 'Symfony\\Component\\Filesystem\\Exception\\IOException' => $vendorDir . '/symfony/filesystem/Symfony/Component/Filesystem/Exception/IOException.php', 'Symfony\\Component\\Filesystem\\Filesystem' => $vendorDir . '/symfony/filesystem/Symfony/Component/Filesystem/Filesystem.php', 'Symfony\\Component\\Filesystem\\Tests\\FilesystemTest' => $vendorDir . '/symfony/filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.php', 'Symfony\\Component\\Finder\\Adapter\\AbstractAdapter' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php', 'Symfony\\Component\\Finder\\Adapter\\AbstractFindAdapter' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php', 'Symfony\\Component\\Finder\\Adapter\\AdapterInterface' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php', 'Symfony\\Component\\Finder\\Adapter\\BsdFindAdapter' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php', 'Symfony\\Component\\Finder\\Adapter\\GnuFindAdapter' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php', 'Symfony\\Component\\Finder\\Adapter\\PhpAdapter' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php', 'Symfony\\Component\\Finder\\Comparator\\Comparator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Comparator/Comparator.php', 'Symfony\\Component\\Finder\\Comparator\\DateComparator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php', 'Symfony\\Component\\Finder\\Comparator\\NumberComparator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php', 'Symfony\\Component\\Finder\\Exception\\AccessDeniedException' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php', 'Symfony\\Component\\Finder\\Exception\\AdapterFailureException' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php', 'Symfony\\Component\\Finder\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php', 'Symfony\\Component\\Finder\\Exception\\OperationNotPermitedException' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.php', 'Symfony\\Component\\Finder\\Exception\\ShellCommandFailureException' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php', 'Symfony\\Component\\Finder\\Expression\\Expression' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Expression/Expression.php', 'Symfony\\Component\\Finder\\Expression\\Glob' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Expression/Glob.php', 'Symfony\\Component\\Finder\\Expression\\Regex' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Expression/Regex.php', 'Symfony\\Component\\Finder\\Expression\\ValueInterface' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Expression/ValueInterface.php', 'Symfony\\Component\\Finder\\Finder' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Finder.php', 'Symfony\\Component\\Finder\\Glob' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Glob.php', 'Symfony\\Component\\Finder\\Iterator\\CustomFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\DateRangeFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\DepthRangeFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\ExcludeDirectoryFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\FilePathsIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php', 'Symfony\\Component\\Finder\\Iterator\\FileTypeFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\FilecontentFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\FilenameFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\FilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\MultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\PathFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\RecursiveDirectoryIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php', 'Symfony\\Component\\Finder\\Iterator\\SizeRangeFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php', 'Symfony\\Component\\Finder\\Iterator\\SortableIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.php', 'Symfony\\Component\\Finder\\Shell\\Command' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Shell/Command.php', 'Symfony\\Component\\Finder\\Shell\\Shell' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Shell/Shell.php', 'Symfony\\Component\\Finder\\SplFileInfo' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/SplFileInfo.php', 'Symfony\\Component\\Finder\\Tests\\Comparator\\ComparatorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Comparator/ComparatorTest.php', 'Symfony\\Component\\Finder\\Tests\\Comparator\\DateComparatorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.php', 'Symfony\\Component\\Finder\\Tests\\Comparator\\NumberComparatorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.php', 'Symfony\\Component\\Finder\\Tests\\Expression\\ExpressionTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Expression/ExpressionTest.php', 'Symfony\\Component\\Finder\\Tests\\Expression\\GlobTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Expression/GlobTest.php', 'Symfony\\Component\\Finder\\Tests\\Expression\\RegexTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Expression/RegexTest.php', 'Symfony\\Component\\Finder\\Tests\\FakeAdapter\\DummyAdapter' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php', 'Symfony\\Component\\Finder\\Tests\\FakeAdapter\\FailingAdapter' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php', 'Symfony\\Component\\Finder\\Tests\\FakeAdapter\\NamedAdapter' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php', 'Symfony\\Component\\Finder\\Tests\\FakeAdapter\\UnsupportedAdapter' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php', 'Symfony\\Component\\Finder\\Tests\\FinderTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/FinderTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\CustomFilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\DateRangeFilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\DepthRangeFilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\ExcludeDirectoryFilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\FilePathsIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\FileTypeFilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\FilecontentFilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\FilenameFilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\FilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\InnerNameIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\InnerSizeIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\InnerTypeIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\Iterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/Iterator.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\IteratorTestCase' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\MockFileListIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\MockSplFileInfo' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\MultiplePcreFilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\PathFilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\RealIteratorTestCase' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\RecursiveDirectoryIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\SizeRangeFilterIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\SortableIteratorTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Iterator\\TestMultiplePcreFilterIterator' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php', 'Symfony\\Component\\Finder\\Tests\\Shell\\CommandTest' => $vendorDir . '/symfony/finder/Symfony/Component/Finder/Tests/Shell/CommandTest.php', 'Symfony\\Component\\Process\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/process/Symfony/Component/Process/Exception/ExceptionInterface.php', 'Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/process/Symfony/Component/Process/Exception/InvalidArgumentException.php', 'Symfony\\Component\\Process\\Exception\\LogicException' => $vendorDir . '/symfony/process/Symfony/Component/Process/Exception/LogicException.php', 'Symfony\\Component\\Process\\Exception\\ProcessFailedException' => $vendorDir . '/symfony/process/Symfony/Component/Process/Exception/ProcessFailedException.php', 'Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => $vendorDir . '/symfony/process/Symfony/Component/Process/Exception/ProcessTimedOutException.php', 'Symfony\\Component\\Process\\Exception\\RuntimeException' => $vendorDir . '/symfony/process/Symfony/Component/Process/Exception/RuntimeException.php', 'Symfony\\Component\\Process\\ExecutableFinder' => $vendorDir . '/symfony/process/Symfony/Component/Process/ExecutableFinder.php', 'Symfony\\Component\\Process\\PhpExecutableFinder' => $vendorDir . '/symfony/process/Symfony/Component/Process/PhpExecutableFinder.php', 'Symfony\\Component\\Process\\PhpProcess' => $vendorDir . '/symfony/process/Symfony/Component/Process/PhpProcess.php', 'Symfony\\Component\\Process\\Pipes\\AbstractPipes' => $vendorDir . '/symfony/process/Symfony/Component/Process/Pipes/AbstractPipes.php', 'Symfony\\Component\\Process\\Pipes\\PipesInterface' => $vendorDir . '/symfony/process/Symfony/Component/Process/Pipes/PipesInterface.php', 'Symfony\\Component\\Process\\Pipes\\UnixPipes' => $vendorDir . '/symfony/process/Symfony/Component/Process/Pipes/UnixPipes.php', 'Symfony\\Component\\Process\\Pipes\\WindowsPipes' => $vendorDir . '/symfony/process/Symfony/Component/Process/Pipes/WindowsPipes.php', 'Symfony\\Component\\Process\\Process' => $vendorDir . '/symfony/process/Symfony/Component/Process/Process.php', 'Symfony\\Component\\Process\\ProcessBuilder' => $vendorDir . '/symfony/process/Symfony/Component/Process/ProcessBuilder.php', 'Symfony\\Component\\Process\\ProcessUtils' => $vendorDir . '/symfony/process/Symfony/Component/Process/ProcessUtils.php', 'Symfony\\Component\\Process\\Tests\\AbstractProcessTest' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.php', 'Symfony\\Component\\Process\\Tests\\ExecutableFinderTest' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/ExecutableFinderTest.php', 'Symfony\\Component\\Process\\Tests\\NonStringifiable' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.php', 'Symfony\\Component\\Process\\Tests\\PhpExecutableFinderTest' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php', 'Symfony\\Component\\Process\\Tests\\PhpProcessTest' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/PhpProcessTest.php', 'Symfony\\Component\\Process\\Tests\\ProcessBuilderTest' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/ProcessBuilderTest.php', 'Symfony\\Component\\Process\\Tests\\ProcessFailedExceptionTest' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php', 'Symfony\\Component\\Process\\Tests\\ProcessInSigchildEnvironment' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.php', 'Symfony\\Component\\Process\\Tests\\ProcessUtilsTest' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/ProcessUtilsTest.php', 'Symfony\\Component\\Process\\Tests\\SigchildDisabledProcessTest' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php', 'Symfony\\Component\\Process\\Tests\\SigchildEnabledProcessTest' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php', 'Symfony\\Component\\Process\\Tests\\SimpleProcessTest' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/SimpleProcessTest.php', 'Symfony\\Component\\Process\\Tests\\Stringifiable' => $vendorDir . '/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.php', 'Symfony\\Component\\Stopwatch\\Section' => $vendorDir . '/symfony/stopwatch/Symfony/Component/Stopwatch/Section.php', 'Symfony\\Component\\Stopwatch\\Stopwatch' => $vendorDir . '/symfony/stopwatch/Symfony/Component/Stopwatch/Stopwatch.php', 'Symfony\\Component\\Stopwatch\\StopwatchEvent' => $vendorDir . '/symfony/stopwatch/Symfony/Component/Stopwatch/StopwatchEvent.php', 'Symfony\\Component\\Stopwatch\\StopwatchPeriod' => $vendorDir . '/symfony/stopwatch/Symfony/Component/Stopwatch/StopwatchPeriod.php', 'Symfony\\Component\\Stopwatch\\Tests\\StopwatchEventTest' => $vendorDir . '/symfony/stopwatch/Symfony/Component/Stopwatch/Tests/StopwatchEventTest.php', 'Symfony\\Component\\Stopwatch\\Tests\\StopwatchTest' => $vendorDir . '/symfony/stopwatch/Symfony/Component/Stopwatch/Tests/StopwatchTest.php', 'Symfony\\Component\\Translation\\Catalogue\\AbstractOperation' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Catalogue/AbstractOperation.php', 'Symfony\\Component\\Translation\\Catalogue\\DiffOperation' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Catalogue/DiffOperation.php', 'Symfony\\Component\\Translation\\Catalogue\\MergeOperation' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Catalogue/MergeOperation.php', 'Symfony\\Component\\Translation\\Catalogue\\OperationInterface' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Catalogue/OperationInterface.php', 'Symfony\\Component\\Translation\\Dumper\\CsvFileDumper' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/CsvFileDumper.php', 'Symfony\\Component\\Translation\\Dumper\\DumperInterface' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/DumperInterface.php', 'Symfony\\Component\\Translation\\Dumper\\FileDumper' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/FileDumper.php', 'Symfony\\Component\\Translation\\Dumper\\IcuResFileDumper' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/IcuResFileDumper.php', 'Symfony\\Component\\Translation\\Dumper\\IniFileDumper' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/IniFileDumper.php', 'Symfony\\Component\\Translation\\Dumper\\MoFileDumper' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/MoFileDumper.php', 'Symfony\\Component\\Translation\\Dumper\\PhpFileDumper' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/PhpFileDumper.php', 'Symfony\\Component\\Translation\\Dumper\\PoFileDumper' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/PoFileDumper.php', 'Symfony\\Component\\Translation\\Dumper\\QtFileDumper' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/QtFileDumper.php', 'Symfony\\Component\\Translation\\Dumper\\XliffFileDumper' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/XliffFileDumper.php', 'Symfony\\Component\\Translation\\Dumper\\YamlFileDumper' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Dumper/YamlFileDumper.php', 'Symfony\\Component\\Translation\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Exception/ExceptionInterface.php', 'Symfony\\Component\\Translation\\Exception\\InvalidResourceException' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Exception/InvalidResourceException.php', 'Symfony\\Component\\Translation\\Exception\\NotFoundResourceException' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Exception/NotFoundResourceException.php', 'Symfony\\Component\\Translation\\Extractor\\ChainExtractor' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Extractor/ChainExtractor.php', 'Symfony\\Component\\Translation\\Extractor\\ExtractorInterface' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Extractor/ExtractorInterface.php', 'Symfony\\Component\\Translation\\IdentityTranslator' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/IdentityTranslator.php', 'Symfony\\Component\\Translation\\Interval' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Interval.php', 'Symfony\\Component\\Translation\\Loader\\ArrayLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/ArrayLoader.php', 'Symfony\\Component\\Translation\\Loader\\CsvFileLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/CsvFileLoader.php', 'Symfony\\Component\\Translation\\Loader\\IcuDatFileLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/IcuDatFileLoader.php', 'Symfony\\Component\\Translation\\Loader\\IcuResFileLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/IcuResFileLoader.php', 'Symfony\\Component\\Translation\\Loader\\IniFileLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/IniFileLoader.php', 'Symfony\\Component\\Translation\\Loader\\LoaderInterface' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/LoaderInterface.php', 'Symfony\\Component\\Translation\\Loader\\MoFileLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/MoFileLoader.php', 'Symfony\\Component\\Translation\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/PhpFileLoader.php', 'Symfony\\Component\\Translation\\Loader\\PoFileLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/PoFileLoader.php', 'Symfony\\Component\\Translation\\Loader\\QtFileLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/QtFileLoader.php', 'Symfony\\Component\\Translation\\Loader\\XliffFileLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/XliffFileLoader.php', 'Symfony\\Component\\Translation\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Loader/YamlFileLoader.php', 'Symfony\\Component\\Translation\\MessageCatalogue' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/MessageCatalogue.php', 'Symfony\\Component\\Translation\\MessageCatalogueInterface' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/MessageCatalogueInterface.php', 'Symfony\\Component\\Translation\\MessageSelector' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/MessageSelector.php', 'Symfony\\Component\\Translation\\MetadataAwareInterface' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/MetadataAwareInterface.php', 'Symfony\\Component\\Translation\\PluralizationRules' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/PluralizationRules.php', 'Symfony\\Component\\Translation\\Test\\Catalogue\\AbstractOperationTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Catalogue/AbstractOperationTest.php', 'Symfony\\Component\\Translation\\Test\\Catalogue\\DiffOperationTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Catalogue/DiffOperationTest.php', 'Symfony\\Component\\Translation\\Test\\Catalogue\\MergeOperationTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Catalogue/MergeOperationTest.php', 'Symfony\\Component\\Translation\\Tests\\Dumper\\CsvFileDumperTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Dumper/CsvFileDumperTest.php', 'Symfony\\Component\\Translation\\Tests\\Dumper\\IcuResFileDumperTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Dumper/IcuResFileDumperTest.php', 'Symfony\\Component\\Translation\\Tests\\Dumper\\IniFileDumperTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Dumper/IniFileDumperTest.php', 'Symfony\\Component\\Translation\\Tests\\Dumper\\MoFileDumperTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Dumper/MoFileDumperTest.php', 'Symfony\\Component\\Translation\\Tests\\Dumper\\PhpFileDumperTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Dumper/PhpFileDumperTest.php', 'Symfony\\Component\\Translation\\Tests\\Dumper\\PoFileDumperTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.php', 'Symfony\\Component\\Translation\\Tests\\Dumper\\QtFileDumperTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Dumper/QtFileDumperTest.php', 'Symfony\\Component\\Translation\\Tests\\Dumper\\XliffFileDumperTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php', 'Symfony\\Component\\Translation\\Tests\\Dumper\\YamlFileDumperTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.php', 'Symfony\\Component\\Translation\\Tests\\IdentityTranslatorTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/IdentityTranslatorTest.php', 'Symfony\\Component\\Translation\\Tests\\IntervalTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/IntervalTest.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\CsvFileLoaderTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/CsvFileLoaderTest.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\IcuDatFileLoaderTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/IcuDatFileLoaderTest.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\IcuResFileLoaderTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/IcuResFileLoaderTest.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\IniFileLoaderTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/IniFileLoaderTest.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\LocalizedTestCase' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/LocalizedTestCase.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\MoFileLoaderTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/MoFileLoaderTest.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\PhpFileLoaderTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/PhpFileLoaderTest.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\PoFileLoaderTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\QtFileLoaderTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/QtFileLoaderTest.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\XliffFileLoaderTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php', 'Symfony\\Component\\Translation\\Tests\\Loader\\YamlFileLoaderTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/Loader/YamlFileLoaderTest.php', 'Symfony\\Component\\Translation\\Tests\\MessageCatalogueTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/MessageCatalogueTest.php', 'Symfony\\Component\\Translation\\Tests\\MessageSelectorTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/MessageSelectorTest.php', 'Symfony\\Component\\Translation\\Tests\\PluralizationRulesTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/PluralizationRulesTest.php', 'Symfony\\Component\\Translation\\Tests\\String' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/TranslatorTest.php', 'Symfony\\Component\\Translation\\Tests\\TranslatorTest' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Tests/TranslatorTest.php', 'Symfony\\Component\\Translation\\Translator' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Translator.php', 'Symfony\\Component\\Translation\\TranslatorInterface' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/TranslatorInterface.php', 'Symfony\\Component\\Translation\\Writer\\TranslationWriter' => $vendorDir . '/symfony/translation/Symfony/Component/Translation/Writer/TranslationWriter.php', 'Symfony\\Component\\Validator\\ClassBasedInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ClassBasedInterface.php', 'Symfony\\Component\\Validator\\Constraint' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraint.php', 'Symfony\\Component\\Validator\\ConstraintValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ConstraintValidator.php', 'Symfony\\Component\\Validator\\ConstraintValidatorFactory' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ConstraintValidatorFactory.php', 'Symfony\\Component\\Validator\\ConstraintValidatorFactoryInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ConstraintValidatorFactoryInterface.php', 'Symfony\\Component\\Validator\\ConstraintValidatorInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ConstraintValidatorInterface.php', 'Symfony\\Component\\Validator\\ConstraintViolation' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ConstraintViolation.php', 'Symfony\\Component\\Validator\\ConstraintViolationInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ConstraintViolationInterface.php', 'Symfony\\Component\\Validator\\ConstraintViolationList' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ConstraintViolationList.php', 'Symfony\\Component\\Validator\\ConstraintViolationListInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ConstraintViolationListInterface.php', 'Symfony\\Component\\Validator\\Constraints\\AbstractComparison' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/AbstractComparison.php', 'Symfony\\Component\\Validator\\Constraints\\AbstractComparisonValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php', 'Symfony\\Component\\Validator\\Constraints\\All' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/All.php', 'Symfony\\Component\\Validator\\Constraints\\AllValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/AllValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Blank' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Blank.php', 'Symfony\\Component\\Validator\\Constraints\\BlankValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/BlankValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Callback' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Callback.php', 'Symfony\\Component\\Validator\\Constraints\\CallbackValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/CallbackValidator.php', 'Symfony\\Component\\Validator\\Constraints\\CardScheme' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/CardScheme.php', 'Symfony\\Component\\Validator\\Constraints\\CardSchemeValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/CardSchemeValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Choice' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Choice.php', 'Symfony\\Component\\Validator\\Constraints\\ChoiceValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/ChoiceValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Collection' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Collection.php', 'Symfony\\Component\\Validator\\Constraints\\CollectionValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/CollectionValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Collection\\Optional' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Collection/Optional.php', 'Symfony\\Component\\Validator\\Constraints\\Collection\\Required' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Collection/Required.php', 'Symfony\\Component\\Validator\\Constraints\\Composite' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Composite.php', 'Symfony\\Component\\Validator\\Constraints\\Count' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Count.php', 'Symfony\\Component\\Validator\\Constraints\\CountValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/CountValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Country' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Country.php', 'Symfony\\Component\\Validator\\Constraints\\CountryValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/CountryValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Currency' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Currency.php', 'Symfony\\Component\\Validator\\Constraints\\CurrencyValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/CurrencyValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Date' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Date.php', 'Symfony\\Component\\Validator\\Constraints\\DateTime' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/DateTime.php', 'Symfony\\Component\\Validator\\Constraints\\DateTimeValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/DateTimeValidator.php', 'Symfony\\Component\\Validator\\Constraints\\DateValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/DateValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Email' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Email.php', 'Symfony\\Component\\Validator\\Constraints\\EmailValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/EmailValidator.php', 'Symfony\\Component\\Validator\\Constraints\\EqualTo' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/EqualTo.php', 'Symfony\\Component\\Validator\\Constraints\\EqualToValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/EqualToValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Existence' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Existence.php', 'Symfony\\Component\\Validator\\Constraints\\Expression' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Expression.php', 'Symfony\\Component\\Validator\\Constraints\\ExpressionValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/ExpressionValidator.php', 'Symfony\\Component\\Validator\\Constraints\\False' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/False.php', 'Symfony\\Component\\Validator\\Constraints\\FalseValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/FalseValidator.php', 'Symfony\\Component\\Validator\\Constraints\\File' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/File.php', 'Symfony\\Component\\Validator\\Constraints\\FileValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/FileValidator.php', 'Symfony\\Component\\Validator\\Constraints\\GreaterThan' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/GreaterThan.php', 'Symfony\\Component\\Validator\\Constraints\\GreaterThanOrEqual' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/GreaterThanOrEqual.php', 'Symfony\\Component\\Validator\\Constraints\\GreaterThanOrEqualValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.php', 'Symfony\\Component\\Validator\\Constraints\\GreaterThanValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/GreaterThanValidator.php', 'Symfony\\Component\\Validator\\Constraints\\GroupSequence' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/GroupSequence.php', 'Symfony\\Component\\Validator\\Constraints\\GroupSequenceProvider' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/GroupSequenceProvider.php', 'Symfony\\Component\\Validator\\Constraints\\Iban' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Iban.php', 'Symfony\\Component\\Validator\\Constraints\\IbanValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IbanValidator.php', 'Symfony\\Component\\Validator\\Constraints\\IdenticalTo' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IdenticalTo.php', 'Symfony\\Component\\Validator\\Constraints\\IdenticalToValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IdenticalToValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Image' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Image.php', 'Symfony\\Component\\Validator\\Constraints\\ImageValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/ImageValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Ip' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Ip.php', 'Symfony\\Component\\Validator\\Constraints\\IpValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IpValidator.php', 'Symfony\\Component\\Validator\\Constraints\\IsFalse' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IsFalse.php', 'Symfony\\Component\\Validator\\Constraints\\IsFalseValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IsFalseValidator.php', 'Symfony\\Component\\Validator\\Constraints\\IsNull' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IsNull.php', 'Symfony\\Component\\Validator\\Constraints\\IsNullValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IsNullValidator.php', 'Symfony\\Component\\Validator\\Constraints\\IsTrue' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IsTrue.php', 'Symfony\\Component\\Validator\\Constraints\\IsTrueValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IsTrueValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Isbn' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Isbn.php', 'Symfony\\Component\\Validator\\Constraints\\IsbnValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IsbnValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Issn' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Issn.php', 'Symfony\\Component\\Validator\\Constraints\\IssnValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/IssnValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Language' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Language.php', 'Symfony\\Component\\Validator\\Constraints\\LanguageValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/LanguageValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Length' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Length.php', 'Symfony\\Component\\Validator\\Constraints\\LengthValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/LengthValidator.php', 'Symfony\\Component\\Validator\\Constraints\\LessThan' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/LessThan.php', 'Symfony\\Component\\Validator\\Constraints\\LessThanOrEqual' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/LessThanOrEqual.php', 'Symfony\\Component\\Validator\\Constraints\\LessThanOrEqualValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/LessThanOrEqualValidator.php', 'Symfony\\Component\\Validator\\Constraints\\LessThanValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/LessThanValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Locale' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Locale.php', 'Symfony\\Component\\Validator\\Constraints\\LocaleValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/LocaleValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Luhn' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Luhn.php', 'Symfony\\Component\\Validator\\Constraints\\LuhnValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/LuhnValidator.php', 'Symfony\\Component\\Validator\\Constraints\\NotBlank' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/NotBlank.php', 'Symfony\\Component\\Validator\\Constraints\\NotBlankValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/NotBlankValidator.php', 'Symfony\\Component\\Validator\\Constraints\\NotEqualTo' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/NotEqualTo.php', 'Symfony\\Component\\Validator\\Constraints\\NotEqualToValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/NotEqualToValidator.php', 'Symfony\\Component\\Validator\\Constraints\\NotIdenticalTo' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/NotIdenticalTo.php', 'Symfony\\Component\\Validator\\Constraints\\NotIdenticalToValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/NotIdenticalToValidator.php', 'Symfony\\Component\\Validator\\Constraints\\NotNull' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/NotNull.php', 'Symfony\\Component\\Validator\\Constraints\\NotNullValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/NotNullValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Null' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Null.php', 'Symfony\\Component\\Validator\\Constraints\\NullValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/NullValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Optional' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Optional.php', 'Symfony\\Component\\Validator\\Constraints\\Range' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Range.php', 'Symfony\\Component\\Validator\\Constraints\\RangeValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/RangeValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Regex' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Regex.php', 'Symfony\\Component\\Validator\\Constraints\\RegexValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/RegexValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Required' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Required.php', 'Symfony\\Component\\Validator\\Constraints\\Time' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Time.php', 'Symfony\\Component\\Validator\\Constraints\\TimeValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/TimeValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Traverse' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Traverse.php', 'Symfony\\Component\\Validator\\Constraints\\True' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/True.php', 'Symfony\\Component\\Validator\\Constraints\\TrueValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/TrueValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Type' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Type.php', 'Symfony\\Component\\Validator\\Constraints\\TypeValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/TypeValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Url' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Url.php', 'Symfony\\Component\\Validator\\Constraints\\UrlValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/UrlValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Uuid' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Uuid.php', 'Symfony\\Component\\Validator\\Constraints\\UuidValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/UuidValidator.php', 'Symfony\\Component\\Validator\\Constraints\\Valid' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Constraints/Valid.php', 'Symfony\\Component\\Validator\\Context\\ExecutionContext' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Context/ExecutionContext.php', 'Symfony\\Component\\Validator\\Context\\ExecutionContextFactory' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Context/ExecutionContextFactory.php', 'Symfony\\Component\\Validator\\Context\\ExecutionContextFactoryInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Context/ExecutionContextFactoryInterface.php', 'Symfony\\Component\\Validator\\Context\\ExecutionContextInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Context/ExecutionContextInterface.php', 'Symfony\\Component\\Validator\\Context\\LegacyExecutionContext' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Context/LegacyExecutionContext.php', 'Symfony\\Component\\Validator\\Context\\LegacyExecutionContextFactory' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Context/LegacyExecutionContextFactory.php', 'Symfony\\Component\\Validator\\DefaultTranslator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/DefaultTranslator.php', 'Symfony\\Component\\Validator\\Exception\\BadMethodCallException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/BadMethodCallException.php', 'Symfony\\Component\\Validator\\Exception\\ConstraintDefinitionException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/ConstraintDefinitionException.php', 'Symfony\\Component\\Validator\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/ExceptionInterface.php', 'Symfony\\Component\\Validator\\Exception\\GroupDefinitionException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/GroupDefinitionException.php', 'Symfony\\Component\\Validator\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/InvalidArgumentException.php', 'Symfony\\Component\\Validator\\Exception\\InvalidOptionsException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/InvalidOptionsException.php', 'Symfony\\Component\\Validator\\Exception\\MappingException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/MappingException.php', 'Symfony\\Component\\Validator\\Exception\\MissingOptionsException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/MissingOptionsException.php', 'Symfony\\Component\\Validator\\Exception\\NoSuchMetadataException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/NoSuchMetadataException.php', 'Symfony\\Component\\Validator\\Exception\\OutOfBoundsException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/OutOfBoundsException.php', 'Symfony\\Component\\Validator\\Exception\\RuntimeException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/RuntimeException.php', 'Symfony\\Component\\Validator\\Exception\\UnexpectedTypeException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/UnexpectedTypeException.php', 'Symfony\\Component\\Validator\\Exception\\UnsupportedMetadataException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/UnsupportedMetadataException.php', 'Symfony\\Component\\Validator\\Exception\\ValidatorException' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Exception/ValidatorException.php', 'Symfony\\Component\\Validator\\ExecutionContext' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ExecutionContext.php', 'Symfony\\Component\\Validator\\ExecutionContextInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ExecutionContextInterface.php', 'Symfony\\Component\\Validator\\GlobalExecutionContextInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/GlobalExecutionContextInterface.php', 'Symfony\\Component\\Validator\\GroupSequenceProviderInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/GroupSequenceProviderInterface.php', 'Symfony\\Component\\Validator\\Mapping\\BlackholeMetadataFactory' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/BlackholeMetadataFactory.php', 'Symfony\\Component\\Validator\\Mapping\\Cache\\ApcCache' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Cache/ApcCache.php', 'Symfony\\Component\\Validator\\Mapping\\Cache\\CacheInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Cache/CacheInterface.php', 'Symfony\\Component\\Validator\\Mapping\\Cache\\DoctrineCache' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Cache/DoctrineCache.php', 'Symfony\\Component\\Validator\\Mapping\\CascadingStrategy' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/CascadingStrategy.php', 'Symfony\\Component\\Validator\\Mapping\\ClassMetadata' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/ClassMetadata.php', 'Symfony\\Component\\Validator\\Mapping\\ClassMetadataFactory' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/ClassMetadataFactory.php', 'Symfony\\Component\\Validator\\Mapping\\ClassMetadataInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/ClassMetadataInterface.php', 'Symfony\\Component\\Validator\\Mapping\\ElementMetadata' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/ElementMetadata.php', 'Symfony\\Component\\Validator\\Mapping\\Factory\\BlackHoleMetadataFactory' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Factory/BlackHoleMetadataFactory.php', 'Symfony\\Component\\Validator\\Mapping\\Factory\\LazyLoadingMetadataFactory' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php', 'Symfony\\Component\\Validator\\Mapping\\Factory\\MetadataFactoryInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Factory/MetadataFactoryInterface.php', 'Symfony\\Component\\Validator\\Mapping\\GenericMetadata' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/GenericMetadata.php', 'Symfony\\Component\\Validator\\Mapping\\GetterMetadata' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/GetterMetadata.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\AbstractLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\AnnotationLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\FileLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/FileLoader.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\FilesLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/FilesLoader.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\LoaderChain' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/LoaderChain.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\LoaderInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/LoaderInterface.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\StaticMethodLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\XmlFileLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\XmlFilesLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/XmlFilesLoader.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php', 'Symfony\\Component\\Validator\\Mapping\\Loader\\YamlFilesLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/Loader/YamlFilesLoader.php', 'Symfony\\Component\\Validator\\Mapping\\MemberMetadata' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/MemberMetadata.php', 'Symfony\\Component\\Validator\\Mapping\\MetadataInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/MetadataInterface.php', 'Symfony\\Component\\Validator\\Mapping\\PropertyMetadata' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/PropertyMetadata.php', 'Symfony\\Component\\Validator\\Mapping\\PropertyMetadataInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/PropertyMetadataInterface.php', 'Symfony\\Component\\Validator\\Mapping\\TraversalStrategy' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Mapping/TraversalStrategy.php', 'Symfony\\Component\\Validator\\MetadataFactoryInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/MetadataFactoryInterface.php', 'Symfony\\Component\\Validator\\MetadataInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/MetadataInterface.php', 'Symfony\\Component\\Validator\\ObjectInitializerInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ObjectInitializerInterface.php', 'Symfony\\Component\\Validator\\PropertyMetadataContainerInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/PropertyMetadataContainerInterface.php', 'Symfony\\Component\\Validator\\PropertyMetadataInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/PropertyMetadataInterface.php', 'Symfony\\Component\\Validator\\Tests\\ConstraintTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/ConstraintTest.php', 'Symfony\\Component\\Validator\\Tests\\ConstraintViolationListTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/ConstraintViolationListTest.php', 'Symfony\\Component\\Validator\\Tests\\ConstraintViolationTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/ConstraintViolationTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\AbstractComparisonValidatorTestCase' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\AbstractConstraintValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\AllTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/AllTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\AllValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\BlankValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CallbackValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CallbackValidatorTest_Class' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CallbackValidatorTest_Object' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CardSchemeValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\ChoiceValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CollectionTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CollectionValidatorArrayObjectTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CollectionValidatorArrayTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CollectionValidatorCustomArrayObjectTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CollectionValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\ComparisonTest_Class' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CompositeTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\ConcreteComposite' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\ConstraintViolationAssertion' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CountValidatorArrayTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CountValidatorCountableTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CountValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CountryValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\CurrencyValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\DateTimeValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\DateValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\EmailValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\EqualToValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\ExpressionValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\FileTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/FileTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\FileValidatorObjectTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\FileValidatorPathTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\FileValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\GreaterThanOrEqualValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\GreaterThanValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\GroupSequenceTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/GroupSequenceTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\IbanValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\IdenticalToValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\ImageValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\IpValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\IsFalseValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IsFalseValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\IsNullValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IsNullValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\IsTrueValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IsTrueValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\IsbnValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\IssnValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LanguageValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyAllValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyAllValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyAllValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyAllValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyBlankValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyBlankValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyBlankValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyBlankValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCallbackValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCallbackValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCallbackValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCallbackValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCardSchemeValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCardSchemeValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCardSchemeValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCardSchemeValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyChoiceValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyChoiceValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyChoiceValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyChoiceValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCollectionValidatorArray2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCollectionValidatorArray2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCollectionValidatorArrayLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCollectionValidatorArrayLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCollectionValidatorArrayObject2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCollectionValidatorArrayObject2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCollectionValidatorArrayObjectLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCollectionValidatorArrayObjectLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCollectionValidatorCustomArrayObject2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCollectionValidatorCustomArrayObject2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCollectionValidatorCustomArrayObjectLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCollectionValidatorCustomArrayObjectLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCountValidatorArray2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCountValidatorArray2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCountValidatorArrayLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCountValidatorArrayLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCountValidatorCountable2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCountValidatorCountable2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCountValidatorCountableLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCountValidatorCountableLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCurrencyValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCurrencyValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyCurrencyValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyCurrencyValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyDateTimeValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyDateTimeValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyDateTimeValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyDateTimeValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyDateValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyDateValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyDateValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyDateValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyEmailValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyEmailValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyEmailValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyEmailValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyEqualToValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyEqualToValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyEqualToValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyEqualToValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyExpressionValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyExpressionValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyExpressionValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyExpressionValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyFalseValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyFalseValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyFalseValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyFalseValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyFileValidatorObject2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyFileValidatorObject2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyFileValidatorObjectLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyFileValidatorObjectLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyFileValidatorPath2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyFileValidatorPath2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyFileValidatorPathLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyFileValidatorPathLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyGreaterThanOrEqualValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyGreaterThanOrEqualValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyGreaterThanOrEqualValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyGreaterThanOrEqualValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyGreaterThanValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyGreaterThanValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyGreaterThanValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyGreaterThanValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyIbanValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyIbanValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyIbanValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyIbanValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyIdenticalToValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyIdenticalToValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyIdenticalToValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyIdenticalToValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyImageValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyImageValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyImageValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyImageValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyIpValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyIpValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyIpValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyIpValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyIsbnValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyIsbnValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyIsbnValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyIsbnValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyIssnValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyIssnValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyIssnValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyIssnValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLanguageValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLanguageValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLanguageValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLanguageValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLengthValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLengthValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLengthValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLengthValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLessThanOrEqualValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLessThanOrEqualValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLessThanOrEqualValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLessThanOrEqualValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLessThanValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLessThanValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLessThanValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLessThanValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLocaleValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLocaleValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLocaleValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLocaleValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLuhnValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLuhnValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyLuhnValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyLuhnValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyNotBlankValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyNotBlankValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyNotBlankValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyNotBlankValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyNotEqualToValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyNotEqualToValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyNotEqualToValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyNotEqualToValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyNotIdenticalToValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyNotIdenticalToValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyNotIdenticalToValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyNotIdenticalToValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyNotNullValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyNotNullValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyNotNullValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyNotNullValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyNullValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyNullValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyNullValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyNullValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyRangeValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyRangeValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyRangeValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyRangeValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyRegexValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyRegexValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyRegexValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyRegexValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyTimeValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyTimeValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyTimeValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyTimeValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyTrueValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyTrueValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyTrueValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyTrueValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyTypeValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyTypeValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyTypeValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyTypeValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyUrlValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyUrlValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyUrlValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyUrlValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyUuidValidator2Dot4ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyUuidValidator2Dot4ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LegacyUuidValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LegacyUuidValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LengthValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LessThanOrEqualValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LessThanValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LocaleValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\LuhnValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\NotBlankValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\NotEqualToValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\NotIdenticalToValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\NotNullValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\RangeValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\RegexValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\TimeValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\TypeValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\UrlValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\UuidValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/UuidValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Constraints\\ValidTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Constraints/ValidTest.php', 'Symfony\\Component\\Validator\\Tests\\ExecutionContextTest_TestClass' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/LegacyExecutionContextTest.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\CallbackClass' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/CallbackClass.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\ClassConstraint' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\ConstraintA' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\ConstraintAValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\ConstraintB' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintB.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\ConstraintC' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintC.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\ConstraintWithValue' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\ConstraintWithValueAsDefault' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\Countable' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/Countable.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\CustomArrayObject' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\Entity' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/Entity.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\EntityInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\EntityParent' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\FailingConstraint' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\FailingConstraintValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\FakeClassMetadata' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/FakeClassMetadata.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\FakeMetadataFactory' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\FilesLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/FilesLoader.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\GroupSequenceProviderEntity' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\InvalidConstraint' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\InvalidConstraintValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\LegacyClassMetadata' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/LegacyClassMetadata.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\PropertyConstraint' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\Reference' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/Reference.php', 'Symfony\\Component\\Validator\\Tests\\Fixtures\\StubGlobalExecutionContext' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/StubGlobalExecutionContext.php', 'Symfony\\Component\\Validator\\Tests\\LegacyExecutionContextTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/LegacyExecutionContextTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Cache\\DoctrineCacheTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Cache/DoctrineCacheTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Cache\\LegacyApcCacheTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Cache/LegacyApcCacheTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\ClassMetadataTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Factory\\BlackHoleMetadataFactoryTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Factory/BlackHoleMetadataFactoryTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Factory\\LazyLoadingMetadataFactoryTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Factory\\TestLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\GetterMetadataTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\LegacyElementMetadataTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/LegacyElementMetadataTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\AbstractStaticLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\AbstractStaticMethodLoader' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractStaticMethodLoader.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\AnnotationLoaderTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\BaseStaticLoaderDocument' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\FilesLoaderTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\LoaderChainTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\StaticLoaderDocument' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\StaticLoaderEntity' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\StaticLoaderInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\StaticMethodLoaderTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\XmlFileLoaderTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\Loader\\YamlFileLoaderTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\MemberMetadataTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\PropertyMetadataTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\TestElementMetadata' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/LegacyElementMetadataTest.php', 'Symfony\\Component\\Validator\\Tests\\Mapping\\TestMemberMetadata' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php', 'Symfony\\Component\\Validator\\Tests\\Util\\PropertyPathTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Util/PropertyPathTest.php', 'Symfony\\Component\\Validator\\Tests\\ValidatorBuilderTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/ValidatorBuilderTest.php', 'Symfony\\Component\\Validator\\Tests\\ValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/ValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Validator\\Abstract2Dot5ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Validator/Abstract2Dot5ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Validator\\AbstractLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Validator/AbstractLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Validator\\AbstractValidatorTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Validator/AbstractValidatorTest.php', 'Symfony\\Component\\Validator\\Tests\\Validator\\LegacyValidator2Dot5ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Validator/LegacyValidator2Dot5ApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Validator\\LegacyValidatorLegacyApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Validator/LegacyValidatorLegacyApiTest.php', 'Symfony\\Component\\Validator\\Tests\\Validator\\RecursiveValidator2Dot5ApiTest' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Tests/Validator/RecursiveValidator2Dot5ApiTest.php', 'Symfony\\Component\\Validator\\Util\\PropertyPath' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Util/PropertyPath.php', 'Symfony\\Component\\Validator\\Validation' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Validation.php', 'Symfony\\Component\\Validator\\ValidationVisitor' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ValidationVisitor.php', 'Symfony\\Component\\Validator\\ValidationVisitorInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ValidationVisitorInterface.php', 'Symfony\\Component\\Validator\\Validator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Validator.php', 'Symfony\\Component\\Validator\\ValidatorBuilder' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ValidatorBuilder.php', 'Symfony\\Component\\Validator\\ValidatorBuilderInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ValidatorBuilderInterface.php', 'Symfony\\Component\\Validator\\ValidatorInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/ValidatorInterface.php', 'Symfony\\Component\\Validator\\Validator\\ContextualValidatorInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Validator/ContextualValidatorInterface.php', 'Symfony\\Component\\Validator\\Validator\\LegacyValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Validator/LegacyValidator.php', 'Symfony\\Component\\Validator\\Validator\\RecursiveContextualValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php', 'Symfony\\Component\\Validator\\Validator\\RecursiveValidator' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Validator/RecursiveValidator.php', 'Symfony\\Component\\Validator\\Validator\\ValidatorInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Validator/ValidatorInterface.php', 'Symfony\\Component\\Validator\\Violation\\ConstraintViolationBuilder' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php', 'Symfony\\Component\\Validator\\Violation\\ConstraintViolationBuilderInterface' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Violation/ConstraintViolationBuilderInterface.php', 'Symfony\\Component\\Validator\\Violation\\LegacyConstraintViolationBuilder' => $vendorDir . '/symfony/validator/Symfony/Component/Validator/Violation/LegacyConstraintViolationBuilder.php', 'Symfony\\Component\\Yaml\\Dumper' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Dumper.php', 'Symfony\\Component\\Yaml\\Escaper' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Escaper.php', 'Symfony\\Component\\Yaml\\Exception\\DumpException' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Exception/DumpException.php', 'Symfony\\Component\\Yaml\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Exception/ExceptionInterface.php', 'Symfony\\Component\\Yaml\\Exception\\ParseException' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Exception/ParseException.php', 'Symfony\\Component\\Yaml\\Exception\\RuntimeException' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Exception/RuntimeException.php', 'Symfony\\Component\\Yaml\\Inline' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Inline.php', 'Symfony\\Component\\Yaml\\Parser' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Parser.php', 'Symfony\\Component\\Yaml\\Tests\\A' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Tests/DumperTest.php', 'Symfony\\Component\\Yaml\\Tests\\B' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Tests/ParserTest.php', 'Symfony\\Component\\Yaml\\Tests\\DumperTest' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Tests/DumperTest.php', 'Symfony\\Component\\Yaml\\Tests\\InlineTest' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Tests/InlineTest.php', 'Symfony\\Component\\Yaml\\Tests\\ParseExceptionTest' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Tests/ParseExceptionTest.php', 'Symfony\\Component\\Yaml\\Tests\\ParserTest' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Tests/ParserTest.php', 'Symfony\\Component\\Yaml\\Tests\\YamlTest' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Tests/YamlTest.php', 'Symfony\\Component\\Yaml\\Unescaper' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Unescaper.php', 'Symfony\\Component\\Yaml\\Yaml' => $vendorDir . '/symfony/yaml/Symfony/Component/Yaml/Yaml.php', 'Text_Template' => $vendorDir . '/phpunit/php-text-template/src/Template.php', 'Twig_Autoloader' => $vendorDir . '/twig/twig/lib/Twig/Autoloader.php', 'Twig_BaseNodeVisitor' => $vendorDir . '/twig/twig/lib/Twig/BaseNodeVisitor.php', 'Twig_CacheInterface' => $vendorDir . '/twig/twig/lib/Twig/CacheInterface.php', 'Twig_Cache_Filesystem' => $vendorDir . '/twig/twig/lib/Twig/Cache/Filesystem.php', 'Twig_Cache_Null' => $vendorDir . '/twig/twig/lib/Twig/Cache/Null.php', 'Twig_Compiler' => $vendorDir . '/twig/twig/lib/Twig/Compiler.php', 'Twig_CompilerInterface' => $vendorDir . '/twig/twig/lib/Twig/CompilerInterface.php', 'Twig_Environment' => $vendorDir . '/twig/twig/lib/Twig/Environment.php', 'Twig_Error' => $vendorDir . '/twig/twig/lib/Twig/Error.php', 'Twig_Error_Loader' => $vendorDir . '/twig/twig/lib/Twig/Error/Loader.php', 'Twig_Error_Runtime' => $vendorDir . '/twig/twig/lib/Twig/Error/Runtime.php', 'Twig_Error_Syntax' => $vendorDir . '/twig/twig/lib/Twig/Error/Syntax.php', 'Twig_ExistsLoaderInterface' => $vendorDir . '/twig/twig/lib/Twig/ExistsLoaderInterface.php', 'Twig_ExpressionParser' => $vendorDir . '/twig/twig/lib/Twig/ExpressionParser.php', 'Twig_Extension' => $vendorDir . '/twig/twig/lib/Twig/Extension.php', 'Twig_ExtensionInterface' => $vendorDir . '/twig/twig/lib/Twig/ExtensionInterface.php', 'Twig_Extension_Core' => $vendorDir . '/twig/twig/lib/Twig/Extension/Core.php', 'Twig_Extension_Debug' => $vendorDir . '/twig/twig/lib/Twig/Extension/Debug.php', 'Twig_Extension_Escaper' => $vendorDir . '/twig/twig/lib/Twig/Extension/Escaper.php', 'Twig_Extension_Optimizer' => $vendorDir . '/twig/twig/lib/Twig/Extension/Optimizer.php', 'Twig_Extension_Profiler' => $vendorDir . '/twig/twig/lib/Twig/Extension/Profiler.php', 'Twig_Extension_Sandbox' => $vendorDir . '/twig/twig/lib/Twig/Extension/Sandbox.php', 'Twig_Extension_Staging' => $vendorDir . '/twig/twig/lib/Twig/Extension/Staging.php', 'Twig_Extension_StringLoader' => $vendorDir . '/twig/twig/lib/Twig/Extension/StringLoader.php', 'Twig_FileExtensionEscapingStrategy' => $vendorDir . '/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php', 'Twig_Filter' => $vendorDir . '/twig/twig/lib/Twig/Filter.php', 'Twig_FilterCallableInterface' => $vendorDir . '/twig/twig/lib/Twig/FilterCallableInterface.php', 'Twig_FilterInterface' => $vendorDir . '/twig/twig/lib/Twig/FilterInterface.php', 'Twig_Filter_Function' => $vendorDir . '/twig/twig/lib/Twig/Filter/Function.php', 'Twig_Filter_Method' => $vendorDir . '/twig/twig/lib/Twig/Filter/Method.php', 'Twig_Filter_Node' => $vendorDir . '/twig/twig/lib/Twig/Filter/Node.php', 'Twig_Function' => $vendorDir . '/twig/twig/lib/Twig/Function.php', 'Twig_FunctionCallableInterface' => $vendorDir . '/twig/twig/lib/Twig/FunctionCallableInterface.php', 'Twig_FunctionInterface' => $vendorDir . '/twig/twig/lib/Twig/FunctionInterface.php', 'Twig_Function_Function' => $vendorDir . '/twig/twig/lib/Twig/Function/Function.php', 'Twig_Function_Method' => $vendorDir . '/twig/twig/lib/Twig/Function/Method.php', 'Twig_Function_Node' => $vendorDir . '/twig/twig/lib/Twig/Function/Node.php', 'Twig_Lexer' => $vendorDir . '/twig/twig/lib/Twig/Lexer.php', 'Twig_LexerInterface' => $vendorDir . '/twig/twig/lib/Twig/LexerInterface.php', 'Twig_LoaderInterface' => $vendorDir . '/twig/twig/lib/Twig/LoaderInterface.php', 'Twig_Loader_Array' => $vendorDir . '/twig/twig/lib/Twig/Loader/Array.php', 'Twig_Loader_Chain' => $vendorDir . '/twig/twig/lib/Twig/Loader/Chain.php', 'Twig_Loader_Filesystem' => $vendorDir . '/twig/twig/lib/Twig/Loader/Filesystem.php', 'Twig_Loader_String' => $vendorDir . '/twig/twig/lib/Twig/Loader/String.php', 'Twig_Markup' => $vendorDir . '/twig/twig/lib/Twig/Markup.php', 'Twig_Node' => $vendorDir . '/twig/twig/lib/Twig/Node.php', 'Twig_NodeInterface' => $vendorDir . '/twig/twig/lib/Twig/NodeInterface.php', 'Twig_NodeOutputInterface' => $vendorDir . '/twig/twig/lib/Twig/NodeOutputInterface.php', 'Twig_NodeTraverser' => $vendorDir . '/twig/twig/lib/Twig/NodeTraverser.php', 'Twig_NodeVisitorInterface' => $vendorDir . '/twig/twig/lib/Twig/NodeVisitorInterface.php', 'Twig_NodeVisitor_Escaper' => $vendorDir . '/twig/twig/lib/Twig/NodeVisitor/Escaper.php', 'Twig_NodeVisitor_Optimizer' => $vendorDir . '/twig/twig/lib/Twig/NodeVisitor/Optimizer.php', 'Twig_NodeVisitor_SafeAnalysis' => $vendorDir . '/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php', 'Twig_NodeVisitor_Sandbox' => $vendorDir . '/twig/twig/lib/Twig/NodeVisitor/Sandbox.php', 'Twig_Node_AutoEscape' => $vendorDir . '/twig/twig/lib/Twig/Node/AutoEscape.php', 'Twig_Node_Block' => $vendorDir . '/twig/twig/lib/Twig/Node/Block.php', 'Twig_Node_BlockReference' => $vendorDir . '/twig/twig/lib/Twig/Node/BlockReference.php', 'Twig_Node_Body' => $vendorDir . '/twig/twig/lib/Twig/Node/Body.php', 'Twig_Node_CheckSecurity' => $vendorDir . '/twig/twig/lib/Twig/Node/CheckSecurity.php', 'Twig_Node_Do' => $vendorDir . '/twig/twig/lib/Twig/Node/Do.php', 'Twig_Node_Embed' => $vendorDir . '/twig/twig/lib/Twig/Node/Embed.php', 'Twig_Node_Expression' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression.php', 'Twig_Node_Expression_Array' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Array.php', 'Twig_Node_Expression_AssignName' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/AssignName.php', 'Twig_Node_Expression_Binary' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary.php', 'Twig_Node_Expression_Binary_Add' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Add.php', 'Twig_Node_Expression_Binary_And' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/And.php', 'Twig_Node_Expression_Binary_BitwiseAnd' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php', 'Twig_Node_Expression_Binary_BitwiseOr' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php', 'Twig_Node_Expression_Binary_BitwiseXor' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php', 'Twig_Node_Expression_Binary_Concat' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php', 'Twig_Node_Expression_Binary_Div' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Div.php', 'Twig_Node_Expression_Binary_EndsWith' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php', 'Twig_Node_Expression_Binary_Equal' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php', 'Twig_Node_Expression_Binary_FloorDiv' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php', 'Twig_Node_Expression_Binary_Greater' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php', 'Twig_Node_Expression_Binary_GreaterEqual' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php', 'Twig_Node_Expression_Binary_In' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/In.php', 'Twig_Node_Expression_Binary_Less' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Less.php', 'Twig_Node_Expression_Binary_LessEqual' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php', 'Twig_Node_Expression_Binary_Matches' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php', 'Twig_Node_Expression_Binary_Mod' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php', 'Twig_Node_Expression_Binary_Mul' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php', 'Twig_Node_Expression_Binary_NotEqual' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php', 'Twig_Node_Expression_Binary_NotIn' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php', 'Twig_Node_Expression_Binary_Or' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Or.php', 'Twig_Node_Expression_Binary_Power' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Power.php', 'Twig_Node_Expression_Binary_Range' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Range.php', 'Twig_Node_Expression_Binary_StartsWith' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php', 'Twig_Node_Expression_Binary_Sub' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php', 'Twig_Node_Expression_BlockReference' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/BlockReference.php', 'Twig_Node_Expression_Call' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Call.php', 'Twig_Node_Expression_Conditional' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Conditional.php', 'Twig_Node_Expression_Constant' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Constant.php', 'Twig_Node_Expression_ExtensionReference' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php', 'Twig_Node_Expression_Filter' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Filter.php', 'Twig_Node_Expression_Filter_Default' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Filter/Default.php', 'Twig_Node_Expression_Function' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Function.php', 'Twig_Node_Expression_GetAttr' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/GetAttr.php', 'Twig_Node_Expression_MethodCall' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/MethodCall.php', 'Twig_Node_Expression_Name' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Name.php', 'Twig_Node_Expression_Parent' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Parent.php', 'Twig_Node_Expression_TempName' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/TempName.php', 'Twig_Node_Expression_Test' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test.php', 'Twig_Node_Expression_Test_Constant' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Constant.php', 'Twig_Node_Expression_Test_Defined' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Defined.php', 'Twig_Node_Expression_Test_Divisibleby' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php', 'Twig_Node_Expression_Test_Even' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Even.php', 'Twig_Node_Expression_Test_Null' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Null.php', 'Twig_Node_Expression_Test_Odd' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Odd.php', 'Twig_Node_Expression_Test_Sameas' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php', 'Twig_Node_Expression_Unary' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Unary.php', 'Twig_Node_Expression_Unary_Neg' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php', 'Twig_Node_Expression_Unary_Not' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Unary/Not.php', 'Twig_Node_Expression_Unary_Pos' => $vendorDir . '/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php', 'Twig_Node_Flush' => $vendorDir . '/twig/twig/lib/Twig/Node/Flush.php', 'Twig_Node_For' => $vendorDir . '/twig/twig/lib/Twig/Node/For.php', 'Twig_Node_ForLoop' => $vendorDir . '/twig/twig/lib/Twig/Node/ForLoop.php', 'Twig_Node_If' => $vendorDir . '/twig/twig/lib/Twig/Node/If.php', 'Twig_Node_Import' => $vendorDir . '/twig/twig/lib/Twig/Node/Import.php', 'Twig_Node_Include' => $vendorDir . '/twig/twig/lib/Twig/Node/Include.php', 'Twig_Node_Macro' => $vendorDir . '/twig/twig/lib/Twig/Node/Macro.php', 'Twig_Node_Module' => $vendorDir . '/twig/twig/lib/Twig/Node/Module.php', 'Twig_Node_Print' => $vendorDir . '/twig/twig/lib/Twig/Node/Print.php', 'Twig_Node_Sandbox' => $vendorDir . '/twig/twig/lib/Twig/Node/Sandbox.php', 'Twig_Node_SandboxedPrint' => $vendorDir . '/twig/twig/lib/Twig/Node/SandboxedPrint.php', 'Twig_Node_Set' => $vendorDir . '/twig/twig/lib/Twig/Node/Set.php', 'Twig_Node_SetTemp' => $vendorDir . '/twig/twig/lib/Twig/Node/SetTemp.php', 'Twig_Node_Spaceless' => $vendorDir . '/twig/twig/lib/Twig/Node/Spaceless.php', 'Twig_Node_Text' => $vendorDir . '/twig/twig/lib/Twig/Node/Text.php', 'Twig_Parser' => $vendorDir . '/twig/twig/lib/Twig/Parser.php', 'Twig_ParserInterface' => $vendorDir . '/twig/twig/lib/Twig/ParserInterface.php', 'Twig_Profiler_Dumper_Blackfire' => $vendorDir . '/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php', 'Twig_Profiler_Dumper_Html' => $vendorDir . '/twig/twig/lib/Twig/Profiler/Dumper/Html.php', 'Twig_Profiler_Dumper_Text' => $vendorDir . '/twig/twig/lib/Twig/Profiler/Dumper/Text.php', 'Twig_Profiler_NodeVisitor_Profiler' => $vendorDir . '/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php', 'Twig_Profiler_Node_EnterProfile' => $vendorDir . '/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php', 'Twig_Profiler_Node_LeaveProfile' => $vendorDir . '/twig/twig/lib/Twig/Profiler/Node/LeaveProfile.php', 'Twig_Profiler_Profile' => $vendorDir . '/twig/twig/lib/Twig/Profiler/Profile.php', 'Twig_Sandbox_SecurityError' => $vendorDir . '/twig/twig/lib/Twig/Sandbox/SecurityError.php', 'Twig_Sandbox_SecurityNotAllowedFilterError' => $vendorDir . '/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php', 'Twig_Sandbox_SecurityNotAllowedFunctionError' => $vendorDir . '/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php', 'Twig_Sandbox_SecurityNotAllowedTagError' => $vendorDir . '/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php', 'Twig_Sandbox_SecurityPolicy' => $vendorDir . '/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php', 'Twig_Sandbox_SecurityPolicyInterface' => $vendorDir . '/twig/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php', 'Twig_SimpleFilter' => $vendorDir . '/twig/twig/lib/Twig/SimpleFilter.php', 'Twig_SimpleFunction' => $vendorDir . '/twig/twig/lib/Twig/SimpleFunction.php', 'Twig_SimpleTest' => $vendorDir . '/twig/twig/lib/Twig/SimpleTest.php', 'Twig_Template' => $vendorDir . '/twig/twig/lib/Twig/Template.php', 'Twig_TemplateInterface' => $vendorDir . '/twig/twig/lib/Twig/TemplateInterface.php', 'Twig_Test' => $vendorDir . '/twig/twig/lib/Twig/Test.php', 'Twig_TestCallableInterface' => $vendorDir . '/twig/twig/lib/Twig/TestCallableInterface.php', 'Twig_TestInterface' => $vendorDir . '/twig/twig/lib/Twig/TestInterface.php', 'Twig_Test_Function' => $vendorDir . '/twig/twig/lib/Twig/Test/Function.php', 'Twig_Test_IntegrationTestCase' => $vendorDir . '/twig/twig/lib/Twig/Test/IntegrationTestCase.php', 'Twig_Test_Method' => $vendorDir . '/twig/twig/lib/Twig/Test/Method.php', 'Twig_Test_Node' => $vendorDir . '/twig/twig/lib/Twig/Test/Node.php', 'Twig_Test_NodeTestCase' => $vendorDir . '/twig/twig/lib/Twig/Test/NodeTestCase.php', 'Twig_Token' => $vendorDir . '/twig/twig/lib/Twig/Token.php', 'Twig_TokenParser' => $vendorDir . '/twig/twig/lib/Twig/TokenParser.php', 'Twig_TokenParserBroker' => $vendorDir . '/twig/twig/lib/Twig/TokenParserBroker.php', 'Twig_TokenParserBrokerInterface' => $vendorDir . '/twig/twig/lib/Twig/TokenParserBrokerInterface.php', 'Twig_TokenParserInterface' => $vendorDir . '/twig/twig/lib/Twig/TokenParserInterface.php', 'Twig_TokenParser_AutoEscape' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/AutoEscape.php', 'Twig_TokenParser_Block' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Block.php', 'Twig_TokenParser_Do' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Do.php', 'Twig_TokenParser_Embed' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Embed.php', 'Twig_TokenParser_Extends' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Extends.php', 'Twig_TokenParser_Filter' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Filter.php', 'Twig_TokenParser_Flush' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Flush.php', 'Twig_TokenParser_For' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/For.php', 'Twig_TokenParser_From' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/From.php', 'Twig_TokenParser_If' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/If.php', 'Twig_TokenParser_Import' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Import.php', 'Twig_TokenParser_Include' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Include.php', 'Twig_TokenParser_Macro' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Macro.php', 'Twig_TokenParser_Sandbox' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Sandbox.php', 'Twig_TokenParser_Set' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Set.php', 'Twig_TokenParser_Spaceless' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Spaceless.php', 'Twig_TokenParser_Use' => $vendorDir . '/twig/twig/lib/Twig/TokenParser/Use.php', 'Twig_TokenStream' => $vendorDir . '/twig/twig/lib/Twig/TokenStream.php', 'Twig_Util_DeprecationCollector' => $vendorDir . '/twig/twig/lib/Twig/Util/DeprecationCollector.php', 'Twig_Util_TemplateDirIterator' => $vendorDir . '/twig/twig/lib/Twig/Util/TemplateDirIterator.php', 'Zend\\Cache\\Exception\\BadMethodCallException' => $vendorDir . '/zendframework/zend-cache/src/Exception/BadMethodCallException.php', 'Zend\\Cache\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-cache/src/Exception/ExceptionInterface.php', 'Zend\\Cache\\Exception\\ExtensionNotLoadedException' => $vendorDir . '/zendframework/zend-cache/src/Exception/ExtensionNotLoadedException.php', 'Zend\\Cache\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-cache/src/Exception/InvalidArgumentException.php', 'Zend\\Cache\\Exception\\LogicException' => $vendorDir . '/zendframework/zend-cache/src/Exception/LogicException.php', 'Zend\\Cache\\Exception\\MissingDependencyException' => $vendorDir . '/zendframework/zend-cache/src/Exception/MissingDependencyException.php', 'Zend\\Cache\\Exception\\MissingKeyException' => $vendorDir . '/zendframework/zend-cache/src/Exception/MissingKeyException.php', 'Zend\\Cache\\Exception\\OutOfSpaceException' => $vendorDir . '/zendframework/zend-cache/src/Exception/OutOfSpaceException.php', 'Zend\\Cache\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-cache/src/Exception/RuntimeException.php', 'Zend\\Cache\\Exception\\UnexpectedValueException' => $vendorDir . '/zendframework/zend-cache/src/Exception/UnexpectedValueException.php', 'Zend\\Cache\\Exception\\UnsupportedMethodCallException' => $vendorDir . '/zendframework/zend-cache/src/Exception/UnsupportedMethodCallException.php', 'Zend\\Cache\\PatternFactory' => $vendorDir . '/zendframework/zend-cache/src/PatternFactory.php', 'Zend\\Cache\\PatternPluginManager' => $vendorDir . '/zendframework/zend-cache/src/PatternPluginManager.php', 'Zend\\Cache\\Pattern\\AbstractPattern' => $vendorDir . '/zendframework/zend-cache/src/Pattern/AbstractPattern.php', 'Zend\\Cache\\Pattern\\CallbackCache' => $vendorDir . '/zendframework/zend-cache/src/Pattern/CallbackCache.php', 'Zend\\Cache\\Pattern\\CaptureCache' => $vendorDir . '/zendframework/zend-cache/src/Pattern/CaptureCache.php', 'Zend\\Cache\\Pattern\\ClassCache' => $vendorDir . '/zendframework/zend-cache/src/Pattern/ClassCache.php', 'Zend\\Cache\\Pattern\\ObjectCache' => $vendorDir . '/zendframework/zend-cache/src/Pattern/ObjectCache.php', 'Zend\\Cache\\Pattern\\OutputCache' => $vendorDir . '/zendframework/zend-cache/src/Pattern/OutputCache.php', 'Zend\\Cache\\Pattern\\PatternInterface' => $vendorDir . '/zendframework/zend-cache/src/Pattern/PatternInterface.php', 'Zend\\Cache\\Pattern\\PatternOptions' => $vendorDir . '/zendframework/zend-cache/src/Pattern/PatternOptions.php', 'Zend\\Cache\\Service\\StorageCacheAbstractServiceFactory' => $vendorDir . '/zendframework/zend-cache/src/Service/StorageCacheAbstractServiceFactory.php', 'Zend\\Cache\\Service\\StorageCacheFactory' => $vendorDir . '/zendframework/zend-cache/src/Service/StorageCacheFactory.php', 'Zend\\Cache\\StorageFactory' => $vendorDir . '/zendframework/zend-cache/src/StorageFactory.php', 'Zend\\Cache\\Storage\\AdapterPluginManager' => $vendorDir . '/zendframework/zend-cache/src/Storage/AdapterPluginManager.php', 'Zend\\Cache\\Storage\\Adapter\\AbstractAdapter' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/AbstractAdapter.php', 'Zend\\Cache\\Storage\\Adapter\\AbstractZendServer' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/AbstractZendServer.php', 'Zend\\Cache\\Storage\\Adapter\\AdapterOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/AdapterOptions.php', 'Zend\\Cache\\Storage\\Adapter\\Apc' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/Apc.php', 'Zend\\Cache\\Storage\\Adapter\\ApcIterator' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/ApcIterator.php', 'Zend\\Cache\\Storage\\Adapter\\ApcOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/ApcOptions.php', 'Zend\\Cache\\Storage\\Adapter\\Dba' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/Dba.php', 'Zend\\Cache\\Storage\\Adapter\\DbaIterator' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/DbaIterator.php', 'Zend\\Cache\\Storage\\Adapter\\DbaOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/DbaOptions.php', 'Zend\\Cache\\Storage\\Adapter\\Filesystem' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/Filesystem.php', 'Zend\\Cache\\Storage\\Adapter\\FilesystemIterator' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/FilesystemIterator.php', 'Zend\\Cache\\Storage\\Adapter\\FilesystemOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/FilesystemOptions.php', 'Zend\\Cache\\Storage\\Adapter\\KeyListIterator' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/KeyListIterator.php', 'Zend\\Cache\\Storage\\Adapter\\Memcached' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/Memcached.php', 'Zend\\Cache\\Storage\\Adapter\\MemcachedOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/MemcachedOptions.php', 'Zend\\Cache\\Storage\\Adapter\\MemcachedResourceManager' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/MemcachedResourceManager.php', 'Zend\\Cache\\Storage\\Adapter\\Memory' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/Memory.php', 'Zend\\Cache\\Storage\\Adapter\\MemoryOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/MemoryOptions.php', 'Zend\\Cache\\Storage\\Adapter\\Redis' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/Redis.php', 'Zend\\Cache\\Storage\\Adapter\\RedisOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/RedisOptions.php', 'Zend\\Cache\\Storage\\Adapter\\RedisResourceManager' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/RedisResourceManager.php', 'Zend\\Cache\\Storage\\Adapter\\Session' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/Session.php', 'Zend\\Cache\\Storage\\Adapter\\SessionOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/SessionOptions.php', 'Zend\\Cache\\Storage\\Adapter\\WinCache' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/WinCache.php', 'Zend\\Cache\\Storage\\Adapter\\WinCacheOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/WinCacheOptions.php', 'Zend\\Cache\\Storage\\Adapter\\XCache' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/XCache.php', 'Zend\\Cache\\Storage\\Adapter\\XCacheOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/XCacheOptions.php', 'Zend\\Cache\\Storage\\Adapter\\ZendServerDisk' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/ZendServerDisk.php', 'Zend\\Cache\\Storage\\Adapter\\ZendServerShm' => $vendorDir . '/zendframework/zend-cache/src/Storage/Adapter/ZendServerShm.php', 'Zend\\Cache\\Storage\\AvailableSpaceCapableInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/AvailableSpaceCapableInterface.php', 'Zend\\Cache\\Storage\\Capabilities' => $vendorDir . '/zendframework/zend-cache/src/Storage/Capabilities.php', 'Zend\\Cache\\Storage\\ClearByNamespaceInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/ClearByNamespaceInterface.php', 'Zend\\Cache\\Storage\\ClearByPrefixInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/ClearByPrefixInterface.php', 'Zend\\Cache\\Storage\\ClearExpiredInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/ClearExpiredInterface.php', 'Zend\\Cache\\Storage\\Event' => $vendorDir . '/zendframework/zend-cache/src/Storage/Event.php', 'Zend\\Cache\\Storage\\ExceptionEvent' => $vendorDir . '/zendframework/zend-cache/src/Storage/ExceptionEvent.php', 'Zend\\Cache\\Storage\\FlushableInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/FlushableInterface.php', 'Zend\\Cache\\Storage\\IterableInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/IterableInterface.php', 'Zend\\Cache\\Storage\\IteratorInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/IteratorInterface.php', 'Zend\\Cache\\Storage\\OptimizableInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/OptimizableInterface.php', 'Zend\\Cache\\Storage\\PluginManager' => $vendorDir . '/zendframework/zend-cache/src/Storage/PluginManager.php', 'Zend\\Cache\\Storage\\Plugin\\AbstractPlugin' => $vendorDir . '/zendframework/zend-cache/src/Storage/Plugin/AbstractPlugin.php', 'Zend\\Cache\\Storage\\Plugin\\ClearExpiredByFactor' => $vendorDir . '/zendframework/zend-cache/src/Storage/Plugin/ClearExpiredByFactor.php', 'Zend\\Cache\\Storage\\Plugin\\ExceptionHandler' => $vendorDir . '/zendframework/zend-cache/src/Storage/Plugin/ExceptionHandler.php', 'Zend\\Cache\\Storage\\Plugin\\IgnoreUserAbort' => $vendorDir . '/zendframework/zend-cache/src/Storage/Plugin/IgnoreUserAbort.php', 'Zend\\Cache\\Storage\\Plugin\\OptimizeByFactor' => $vendorDir . '/zendframework/zend-cache/src/Storage/Plugin/OptimizeByFactor.php', 'Zend\\Cache\\Storage\\Plugin\\PluginInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/Plugin/PluginInterface.php', 'Zend\\Cache\\Storage\\Plugin\\PluginOptions' => $vendorDir . '/zendframework/zend-cache/src/Storage/Plugin/PluginOptions.php', 'Zend\\Cache\\Storage\\Plugin\\Serializer' => $vendorDir . '/zendframework/zend-cache/src/Storage/Plugin/Serializer.php', 'Zend\\Cache\\Storage\\PostEvent' => $vendorDir . '/zendframework/zend-cache/src/Storage/PostEvent.php', 'Zend\\Cache\\Storage\\StorageInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/StorageInterface.php', 'Zend\\Cache\\Storage\\TaggableInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/TaggableInterface.php', 'Zend\\Cache\\Storage\\TotalSpaceCapableInterface' => $vendorDir . '/zendframework/zend-cache/src/Storage/TotalSpaceCapableInterface.php', 'Zend\\Config\\Config' => $vendorDir . '/zendframework/zend-config/src/Config.php', 'Zend\\Config\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-config/src/Exception/ExceptionInterface.php', 'Zend\\Config\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-config/src/Exception/InvalidArgumentException.php', 'Zend\\Config\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-config/src/Exception/RuntimeException.php', 'Zend\\Config\\Factory' => $vendorDir . '/zendframework/zend-config/src/Factory.php', 'Zend\\Config\\Processor\\Constant' => $vendorDir . '/zendframework/zend-config/src/Processor/Constant.php', 'Zend\\Config\\Processor\\Filter' => $vendorDir . '/zendframework/zend-config/src/Processor/Filter.php', 'Zend\\Config\\Processor\\ProcessorInterface' => $vendorDir . '/zendframework/zend-config/src/Processor/ProcessorInterface.php', 'Zend\\Config\\Processor\\Queue' => $vendorDir . '/zendframework/zend-config/src/Processor/Queue.php', 'Zend\\Config\\Processor\\Token' => $vendorDir . '/zendframework/zend-config/src/Processor/Token.php', 'Zend\\Config\\Processor\\Translator' => $vendorDir . '/zendframework/zend-config/src/Processor/Translator.php', 'Zend\\Config\\ReaderPluginManager' => $vendorDir . '/zendframework/zend-config/src/ReaderPluginManager.php', 'Zend\\Config\\Reader\\Ini' => $vendorDir . '/zendframework/zend-config/src/Reader/Ini.php', 'Zend\\Config\\Reader\\Json' => $vendorDir . '/zendframework/zend-config/src/Reader/Json.php', 'Zend\\Config\\Reader\\ReaderInterface' => $vendorDir . '/zendframework/zend-config/src/Reader/ReaderInterface.php', 'Zend\\Config\\Reader\\Xml' => $vendorDir . '/zendframework/zend-config/src/Reader/Xml.php', 'Zend\\Config\\Reader\\Yaml' => $vendorDir . '/zendframework/zend-config/src/Reader/Yaml.php', 'Zend\\Config\\WriterPluginManager' => $vendorDir . '/zendframework/zend-config/src/WriterPluginManager.php', 'Zend\\Config\\Writer\\AbstractWriter' => $vendorDir . '/zendframework/zend-config/src/Writer/AbstractWriter.php', 'Zend\\Config\\Writer\\Ini' => $vendorDir . '/zendframework/zend-config/src/Writer/Ini.php', 'Zend\\Config\\Writer\\Json' => $vendorDir . '/zendframework/zend-config/src/Writer/Json.php', 'Zend\\Config\\Writer\\PhpArray' => $vendorDir . '/zendframework/zend-config/src/Writer/PhpArray.php', 'Zend\\Config\\Writer\\WriterInterface' => $vendorDir . '/zendframework/zend-config/src/Writer/WriterInterface.php', 'Zend\\Config\\Writer\\Xml' => $vendorDir . '/zendframework/zend-config/src/Writer/Xml.php', 'Zend\\Config\\Writer\\Yaml' => $vendorDir . '/zendframework/zend-config/src/Writer/Yaml.php', 'Zend\\EventManager\\AbstractListenerAggregate' => $vendorDir . '/zendframework/zend-eventmanager/src/AbstractListenerAggregate.php', 'Zend\\EventManager\\Event' => $vendorDir . '/zendframework/zend-eventmanager/src/Event.php', 'Zend\\EventManager\\EventInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/EventInterface.php', 'Zend\\EventManager\\EventManager' => $vendorDir . '/zendframework/zend-eventmanager/src/EventManager.php', 'Zend\\EventManager\\EventManagerAwareInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/EventManagerAwareInterface.php', 'Zend\\EventManager\\EventManagerAwareTrait' => $vendorDir . '/zendframework/zend-eventmanager/src/EventManagerAwareTrait.php', 'Zend\\EventManager\\EventManagerInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/EventManagerInterface.php', 'Zend\\EventManager\\EventsCapableInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/EventsCapableInterface.php', 'Zend\\EventManager\\Exception\\DomainException' => $vendorDir . '/zendframework/zend-eventmanager/src/Exception/DomainException.php', 'Zend\\EventManager\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/Exception/ExceptionInterface.php', 'Zend\\EventManager\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-eventmanager/src/Exception/InvalidArgumentException.php', 'Zend\\EventManager\\Exception\\InvalidCallbackException' => $vendorDir . '/zendframework/zend-eventmanager/src/Exception/InvalidCallbackException.php', 'Zend\\EventManager\\FilterChain' => $vendorDir . '/zendframework/zend-eventmanager/src/FilterChain.php', 'Zend\\EventManager\\Filter\\FilterInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/Filter/FilterInterface.php', 'Zend\\EventManager\\Filter\\FilterIterator' => $vendorDir . '/zendframework/zend-eventmanager/src/Filter/FilterIterator.php', 'Zend\\EventManager\\GlobalEventManager' => $vendorDir . '/zendframework/zend-eventmanager/src/GlobalEventManager.php', 'Zend\\EventManager\\ListenerAggregateInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/ListenerAggregateInterface.php', 'Zend\\EventManager\\ListenerAggregateTrait' => $vendorDir . '/zendframework/zend-eventmanager/src/ListenerAggregateTrait.php', 'Zend\\EventManager\\ProvidesEvents' => $vendorDir . '/zendframework/zend-eventmanager/src/ProvidesEvents.php', 'Zend\\EventManager\\ResponseCollection' => $vendorDir . '/zendframework/zend-eventmanager/src/ResponseCollection.php', 'Zend\\EventManager\\SharedEventAggregateAwareInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/SharedEventAggregateAwareInterface.php', 'Zend\\EventManager\\SharedEventManager' => $vendorDir . '/zendframework/zend-eventmanager/src/SharedEventManager.php', 'Zend\\EventManager\\SharedEventManagerAwareInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/SharedEventManagerAwareInterface.php', 'Zend\\EventManager\\SharedEventManagerInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/SharedEventManagerInterface.php', 'Zend\\EventManager\\SharedListenerAggregateInterface' => $vendorDir . '/zendframework/zend-eventmanager/src/SharedListenerAggregateInterface.php', 'Zend\\EventManager\\StaticEventManager' => $vendorDir . '/zendframework/zend-eventmanager/src/StaticEventManager.php', 'Zend\\Filter\\AbstractFilter' => $vendorDir . '/zendframework/zend-filter/src/AbstractFilter.php', 'Zend\\Filter\\AbstractUnicode' => $vendorDir . '/zendframework/zend-filter/src/AbstractUnicode.php', 'Zend\\Filter\\BaseName' => $vendorDir . '/zendframework/zend-filter/src/BaseName.php', 'Zend\\Filter\\Boolean' => $vendorDir . '/zendframework/zend-filter/src/Boolean.php', 'Zend\\Filter\\Callback' => $vendorDir . '/zendframework/zend-filter/src/Callback.php', 'Zend\\Filter\\Compress' => $vendorDir . '/zendframework/zend-filter/src/Compress.php', 'Zend\\Filter\\Compress\\AbstractCompressionAlgorithm' => $vendorDir . '/zendframework/zend-filter/src/Compress/AbstractCompressionAlgorithm.php', 'Zend\\Filter\\Compress\\Bz2' => $vendorDir . '/zendframework/zend-filter/src/Compress/Bz2.php', 'Zend\\Filter\\Compress\\CompressionAlgorithmInterface' => $vendorDir . '/zendframework/zend-filter/src/Compress/CompressionAlgorithmInterface.php', 'Zend\\Filter\\Compress\\Gz' => $vendorDir . '/zendframework/zend-filter/src/Compress/Gz.php', 'Zend\\Filter\\Compress\\Lzf' => $vendorDir . '/zendframework/zend-filter/src/Compress/Lzf.php', 'Zend\\Filter\\Compress\\Rar' => $vendorDir . '/zendframework/zend-filter/src/Compress/Rar.php', 'Zend\\Filter\\Compress\\Snappy' => $vendorDir . '/zendframework/zend-filter/src/Compress/Snappy.php', 'Zend\\Filter\\Compress\\Tar' => $vendorDir . '/zendframework/zend-filter/src/Compress/Tar.php', 'Zend\\Filter\\Compress\\Zip' => $vendorDir . '/zendframework/zend-filter/src/Compress/Zip.php', 'Zend\\Filter\\DateTimeFormatter' => $vendorDir . '/zendframework/zend-filter/src/DateTimeFormatter.php', 'Zend\\Filter\\Decompress' => $vendorDir . '/zendframework/zend-filter/src/Decompress.php', 'Zend\\Filter\\Decrypt' => $vendorDir . '/zendframework/zend-filter/src/Decrypt.php', 'Zend\\Filter\\Digits' => $vendorDir . '/zendframework/zend-filter/src/Digits.php', 'Zend\\Filter\\Dir' => $vendorDir . '/zendframework/zend-filter/src/Dir.php', 'Zend\\Filter\\Encrypt' => $vendorDir . '/zendframework/zend-filter/src/Encrypt.php', 'Zend\\Filter\\Encrypt\\BlockCipher' => $vendorDir . '/zendframework/zend-filter/src/Encrypt/BlockCipher.php', 'Zend\\Filter\\Encrypt\\EncryptionAlgorithmInterface' => $vendorDir . '/zendframework/zend-filter/src/Encrypt/EncryptionAlgorithmInterface.php', 'Zend\\Filter\\Encrypt\\Openssl' => $vendorDir . '/zendframework/zend-filter/src/Encrypt/Openssl.php', 'Zend\\Filter\\Exception\\BadMethodCallException' => $vendorDir . '/zendframework/zend-filter/src/Exception/BadMethodCallException.php', 'Zend\\Filter\\Exception\\DomainException' => $vendorDir . '/zendframework/zend-filter/src/Exception/DomainException.php', 'Zend\\Filter\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-filter/src/Exception/ExceptionInterface.php', 'Zend\\Filter\\Exception\\ExtensionNotLoadedException' => $vendorDir . '/zendframework/zend-filter/src/Exception/ExtensionNotLoadedException.php', 'Zend\\Filter\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-filter/src/Exception/InvalidArgumentException.php', 'Zend\\Filter\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-filter/src/Exception/RuntimeException.php', 'Zend\\Filter\\File\\Decrypt' => $vendorDir . '/zendframework/zend-filter/src/File/Decrypt.php', 'Zend\\Filter\\File\\Encrypt' => $vendorDir . '/zendframework/zend-filter/src/File/Encrypt.php', 'Zend\\Filter\\File\\LowerCase' => $vendorDir . '/zendframework/zend-filter/src/File/LowerCase.php', 'Zend\\Filter\\File\\Rename' => $vendorDir . '/zendframework/zend-filter/src/File/Rename.php', 'Zend\\Filter\\File\\RenameUpload' => $vendorDir . '/zendframework/zend-filter/src/File/RenameUpload.php', 'Zend\\Filter\\File\\UpperCase' => $vendorDir . '/zendframework/zend-filter/src/File/UpperCase.php', 'Zend\\Filter\\FilterChain' => $vendorDir . '/zendframework/zend-filter/src/FilterChain.php', 'Zend\\Filter\\FilterInterface' => $vendorDir . '/zendframework/zend-filter/src/FilterInterface.php', 'Zend\\Filter\\FilterPluginManager' => $vendorDir . '/zendframework/zend-filter/src/FilterPluginManager.php', 'Zend\\Filter\\HtmlEntities' => $vendorDir . '/zendframework/zend-filter/src/HtmlEntities.php', 'Zend\\Filter\\Inflector' => $vendorDir . '/zendframework/zend-filter/src/Inflector.php', 'Zend\\Filter\\Int' => $vendorDir . '/zendframework/zend-filter/src/Int.php', 'Zend\\Filter\\Null' => $vendorDir . '/zendframework/zend-filter/src/Null.php', 'Zend\\Filter\\PregReplace' => $vendorDir . '/zendframework/zend-filter/src/PregReplace.php', 'Zend\\Filter\\RealPath' => $vendorDir . '/zendframework/zend-filter/src/RealPath.php', 'Zend\\Filter\\StaticFilter' => $vendorDir . '/zendframework/zend-filter/src/StaticFilter.php', 'Zend\\Filter\\StringToLower' => $vendorDir . '/zendframework/zend-filter/src/StringToLower.php', 'Zend\\Filter\\StringToUpper' => $vendorDir . '/zendframework/zend-filter/src/StringToUpper.php', 'Zend\\Filter\\StringTrim' => $vendorDir . '/zendframework/zend-filter/src/StringTrim.php', 'Zend\\Filter\\StripNewlines' => $vendorDir . '/zendframework/zend-filter/src/StripNewlines.php', 'Zend\\Filter\\StripTags' => $vendorDir . '/zendframework/zend-filter/src/StripTags.php', 'Zend\\Filter\\UriNormalize' => $vendorDir . '/zendframework/zend-filter/src/UriNormalize.php', 'Zend\\Filter\\Word\\AbstractSeparator' => $vendorDir . '/zendframework/zend-filter/src/Word/AbstractSeparator.php', 'Zend\\Filter\\Word\\CamelCaseToDash' => $vendorDir . '/zendframework/zend-filter/src/Word/CamelCaseToDash.php', 'Zend\\Filter\\Word\\CamelCaseToSeparator' => $vendorDir . '/zendframework/zend-filter/src/Word/CamelCaseToSeparator.php', 'Zend\\Filter\\Word\\CamelCaseToUnderscore' => $vendorDir . '/zendframework/zend-filter/src/Word/CamelCaseToUnderscore.php', 'Zend\\Filter\\Word\\DashToCamelCase' => $vendorDir . '/zendframework/zend-filter/src/Word/DashToCamelCase.php', 'Zend\\Filter\\Word\\DashToSeparator' => $vendorDir . '/zendframework/zend-filter/src/Word/DashToSeparator.php', 'Zend\\Filter\\Word\\DashToUnderscore' => $vendorDir . '/zendframework/zend-filter/src/Word/DashToUnderscore.php', 'Zend\\Filter\\Word\\SeparatorToCamelCase' => $vendorDir . '/zendframework/zend-filter/src/Word/SeparatorToCamelCase.php', 'Zend\\Filter\\Word\\SeparatorToDash' => $vendorDir . '/zendframework/zend-filter/src/Word/SeparatorToDash.php', 'Zend\\Filter\\Word\\SeparatorToSeparator' => $vendorDir . '/zendframework/zend-filter/src/Word/SeparatorToSeparator.php', 'Zend\\Filter\\Word\\UnderscoreToCamelCase' => $vendorDir . '/zendframework/zend-filter/src/Word/UnderscoreToCamelCase.php', 'Zend\\Filter\\Word\\UnderscoreToDash' => $vendorDir . '/zendframework/zend-filter/src/Word/UnderscoreToDash.php', 'Zend\\Filter\\Word\\UnderscoreToSeparator' => $vendorDir . '/zendframework/zend-filter/src/Word/UnderscoreToSeparator.php', 'Zend\\I18n\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-i18n/src/Exception/ExceptionInterface.php', 'Zend\\I18n\\Exception\\ExtensionNotLoadedException' => $vendorDir . '/zendframework/zend-i18n/src/Exception/ExtensionNotLoadedException.php', 'Zend\\I18n\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-i18n/src/Exception/InvalidArgumentException.php', 'Zend\\I18n\\Exception\\OutOfBoundsException' => $vendorDir . '/zendframework/zend-i18n/src/Exception/OutOfBoundsException.php', 'Zend\\I18n\\Exception\\ParseException' => $vendorDir . '/zendframework/zend-i18n/src/Exception/ParseException.php', 'Zend\\I18n\\Exception\\RangeException' => $vendorDir . '/zendframework/zend-i18n/src/Exception/RangeException.php', 'Zend\\I18n\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-i18n/src/Exception/RuntimeException.php', 'Zend\\I18n\\Filter\\AbstractLocale' => $vendorDir . '/zendframework/zend-i18n/src/Filter/AbstractLocale.php', 'Zend\\I18n\\Filter\\Alnum' => $vendorDir . '/zendframework/zend-i18n/src/Filter/Alnum.php', 'Zend\\I18n\\Filter\\Alpha' => $vendorDir . '/zendframework/zend-i18n/src/Filter/Alpha.php', 'Zend\\I18n\\Filter\\NumberFormat' => $vendorDir . '/zendframework/zend-i18n/src/Filter/NumberFormat.php', 'Zend\\I18n\\Translator\\LoaderPluginManager' => $vendorDir . '/zendframework/zend-i18n/src/Translator/LoaderPluginManager.php', 'Zend\\I18n\\Translator\\Loader\\FileLoaderInterface' => $vendorDir . '/zendframework/zend-i18n/src/Translator/Loader/FileLoaderInterface.php', 'Zend\\I18n\\Translator\\Loader\\Gettext' => $vendorDir . '/zendframework/zend-i18n/src/Translator/Loader/Gettext.php', 'Zend\\I18n\\Translator\\Loader\\Ini' => $vendorDir . '/zendframework/zend-i18n/src/Translator/Loader/Ini.php', 'Zend\\I18n\\Translator\\Loader\\PhpArray' => $vendorDir . '/zendframework/zend-i18n/src/Translator/Loader/PhpArray.php', 'Zend\\I18n\\Translator\\Loader\\RemoteLoaderInterface' => $vendorDir . '/zendframework/zend-i18n/src/Translator/Loader/RemoteLoaderInterface.php', 'Zend\\I18n\\Translator\\Plural\\Parser' => $vendorDir . '/zendframework/zend-i18n/src/Translator/Plural/Parser.php', 'Zend\\I18n\\Translator\\Plural\\Rule' => $vendorDir . '/zendframework/zend-i18n/src/Translator/Plural/Rule.php', 'Zend\\I18n\\Translator\\Plural\\Symbol' => $vendorDir . '/zendframework/zend-i18n/src/Translator/Plural/Symbol.php', 'Zend\\I18n\\Translator\\TextDomain' => $vendorDir . '/zendframework/zend-i18n/src/Translator/TextDomain.php', 'Zend\\I18n\\Translator\\Translator' => $vendorDir . '/zendframework/zend-i18n/src/Translator/Translator.php', 'Zend\\I18n\\Translator\\TranslatorAwareInterface' => $vendorDir . '/zendframework/zend-i18n/src/Translator/TranslatorAwareInterface.php', 'Zend\\I18n\\Translator\\TranslatorAwareTrait' => $vendorDir . '/zendframework/zend-i18n/src/Translator/TranslatorAwareTrait.php', 'Zend\\I18n\\Translator\\TranslatorServiceFactory' => $vendorDir . '/zendframework/zend-i18n/src/Translator/TranslatorServiceFactory.php', 'Zend\\I18n\\Validator\\Alnum' => $vendorDir . '/zendframework/zend-i18n/src/Validator/Alnum.php', 'Zend\\I18n\\Validator\\Alpha' => $vendorDir . '/zendframework/zend-i18n/src/Validator/Alpha.php', 'Zend\\I18n\\Validator\\DateTime' => $vendorDir . '/zendframework/zend-i18n/src/Validator/DateTime.php', 'Zend\\I18n\\Validator\\Float' => $vendorDir . '/zendframework/zend-i18n/src/Validator/Float.php', 'Zend\\I18n\\Validator\\Int' => $vendorDir . '/zendframework/zend-i18n/src/Validator/Int.php', 'Zend\\I18n\\Validator\\PhoneNumber' => $vendorDir . '/zendframework/zend-i18n/src/Validator/PhoneNumber.php', 'Zend\\I18n\\Validator\\PostCode' => $vendorDir . '/zendframework/zend-i18n/src/Validator/PostCode.php', 'Zend\\I18n\\View\\HelperConfig' => $vendorDir . '/zendframework/zend-i18n/src/View/HelperConfig.php', 'Zend\\I18n\\View\\Helper\\AbstractTranslatorHelper' => $vendorDir . '/zendframework/zend-i18n/src/View/Helper/AbstractTranslatorHelper.php', 'Zend\\I18n\\View\\Helper\\CurrencyFormat' => $vendorDir . '/zendframework/zend-i18n/src/View/Helper/CurrencyFormat.php', 'Zend\\I18n\\View\\Helper\\DateFormat' => $vendorDir . '/zendframework/zend-i18n/src/View/Helper/DateFormat.php', 'Zend\\I18n\\View\\Helper\\NumberFormat' => $vendorDir . '/zendframework/zend-i18n/src/View/Helper/NumberFormat.php', 'Zend\\I18n\\View\\Helper\\Plural' => $vendorDir . '/zendframework/zend-i18n/src/View/Helper/Plural.php', 'Zend\\I18n\\View\\Helper\\Translate' => $vendorDir . '/zendframework/zend-i18n/src/View/Helper/Translate.php', 'Zend\\I18n\\View\\Helper\\TranslatePlural' => $vendorDir . '/zendframework/zend-i18n/src/View/Helper/TranslatePlural.php', 'Zend\\Json\\Decoder' => $vendorDir . '/zendframework/zend-json/src/Decoder.php', 'Zend\\Json\\Encoder' => $vendorDir . '/zendframework/zend-json/src/Encoder.php', 'Zend\\Json\\Exception\\BadMethodCallException' => $vendorDir . '/zendframework/zend-json/src/Exception/BadMethodCallException.php', 'Zend\\Json\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-json/src/Exception/ExceptionInterface.php', 'Zend\\Json\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-json/src/Exception/InvalidArgumentException.php', 'Zend\\Json\\Exception\\RecursionException' => $vendorDir . '/zendframework/zend-json/src/Exception/RecursionException.php', 'Zend\\Json\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-json/src/Exception/RuntimeException.php', 'Zend\\Json\\Expr' => $vendorDir . '/zendframework/zend-json/src/Expr.php', 'Zend\\Json\\Json' => $vendorDir . '/zendframework/zend-json/src/Json.php', 'Zend\\Json\\Server\\Cache' => $vendorDir . '/zendframework/zend-json/src/Server/Cache.php', 'Zend\\Json\\Server\\Client' => $vendorDir . '/zendframework/zend-json/src/Server/Client.php', 'Zend\\Json\\Server\\Error' => $vendorDir . '/zendframework/zend-json/src/Server/Error.php', 'Zend\\Json\\Server\\Exception\\ErrorException' => $vendorDir . '/zendframework/zend-json/src/Server/Exception/ErrorException.php', 'Zend\\Json\\Server\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-json/src/Server/Exception/ExceptionInterface.php', 'Zend\\Json\\Server\\Exception\\HttpException' => $vendorDir . '/zendframework/zend-json/src/Server/Exception/HttpException.php', 'Zend\\Json\\Server\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-json/src/Server/Exception/InvalidArgumentException.php', 'Zend\\Json\\Server\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-json/src/Server/Exception/RuntimeException.php', 'Zend\\Json\\Server\\Request' => $vendorDir . '/zendframework/zend-json/src/Server/Request.php', 'Zend\\Json\\Server\\Request\\Http' => $vendorDir . '/zendframework/zend-json/src/Server/Request/Http.php', 'Zend\\Json\\Server\\Response' => $vendorDir . '/zendframework/zend-json/src/Server/Response.php', 'Zend\\Json\\Server\\Response\\Http' => $vendorDir . '/zendframework/zend-json/src/Server/Response/Http.php', 'Zend\\Json\\Server\\Server' => $vendorDir . '/zendframework/zend-json/src/Server/Server.php', 'Zend\\Json\\Server\\Smd' => $vendorDir . '/zendframework/zend-json/src/Server/Smd.php', 'Zend\\Json\\Server\\Smd\\Service' => $vendorDir . '/zendframework/zend-json/src/Server/Smd/Service.php', 'Zend\\Math\\BigInteger\\AdapterPluginManager' => $vendorDir . '/zendframework/zend-math/src/BigInteger/AdapterPluginManager.php', 'Zend\\Math\\BigInteger\\Adapter\\AdapterInterface' => $vendorDir . '/zendframework/zend-math/src/BigInteger/Adapter/AdapterInterface.php', 'Zend\\Math\\BigInteger\\Adapter\\Bcmath' => $vendorDir . '/zendframework/zend-math/src/BigInteger/Adapter/Bcmath.php', 'Zend\\Math\\BigInteger\\Adapter\\Gmp' => $vendorDir . '/zendframework/zend-math/src/BigInteger/Adapter/Gmp.php', 'Zend\\Math\\BigInteger\\BigInteger' => $vendorDir . '/zendframework/zend-math/src/BigInteger/BigInteger.php', 'Zend\\Math\\BigInteger\\Exception\\DivisionByZeroException' => $vendorDir . '/zendframework/zend-math/src/BigInteger/Exception/DivisionByZeroException.php', 'Zend\\Math\\BigInteger\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-math/src/BigInteger/Exception/ExceptionInterface.php', 'Zend\\Math\\BigInteger\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-math/src/BigInteger/Exception/InvalidArgumentException.php', 'Zend\\Math\\BigInteger\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-math/src/BigInteger/Exception/RuntimeException.php', 'Zend\\Math\\Exception\\DomainException' => $vendorDir . '/zendframework/zend-math/src/Exception/DomainException.php', 'Zend\\Math\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-math/src/Exception/ExceptionInterface.php', 'Zend\\Math\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-math/src/Exception/InvalidArgumentException.php', 'Zend\\Math\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-math/src/Exception/RuntimeException.php', 'Zend\\Math\\Rand' => $vendorDir . '/zendframework/zend-math/src/Rand.php', 'Zend\\Math\\Source\\HashTiming' => $vendorDir . '/zendframework/zend-math/src/Source/HashTiming.php', 'Zend\\Serializer\\AdapterPluginManager' => $vendorDir . '/zendframework/zend-serializer/src/AdapterPluginManager.php', 'Zend\\Serializer\\Adapter\\AbstractAdapter' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/AbstractAdapter.php', 'Zend\\Serializer\\Adapter\\AdapterInterface' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/AdapterInterface.php', 'Zend\\Serializer\\Adapter\\AdapterOptions' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/AdapterOptions.php', 'Zend\\Serializer\\Adapter\\IgBinary' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/IgBinary.php', 'Zend\\Serializer\\Adapter\\Json' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/Json.php', 'Zend\\Serializer\\Adapter\\JsonOptions' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/JsonOptions.php', 'Zend\\Serializer\\Adapter\\MsgPack' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/MsgPack.php', 'Zend\\Serializer\\Adapter\\PhpCode' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/PhpCode.php', 'Zend\\Serializer\\Adapter\\PhpSerialize' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/PhpSerialize.php', 'Zend\\Serializer\\Adapter\\PythonPickle' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/PythonPickle.php', 'Zend\\Serializer\\Adapter\\PythonPickleOptions' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/PythonPickleOptions.php', 'Zend\\Serializer\\Adapter\\Wddx' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/Wddx.php', 'Zend\\Serializer\\Adapter\\WddxOptions' => $vendorDir . '/zendframework/zend-serializer/src/Adapter/WddxOptions.php', 'Zend\\Serializer\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-serializer/src/Exception/ExceptionInterface.php', 'Zend\\Serializer\\Exception\\ExtensionNotLoadedException' => $vendorDir . '/zendframework/zend-serializer/src/Exception/ExtensionNotLoadedException.php', 'Zend\\Serializer\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-serializer/src/Exception/InvalidArgumentException.php', 'Zend\\Serializer\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-serializer/src/Exception/RuntimeException.php', 'Zend\\Serializer\\Serializer' => $vendorDir . '/zendframework/zend-serializer/src/Serializer.php', 'Zend\\ServiceManager\\AbstractFactoryInterface' => $vendorDir . '/zendframework/zend-servicemanager/src/AbstractFactoryInterface.php', 'Zend\\ServiceManager\\AbstractPluginManager' => $vendorDir . '/zendframework/zend-servicemanager/src/AbstractPluginManager.php', 'Zend\\ServiceManager\\Config' => $vendorDir . '/zendframework/zend-servicemanager/src/Config.php', 'Zend\\ServiceManager\\ConfigInterface' => $vendorDir . '/zendframework/zend-servicemanager/src/ConfigInterface.php', 'Zend\\ServiceManager\\DelegatorFactoryInterface' => $vendorDir . '/zendframework/zend-servicemanager/src/DelegatorFactoryInterface.php', 'Zend\\ServiceManager\\Di\\DiAbstractServiceFactory' => $vendorDir . '/zendframework/zend-servicemanager/src/Di/DiAbstractServiceFactory.php', 'Zend\\ServiceManager\\Di\\DiInstanceManagerProxy' => $vendorDir . '/zendframework/zend-servicemanager/src/Di/DiInstanceManagerProxy.php', 'Zend\\ServiceManager\\Di\\DiServiceFactory' => $vendorDir . '/zendframework/zend-servicemanager/src/Di/DiServiceFactory.php', 'Zend\\ServiceManager\\Di\\DiServiceInitializer' => $vendorDir . '/zendframework/zend-servicemanager/src/Di/DiServiceInitializer.php', 'Zend\\ServiceManager\\Exception\\CircularDependencyFoundException' => $vendorDir . '/zendframework/zend-servicemanager/src/Exception/CircularDependencyFoundException.php', 'Zend\\ServiceManager\\Exception\\CircularReferenceException' => $vendorDir . '/zendframework/zend-servicemanager/src/Exception/CircularReferenceException.php', 'Zend\\ServiceManager\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-servicemanager/src/Exception/ExceptionInterface.php', 'Zend\\ServiceManager\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-servicemanager/src/Exception/InvalidArgumentException.php', 'Zend\\ServiceManager\\Exception\\InvalidServiceNameException' => $vendorDir . '/zendframework/zend-servicemanager/src/Exception/InvalidServiceNameException.php', 'Zend\\ServiceManager\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-servicemanager/src/Exception/RuntimeException.php', 'Zend\\ServiceManager\\Exception\\ServiceNotCreatedException' => $vendorDir . '/zendframework/zend-servicemanager/src/Exception/ServiceNotCreatedException.php', 'Zend\\ServiceManager\\Exception\\ServiceNotFoundException' => $vendorDir . '/zendframework/zend-servicemanager/src/Exception/ServiceNotFoundException.php', 'Zend\\ServiceManager\\FactoryInterface' => $vendorDir . '/zendframework/zend-servicemanager/src/FactoryInterface.php', 'Zend\\ServiceManager\\InitializerInterface' => $vendorDir . '/zendframework/zend-servicemanager/src/InitializerInterface.php', 'Zend\\ServiceManager\\MutableCreationOptionsInterface' => $vendorDir . '/zendframework/zend-servicemanager/src/MutableCreationOptionsInterface.php', 'Zend\\ServiceManager\\Proxy\\LazyServiceFactory' => $vendorDir . '/zendframework/zend-servicemanager/src/Proxy/LazyServiceFactory.php', 'Zend\\ServiceManager\\Proxy\\LazyServiceFactoryFactory' => $vendorDir . '/zendframework/zend-servicemanager/src/Proxy/LazyServiceFactoryFactory.php', 'Zend\\ServiceManager\\ServiceLocatorAwareInterface' => $vendorDir . '/zendframework/zend-servicemanager/src/ServiceLocatorAwareInterface.php', 'Zend\\ServiceManager\\ServiceLocatorAwareTrait' => $vendorDir . '/zendframework/zend-servicemanager/src/ServiceLocatorAwareTrait.php', 'Zend\\ServiceManager\\ServiceLocatorInterface' => $vendorDir . '/zendframework/zend-servicemanager/src/ServiceLocatorInterface.php', 'Zend\\ServiceManager\\ServiceManager' => $vendorDir . '/zendframework/zend-servicemanager/src/ServiceManager.php', 'Zend\\ServiceManager\\ServiceManagerAwareInterface' => $vendorDir . '/zendframework/zend-servicemanager/src/ServiceManagerAwareInterface.php', 'Zend\\Stdlib\\AbstractOptions' => $vendorDir . '/zendframework/zend-stdlib/src/AbstractOptions.php', 'Zend\\Stdlib\\ArrayObject' => $vendorDir . '/zendframework/zend-stdlib/src/ArrayObject.php', 'Zend\\Stdlib\\ArrayObject\\PhpLegacyCompatibility' => $vendorDir . '/zendframework/zend-stdlib/src/ArrayObject/PhpLegacyCompatibility.php', 'Zend\\Stdlib\\ArrayObject\\PhpReferenceCompatibility' => $vendorDir . '/zendframework/zend-stdlib/src/ArrayObject/PhpReferenceCompatibility.php', 'Zend\\Stdlib\\ArraySerializableInterface' => $vendorDir . '/zendframework/zend-stdlib/src/ArraySerializableInterface.php', 'Zend\\Stdlib\\ArrayStack' => $vendorDir . '/zendframework/zend-stdlib/src/ArrayStack.php', 'Zend\\Stdlib\\ArrayUtils' => $vendorDir . '/zendframework/zend-stdlib/src/ArrayUtils.php', 'Zend\\Stdlib\\CallbackHandler' => $vendorDir . '/zendframework/zend-stdlib/src/CallbackHandler.php', 'Zend\\Stdlib\\DateTime' => $vendorDir . '/zendframework/zend-stdlib/src/DateTime.php', 'Zend\\Stdlib\\DispatchableInterface' => $vendorDir . '/zendframework/zend-stdlib/src/DispatchableInterface.php', 'Zend\\Stdlib\\ErrorHandler' => $vendorDir . '/zendframework/zend-stdlib/src/ErrorHandler.php', 'Zend\\Stdlib\\Exception\\BadMethodCallException' => $vendorDir . '/zendframework/zend-stdlib/src/Exception/BadMethodCallException.php', 'Zend\\Stdlib\\Exception\\DomainException' => $vendorDir . '/zendframework/zend-stdlib/src/Exception/DomainException.php', 'Zend\\Stdlib\\Exception\\ExceptionInterface' => $vendorDir . '/zendframework/zend-stdlib/src/Exception/ExceptionInterface.php', 'Zend\\Stdlib\\Exception\\ExtensionNotLoadedException' => $vendorDir . '/zendframework/zend-stdlib/src/Exception/ExtensionNotLoadedException.php', 'Zend\\Stdlib\\Exception\\InvalidArgumentException' => $vendorDir . '/zendframework/zend-stdlib/src/Exception/InvalidArgumentException.php', 'Zend\\Stdlib\\Exception\\InvalidCallbackException' => $vendorDir . '/zendframework/zend-stdlib/src/Exception/InvalidCallbackException.php', 'Zend\\Stdlib\\Exception\\LogicException' => $vendorDir . '/zendframework/zend-stdlib/src/Exception/LogicException.php', 'Zend\\Stdlib\\Exception\\RuntimeException' => $vendorDir . '/zendframework/zend-stdlib/src/Exception/RuntimeException.php', 'Zend\\Stdlib\\Glob' => $vendorDir . '/zendframework/zend-stdlib/src/Glob.php', 'Zend\\Stdlib\\Hydrator\\AbstractHydrator' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/AbstractHydrator.php', 'Zend\\Stdlib\\Hydrator\\Aggregate\\AggregateHydrator' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Aggregate/AggregateHydrator.php', 'Zend\\Stdlib\\Hydrator\\Aggregate\\ExtractEvent' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Aggregate/ExtractEvent.php', 'Zend\\Stdlib\\Hydrator\\Aggregate\\HydrateEvent' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Aggregate/HydrateEvent.php', 'Zend\\Stdlib\\Hydrator\\Aggregate\\HydratorListener' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Aggregate/HydratorListener.php', 'Zend\\Stdlib\\Hydrator\\ArraySerializable' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/ArraySerializable.php', 'Zend\\Stdlib\\Hydrator\\ClassMethods' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/ClassMethods.php', 'Zend\\Stdlib\\Hydrator\\Filter\\FilterComposite' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Filter/FilterComposite.php', 'Zend\\Stdlib\\Hydrator\\Filter\\FilterInterface' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Filter/FilterInterface.php', 'Zend\\Stdlib\\Hydrator\\Filter\\FilterProviderInterface' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Filter/FilterProviderInterface.php', 'Zend\\Stdlib\\Hydrator\\Filter\\GetFilter' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Filter/GetFilter.php', 'Zend\\Stdlib\\Hydrator\\Filter\\HasFilter' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Filter/HasFilter.php', 'Zend\\Stdlib\\Hydrator\\Filter\\IsFilter' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Filter/IsFilter.php', 'Zend\\Stdlib\\Hydrator\\Filter\\MethodMatchFilter' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Filter/MethodMatchFilter.php', 'Zend\\Stdlib\\Hydrator\\Filter\\NumberOfParameterFilter' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Filter/NumberOfParameterFilter.php', 'Zend\\Stdlib\\Hydrator\\Filter\\OptionalParametersFilter' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Filter/OptionalParametersFilter.php', 'Zend\\Stdlib\\Hydrator\\HydratorAwareInterface' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/HydratorAwareInterface.php', 'Zend\\Stdlib\\Hydrator\\HydratorInterface' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/HydratorInterface.php', 'Zend\\Stdlib\\Hydrator\\HydratorOptionsInterface' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/HydratorOptionsInterface.php', 'Zend\\Stdlib\\Hydrator\\HydratorPluginManager' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/HydratorPluginManager.php', 'Zend\\Stdlib\\Hydrator\\ObjectProperty' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/ObjectProperty.php', 'Zend\\Stdlib\\Hydrator\\Reflection' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Reflection.php', 'Zend\\Stdlib\\Hydrator\\StrategyEnabledInterface' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/StrategyEnabledInterface.php', 'Zend\\Stdlib\\Hydrator\\Strategy\\ClosureStrategy' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Strategy/ClosureStrategy.php', 'Zend\\Stdlib\\Hydrator\\Strategy\\DefaultStrategy' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Strategy/DefaultStrategy.php', 'Zend\\Stdlib\\Hydrator\\Strategy\\SerializableStrategy' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Strategy/SerializableStrategy.php', 'Zend\\Stdlib\\Hydrator\\Strategy\\StrategyInterface' => $vendorDir . '/zendframework/zend-stdlib/src/Hydrator/Strategy/StrategyInterface.php', 'Zend\\Stdlib\\InitializableInterface' => $vendorDir . '/zendframework/zend-stdlib/src/InitializableInterface.php', 'Zend\\Stdlib\\Message' => $vendorDir . '/zendframework/zend-stdlib/src/Message.php', 'Zend\\Stdlib\\MessageInterface' => $vendorDir . '/zendframework/zend-stdlib/src/MessageInterface.php', 'Zend\\Stdlib\\ParameterObjectInterface' => $vendorDir . '/zendframework/zend-stdlib/src/ParameterObjectInterface.php', 'Zend\\Stdlib\\Parameters' => $vendorDir . '/zendframework/zend-stdlib/src/Parameters.php', 'Zend\\Stdlib\\ParametersInterface' => $vendorDir . '/zendframework/zend-stdlib/src/ParametersInterface.php', 'Zend\\Stdlib\\PriorityQueue' => $vendorDir . '/zendframework/zend-stdlib/src/PriorityQueue.php', 'Zend\\Stdlib\\Request' => $vendorDir . '/zendframework/zend-stdlib/src/Request.php', 'Zend\\Stdlib\\RequestInterface' => $vendorDir . '/zendframework/zend-stdlib/src/RequestInterface.php', 'Zend\\Stdlib\\Response' => $vendorDir . '/zendframework/zend-stdlib/src/Response.php', 'Zend\\Stdlib\\ResponseInterface' => $vendorDir . '/zendframework/zend-stdlib/src/ResponseInterface.php', 'Zend\\Stdlib\\SplPriorityQueue' => $vendorDir . '/zendframework/zend-stdlib/src/SplPriorityQueue.php', 'Zend\\Stdlib\\SplQueue' => $vendorDir . '/zendframework/zend-stdlib/src/SplQueue.php', 'Zend\\Stdlib\\SplStack' => $vendorDir . '/zendframework/zend-stdlib/src/SplStack.php', 'Zend\\Stdlib\\StringUtils' => $vendorDir . '/zendframework/zend-stdlib/src/StringUtils.php', 'Zend\\Stdlib\\StringWrapper\\AbstractStringWrapper' => $vendorDir . '/zendframework/zend-stdlib/src/StringWrapper/AbstractStringWrapper.php', 'Zend\\Stdlib\\StringWrapper\\Iconv' => $vendorDir . '/zendframework/zend-stdlib/src/StringWrapper/Iconv.php', 'Zend\\Stdlib\\StringWrapper\\Intl' => $vendorDir . '/zendframework/zend-stdlib/src/StringWrapper/Intl.php', 'Zend\\Stdlib\\StringWrapper\\MbString' => $vendorDir . '/zendframework/zend-stdlib/src/StringWrapper/MbString.php', 'Zend\\Stdlib\\StringWrapper\\Native' => $vendorDir . '/zendframework/zend-stdlib/src/StringWrapper/Native.php', 'Zend\\Stdlib\\StringWrapper\\StringWrapperInterface' => $vendorDir . '/zendframework/zend-stdlib/src/StringWrapper/StringWrapperInterface.php', 'Zend_Sniffs_Debug_CodeAnalyzerSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php', 'Zend_Sniffs_Files_ClosingTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/Files/ClosingTagSniff.php', 'Zend_Sniffs_NamingConventions_ValidVariableNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php', 'ezcBase' => $vendorDir . '/zetacomponents/base/src/base.php', 'ezcBaseAutoloadException' => $vendorDir . '/zetacomponents/base/src/exceptions/autoload.php', 'ezcBaseAutoloadOptions' => $vendorDir . '/zetacomponents/base/src/options/autoload.php', 'ezcBaseConfigurationInitializer' => $vendorDir . '/zetacomponents/base/src/interfaces/configuration_initializer.php', 'ezcBaseDoubleClassRepositoryPrefixException' => $vendorDir . '/zetacomponents/base/src/exceptions/double_class_repository_prefix.php', 'ezcBaseException' => $vendorDir . '/zetacomponents/base/src/exceptions/exception.php', 'ezcBaseExportable' => $vendorDir . '/zetacomponents/base/src/interfaces/exportable.php', 'ezcBaseExtensionNotFoundException' => $vendorDir . '/zetacomponents/base/src/exceptions/extension_not_found.php', 'ezcBaseFeatures' => $vendorDir . '/zetacomponents/base/src/features.php', 'ezcBaseFile' => $vendorDir . '/zetacomponents/base/src/file.php', 'ezcBaseFileException' => $vendorDir . '/zetacomponents/base/src/exceptions/file_exception.php', 'ezcBaseFileFindContext' => $vendorDir . '/zetacomponents/base/src/structs/file_find_context.php', 'ezcBaseFileIoException' => $vendorDir . '/zetacomponents/base/src/exceptions/file_io.php', 'ezcBaseFileNotFoundException' => $vendorDir . '/zetacomponents/base/src/exceptions/file_not_found.php', 'ezcBaseFilePermissionException' => $vendorDir . '/zetacomponents/base/src/exceptions/file_permission.php', 'ezcBaseFunctionalityNotSupportedException' => $vendorDir . '/zetacomponents/base/src/exceptions/functionality_not_supported.php', 'ezcBaseInit' => $vendorDir . '/zetacomponents/base/src/init.php', 'ezcBaseInitCallbackConfiguredException' => $vendorDir . '/zetacomponents/base/src/exceptions/init_callback_configured.php', 'ezcBaseInitInvalidCallbackClassException' => $vendorDir . '/zetacomponents/base/src/exceptions/invalid_callback_class.php', 'ezcBaseInvalidParentClassException' => $vendorDir . '/zetacomponents/base/src/exceptions/invalid_parent_class.php', 'ezcBaseMetaData' => $vendorDir . '/zetacomponents/base/src/metadata.php', 'ezcBaseMetaDataPearReader' => $vendorDir . '/zetacomponents/base/src/metadata/pear.php', 'ezcBaseMetaDataTarballReader' => $vendorDir . '/zetacomponents/base/src/metadata/tarball.php', 'ezcBaseOptions' => $vendorDir . '/zetacomponents/base/src/options.php', 'ezcBasePersistable' => $vendorDir . '/zetacomponents/base/src/interfaces/persistable.php', 'ezcBasePropertyNotFoundException' => $vendorDir . '/zetacomponents/base/src/exceptions/property_not_found.php', 'ezcBasePropertyPermissionException' => $vendorDir . '/zetacomponents/base/src/exceptions/property_permission.php', 'ezcBaseRepositoryDirectory' => $vendorDir . '/zetacomponents/base/src/structs/repository_directory.php', 'ezcBaseSettingNotFoundException' => $vendorDir . '/zetacomponents/base/src/exceptions/setting_not_found.php', 'ezcBaseSettingValueException' => $vendorDir . '/zetacomponents/base/src/exceptions/setting_value.php', 'ezcBaseStruct' => $vendorDir . '/zetacomponents/base/src/struct.php', 'ezcBaseValueException' => $vendorDir . '/zetacomponents/base/src/exceptions/value.php', 'ezcBaseWhateverException' => $vendorDir . '/zetacomponents/base/src/exceptions/whatever.php', 'ezcDocument' => $vendorDir . '/zetacomponents/document/src/interfaces/document.php', 'ezcDocumentAlnumListItemGenerator' => $vendorDir . '/zetacomponents/document/src/document/pdf/item_generator/alnum.php', 'ezcDocumentAlphaListItemGenerator' => $vendorDir . '/zetacomponents/document/src/document/pdf/item_generator/alpha.php', 'ezcDocumentBBCode' => $vendorDir . '/zetacomponents/document/src/document/bbcode.php', 'ezcDocumentBBCodeBlockLevelNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/block.php', 'ezcDocumentBBCodeBulletListNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/bullet_list.php', 'ezcDocumentBBCodeClosingTagNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/tag_close.php', 'ezcDocumentBBCodeDocbookVisitor' => $vendorDir . '/zetacomponents/document/src/document/bbcode/visitor/docbook.php', 'ezcDocumentBBCodeDocumentNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/document.php', 'ezcDocumentBBCodeEmailPlugin' => $vendorDir . '/zetacomponents/document/src/document/bbcode/plugins/email.php', 'ezcDocumentBBCodeEmphasisPlugin' => $vendorDir . '/zetacomponents/document/src/document/bbcode/plugins/emphasis.php', 'ezcDocumentBBCodeEndOfFileToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token/end_of_file.php', 'ezcDocumentBBCodeEnumeratedListNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/enumerated_list.php', 'ezcDocumentBBCodeImagePlugin' => $vendorDir . '/zetacomponents/document/src/document/bbcode/plugins/image.php', 'ezcDocumentBBCodeInlineLiteralNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/inline_literal.php', 'ezcDocumentBBCodeLineBreakToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token/line_break.php', 'ezcDocumentBBCodeListEndNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/list_end.php', 'ezcDocumentBBCodeListItemNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/list_item.php', 'ezcDocumentBBCodeListItemToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token/list_item.php', 'ezcDocumentBBCodeListNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/list.php', 'ezcDocumentBBCodeLiteralBlockNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/literal_block.php', 'ezcDocumentBBCodeLiteralBlockToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token/literal_block.php', 'ezcDocumentBBCodeNewLineToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token/new_line.php', 'ezcDocumentBBCodeNoMarkupPlugin' => $vendorDir . '/zetacomponents/document/src/document/bbcode/plugins/no.php', 'ezcDocumentBBCodeNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/node.php', 'ezcDocumentBBCodeOptions' => $vendorDir . '/zetacomponents/document/src/options/document_bbcode.php', 'ezcDocumentBBCodeParagraphNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/paragraph.php', 'ezcDocumentBBCodeParser' => $vendorDir . '/zetacomponents/document/src/document/bbcode/parser.php', 'ezcDocumentBBCodePlugin' => $vendorDir . '/zetacomponents/document/src/document/bbcode/plugin.php', 'ezcDocumentBBCodeQuotePlugin' => $vendorDir . '/zetacomponents/document/src/document/bbcode/plugins/quote.php', 'ezcDocumentBBCodeSpecialCharsToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token/special_chars.php', 'ezcDocumentBBCodeTagCloseToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token/tag_clsoe.php', 'ezcDocumentBBCodeTagNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/tag.php', 'ezcDocumentBBCodeTagOpenToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token/tag_open.php', 'ezcDocumentBBCodeTextLineToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token/text_line.php', 'ezcDocumentBBCodeTextNode' => $vendorDir . '/zetacomponents/document/src/document/bbcode/nodes/text.php', 'ezcDocumentBBCodeToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token.php', 'ezcDocumentBBCodeTokenizer' => $vendorDir . '/zetacomponents/document/src/document/bbcode/tokenizer.php', 'ezcDocumentBBCodeUrlPlugin' => $vendorDir . '/zetacomponents/document/src/document/bbcode/plugins/url.php', 'ezcDocumentBBCodeVisitor' => $vendorDir . '/zetacomponents/document/src/document/bbcode/visitor.php', 'ezcDocumentBBCodeWhitespaceToken' => $vendorDir . '/zetacomponents/document/src/document/bbcode/token/whitespace.php', 'ezcDocumentBulletListItemGenerator' => $vendorDir . '/zetacomponents/document/src/document/pdf/item_generator/bullet.php', 'ezcDocumentConfluenceWiki' => $vendorDir . '/zetacomponents/document/src/document/wiki/confluence.php', 'ezcDocumentConversionException' => $vendorDir . '/zetacomponents/document/src/exceptions/conversion.php', 'ezcDocumentConverter' => $vendorDir . '/zetacomponents/document/src/interfaces/converter.php', 'ezcDocumentConverterOptions' => $vendorDir . '/zetacomponents/document/src/options/converter.php', 'ezcDocumentCreoleWiki' => $vendorDir . '/zetacomponents/document/src/document/wiki/creole.php', 'ezcDocumentDocbook' => $vendorDir . '/zetacomponents/document/src/document/xml/docbook.php', 'ezcDocumentDocbookOptions' => $vendorDir . '/zetacomponents/document/src/options/document_docbook.php', 'ezcDocumentDocbookToEzXmlAnchorHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/anchor.php', 'ezcDocumentDocbookToEzXmlCommentHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/comment.php', 'ezcDocumentDocbookToEzXmlConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook_ezxml.php', 'ezcDocumentDocbookToEzXmlConverterOptions' => $vendorDir . '/zetacomponents/document/src/options/converter_docbook_ezxml.php', 'ezcDocumentDocbookToEzXmlEmphasisHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/emphasis.php', 'ezcDocumentDocbookToEzXmlExternalLinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/external_link.php', 'ezcDocumentDocbookToEzXmlFootnoteHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/footnote.php', 'ezcDocumentDocbookToEzXmlIgnoreHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/ignore.php', 'ezcDocumentDocbookToEzXmlInternalLinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/internal_link.php', 'ezcDocumentDocbookToEzXmlItemizedListHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/itemized_list.php', 'ezcDocumentDocbookToEzXmlLiteralLayoutHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/literal_layout.php', 'ezcDocumentDocbookToEzXmlMappingHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/mapper.php', 'ezcDocumentDocbookToEzXmlOrderedListHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/ordered_list.php', 'ezcDocumentDocbookToEzXmlParagraphHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/paragraph.php', 'ezcDocumentDocbookToEzXmlRecurseHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/recurse.php', 'ezcDocumentDocbookToEzXmlSectionHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/section.php', 'ezcDocumentDocbookToEzXmlTableCellHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/table_cell.php', 'ezcDocumentDocbookToEzXmlTableHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/table.php', 'ezcDocumentDocbookToEzXmlTitleHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/ezxml/title.php', 'ezcDocumentDocbookToHtmlAnchorHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/anchor.php', 'ezcDocumentDocbookToHtmlBaseHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/handler.php', 'ezcDocumentDocbookToHtmlBlockquoteHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/blockquote.php', 'ezcDocumentDocbookToHtmlCommentHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/comment.php', 'ezcDocumentDocbookToHtmlConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook_html.php', 'ezcDocumentDocbookToHtmlConverterOptions' => $vendorDir . '/zetacomponents/document/src/options/converter_docbook_html.php', 'ezcDocumentDocbookToHtmlDefinitionListEntryHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/definition_list_entry.php', 'ezcDocumentDocbookToHtmlEmphasisHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/emphasis.php', 'ezcDocumentDocbookToHtmlExternalLinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/external_link.php', 'ezcDocumentDocbookToHtmlFootnoteHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/footnote.php', 'ezcDocumentDocbookToHtmlHeadHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/head.php', 'ezcDocumentDocbookToHtmlIgnoreHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/ignore.php', 'ezcDocumentDocbookToHtmlInternalLinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/internal_link.php', 'ezcDocumentDocbookToHtmlLiteralLayoutHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/literal_layout.php', 'ezcDocumentDocbookToHtmlMappingHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/mapper.php', 'ezcDocumentDocbookToHtmlMediaObjectHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/mediaobject.php', 'ezcDocumentDocbookToHtmlParagraphHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/paragraph.php', 'ezcDocumentDocbookToHtmlSectionHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/section.php', 'ezcDocumentDocbookToHtmlSpecialParagraphHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/special_paragraph.php', 'ezcDocumentDocbookToHtmlTableCellHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/xhtml/table_cell.php', 'ezcDocumentDocbookToHtmlXsltConverter' => $vendorDir . '/zetacomponents/document/src/converters/xslt/docbook_html.php', 'ezcDocumentDocbookToHtmlXsltConverterOptions' => $vendorDir . '/zetacomponents/document/src/options/converter_docbook_html_xslt.php', 'ezcDocumentDocbookToOdtAnchorHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/anchor.php', 'ezcDocumentDocbookToOdtBaseHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/handler.php', 'ezcDocumentDocbookToOdtCommentHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/comment.php', 'ezcDocumentDocbookToOdtConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook_odt.php', 'ezcDocumentDocbookToOdtConverterOptions' => $vendorDir . '/zetacomponents/document/src/options/converter_docbook_odt.php', 'ezcDocumentDocbookToOdtFootnoteHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/footnote.php', 'ezcDocumentDocbookToOdtIgnoreHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/ignore.php', 'ezcDocumentDocbookToOdtInlineHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/inline.php', 'ezcDocumentDocbookToOdtLinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/link.php', 'ezcDocumentDocbookToOdtListHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/list.php', 'ezcDocumentDocbookToOdtLiteralLayoutHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/literal_layout.php', 'ezcDocumentDocbookToOdtMappingHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/mapper.php', 'ezcDocumentDocbookToOdtMediaObjectHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/media_object.php', 'ezcDocumentDocbookToOdtPageBreakHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/page_break.php', 'ezcDocumentDocbookToOdtParagraphHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/paragraph.php', 'ezcDocumentDocbookToOdtSectionHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/section.php', 'ezcDocumentDocbookToOdtTableHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/table.php', 'ezcDocumentDocbookToOdtUlinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/element_handlers/ulink.php', 'ezcDocumentDocbookToRstBaseHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/handler.php', 'ezcDocumentDocbookToRstBeginPageHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/begin_page.php', 'ezcDocumentDocbookToRstBlockquoteHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/blockquote.php', 'ezcDocumentDocbookToRstCitationHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/citation.php', 'ezcDocumentDocbookToRstCommentHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/comment.php', 'ezcDocumentDocbookToRstConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook_rst.php', 'ezcDocumentDocbookToRstConverterOptions' => $vendorDir . '/zetacomponents/document/src/options/converter_docbook_rst.php', 'ezcDocumentDocbookToRstEmphasisHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/emphasis.php', 'ezcDocumentDocbookToRstExternalLinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/external_link.php', 'ezcDocumentDocbookToRstFootnoteHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/footnote.php', 'ezcDocumentDocbookToRstHeadHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/head.php', 'ezcDocumentDocbookToRstIgnoreHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/ignore.php', 'ezcDocumentDocbookToRstInlineMediaObjectHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/inlinemediaobject.php', 'ezcDocumentDocbookToRstInternalLinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/internal_link.php', 'ezcDocumentDocbookToRstItemizedListHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/itemized_list.php', 'ezcDocumentDocbookToRstLiteralHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/literal.php', 'ezcDocumentDocbookToRstLiteralLayoutHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/literal_layout.php', 'ezcDocumentDocbookToRstMediaObjectHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/mediaobject.php', 'ezcDocumentDocbookToRstOrderedListHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/ordered_list.php', 'ezcDocumentDocbookToRstParagraphHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/paragraph.php', 'ezcDocumentDocbookToRstRecurseHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/recurse.php', 'ezcDocumentDocbookToRstSectionHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/section.php', 'ezcDocumentDocbookToRstSpecialParagraphHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/special_paragraph.php', 'ezcDocumentDocbookToRstTableHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/table.php', 'ezcDocumentDocbookToRstVariableListHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/rst/variable_list.php', 'ezcDocumentDocbookToWikiBaseHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/handler.php', 'ezcDocumentDocbookToWikiBeginPageHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/begin_page.php', 'ezcDocumentDocbookToWikiConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook_wiki.php', 'ezcDocumentDocbookToWikiConverterOptions' => $vendorDir . '/zetacomponents/document/src/options/converter_docbook_wiki.php', 'ezcDocumentDocbookToWikiEmphasisHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/emphasis.php', 'ezcDocumentDocbookToWikiExternalLinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/external_link.php', 'ezcDocumentDocbookToWikiIgnoreHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/ignore.php', 'ezcDocumentDocbookToWikiInlineMediaObjectHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/inlinemediaobject.php', 'ezcDocumentDocbookToWikiInternalLinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/internal_link.php', 'ezcDocumentDocbookToWikiItemizedListHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/itemized_list.php', 'ezcDocumentDocbookToWikiLiteralHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/literal.php', 'ezcDocumentDocbookToWikiLiteralLayoutHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/literal_layout.php', 'ezcDocumentDocbookToWikiMediaObjectHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/mediaobject.php', 'ezcDocumentDocbookToWikiOrderedListHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/ordered_list.php', 'ezcDocumentDocbookToWikiParagraphHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/paragraph.php', 'ezcDocumentDocbookToWikiRecurseHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/recurse.php', 'ezcDocumentDocbookToWikiSectionHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/section.php', 'ezcDocumentDocbookToWikiTableHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/wiki/table.php', 'ezcDocumentDokuwikiWiki' => $vendorDir . '/zetacomponents/document/src/document/wiki/dokuwiki.php', 'ezcDocumentElementVisitorConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor.php', 'ezcDocumentElementVisitorHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor_handler.php', 'ezcDocumentErroneousXmlException' => $vendorDir . '/zetacomponents/document/src/exceptions/erroneous_xml.php', 'ezcDocumentErrorReporting' => $vendorDir . '/zetacomponents/document/src/interfaces/error_reporting.php', 'ezcDocumentException' => $vendorDir . '/zetacomponents/document/src/exceptions/exception.php', 'ezcDocumentEzXml' => $vendorDir . '/zetacomponents/document/src/document/xml/ezxml.php', 'ezcDocumentEzXmlDummyLinkConverter' => $vendorDir . '/zetacomponents/document/src/document/xml/ezxml/dummy_link_converter.php', 'ezcDocumentEzXmlDummyLinkProvider' => $vendorDir . '/zetacomponents/document/src/document/xml/ezxml/dummy_link_provider.php', 'ezcDocumentEzXmlLinkConverter' => $vendorDir . '/zetacomponents/document/src/interfaces/ezxml_link_converter.php', 'ezcDocumentEzXmlLinkProvider' => $vendorDir . '/zetacomponents/document/src/interfaces/ezxml_link_provider.php', 'ezcDocumentEzXmlOptions' => $vendorDir . '/zetacomponents/document/src/options/document_ezxml.php', 'ezcDocumentEzXmlToDocbookAnchorHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/anchor.php', 'ezcDocumentEzXmlToDocbookConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml_docbook.php', 'ezcDocumentEzXmlToDocbookConverterOptions' => $vendorDir . '/zetacomponents/document/src/options/converter_ezxml_docbook.php', 'ezcDocumentEzXmlToDocbookEmphasisHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/emphasis.php', 'ezcDocumentEzXmlToDocbookHeaderHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/header.php', 'ezcDocumentEzXmlToDocbookLineHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/line.php', 'ezcDocumentEzXmlToDocbookLinkHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/link.php', 'ezcDocumentEzXmlToDocbookListHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/list.php', 'ezcDocumentEzXmlToDocbookLiteralHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/literal.php', 'ezcDocumentEzXmlToDocbookMappingHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/mapper.php', 'ezcDocumentEzXmlToDocbookTableCellHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/table_cell.php', 'ezcDocumentEzXmlToDocbookTableHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/table.php', 'ezcDocumentEzXmlToDocbookTableRowHandler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/ezxml/docbook/table_row.php', 'ezcDocumentHtmlConverterOptions' => $vendorDir . '/zetacomponents/document/src/options/html_rendering.php', 'ezcDocumentInvalidDocbookException' => $vendorDir . '/zetacomponents/document/src/exceptions/invalid_docbook.php', 'ezcDocumentInvalidFontException' => $vendorDir . '/zetacomponents/document/src/exceptions/unknown_font.php', 'ezcDocumentInvalidOdtException' => $vendorDir . '/zetacomponents/document/src/exceptions/invalid_odt.php', 'ezcDocumentListBulletGuesser' => $vendorDir . '/zetacomponents/document/src/tools/list_bullet_guesser.php', 'ezcDocumentListItemGenerator' => $vendorDir . '/zetacomponents/document/src/document/pdf/item_generator.php', 'ezcDocumentLocateable' => $vendorDir . '/zetacomponents/document/src/interfaces/locateable.php', 'ezcDocumentLocateableDomElement' => $vendorDir . '/zetacomponents/document/src/dom_elements/locateable.php', 'ezcDocumentMissingVisitorException' => $vendorDir . '/zetacomponents/document/src/exceptions/missing_visitor.php', 'ezcDocumentNoListItemGenerator' => $vendorDir . '/zetacomponents/document/src/document/pdf/item_generator/no.php', 'ezcDocumentNumberedListItemGenerator' => $vendorDir . '/zetacomponents/document/src/document/pdf/item_generator/number.php', 'ezcDocumentOdt' => $vendorDir . '/zetacomponents/document/src/document/xml/odt.php', 'ezcDocumentOdtBaseFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/base.php', 'ezcDocumentOdtDefaultPcssConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/default.php', 'ezcDocumentOdtElementBaseFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/base.php', 'ezcDocumentOdtElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element.php', 'ezcDocumentOdtElementFootnoteFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/footnote.php', 'ezcDocumentOdtElementFrameFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/frame.php', 'ezcDocumentOdtElementHeaderFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/header.php', 'ezcDocumentOdtElementHtmlTableFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/html_table.php', 'ezcDocumentOdtElementImageFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/image.php', 'ezcDocumentOdtElementLinkFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/link.php', 'ezcDocumentOdtElementListFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/list.php', 'ezcDocumentOdtElementParagraphFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/paragraph.php', 'ezcDocumentOdtElementTableFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/table.php', 'ezcDocumentOdtElementWhitespaceFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/element/whitespace.php', 'ezcDocumentOdtEmphasisStyleFilterRule' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/style/rule/emphasis.php', 'ezcDocumentOdtFormattingProperties' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/formatting/properties.php', 'ezcDocumentOdtFormattingPropertiesExistException' => $vendorDir . '/zetacomponents/document/src/exceptions/odt/formatting_properties_exist.php', 'ezcDocumentOdtFormattingPropertyCollection' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/formatting/property_collection.php', 'ezcDocumentOdtImageFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/image.php', 'ezcDocumentOdtImageLocator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/image_locator.php', 'ezcDocumentOdtListLevelStyle' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/list_level_style.php', 'ezcDocumentOdtListLevelStyleBullet' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/list_level_style/bullet.php', 'ezcDocumentOdtListLevelStyleFilterRule' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/style/rule/list_level.php', 'ezcDocumentOdtListLevelStyleNumber' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/list_level_style/number.php', 'ezcDocumentOdtListStyle' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/list_style.php', 'ezcDocumentOdtListStyleGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/list.php', 'ezcDocumentOdtMetaGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/meta_generator.php', 'ezcDocumentOdtOptions' => $vendorDir . '/zetacomponents/document/src/options/document_odt.php', 'ezcDocumentOdtParagraphStyleGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/paragraph.php', 'ezcDocumentOdtPcssBorderConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/border.php', 'ezcDocumentOdtPcssColorConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/color.php', 'ezcDocumentOdtPcssConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter.php', 'ezcDocumentOdtPcssConverterManager' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter_manager.php', 'ezcDocumentOdtPcssConverterTools' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter_tools.php', 'ezcDocumentOdtPcssFontConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/font.php', 'ezcDocumentOdtPcssFontNameConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/font_name.php', 'ezcDocumentOdtPcssFontSizeConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/font_size.php', 'ezcDocumentOdtPcssFontStylePreprocessor' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/preprocessor/font.php', 'ezcDocumentOdtPcssListStylePreprocessor' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/preprocessor/list.php', 'ezcDocumentOdtPcssMarginConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/margin.php', 'ezcDocumentOdtPcssParagraphStylePreprocessor' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/preprocessor/paragraph.php', 'ezcDocumentOdtPcssPreprocessor' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/preprocessor.php', 'ezcDocumentOdtPcssStyler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss.php', 'ezcDocumentOdtPcssTextDecorationConverter' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/converter/text_decoration.php', 'ezcDocumentOdtStyle' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/style.php', 'ezcDocumentOdtStyleExtractor' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/style/extractor.php', 'ezcDocumentOdtStyleFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/style.php', 'ezcDocumentOdtStyleFilterRule' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/filter/style/rule.php', 'ezcDocumentOdtStyleGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator.php', 'ezcDocumentOdtStyleInferencer' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/style/inferencer.php', 'ezcDocumentOdtStyleInformation' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/style_information.php', 'ezcDocumentOdtStyleListPropertyGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/list.php', 'ezcDocumentOdtStyleParagraphPropertyGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/paragraph.php', 'ezcDocumentOdtStyleParser' => $vendorDir . '/zetacomponents/document/src/document/xml/odt/style/parser.php', 'ezcDocumentOdtStylePropertyGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator.php', 'ezcDocumentOdtStyleTableCellPropertyGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/table_cell.php', 'ezcDocumentOdtStyleTablePropertyGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/table.php', 'ezcDocumentOdtStyleTableRowPropertyGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/table_row.php', 'ezcDocumentOdtStyleTextPropertyGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/property_generator/text.php', 'ezcDocumentOdtStyler' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler.php', 'ezcDocumentOdtTableCellStyleGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/table_cell.php', 'ezcDocumentOdtTableRowStyleGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/table_row.php', 'ezcDocumentOdtTableStyleGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/table.php', 'ezcDocumentOdtTextProcessor' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/text_processor.php', 'ezcDocumentOdtTextStyleGenerator' => $vendorDir . '/zetacomponents/document/src/converters/element_visitor/docbook/odt/styler/pcss/generator/text.php', 'ezcDocumentOptions' => $vendorDir . '/zetacomponents/document/src/options/document.php', 'ezcDocumentParser' => $vendorDir . '/zetacomponents/document/src/interfaces/parser.php', 'ezcDocumentParserException' => $vendorDir . '/zetacomponents/document/src/exceptions/parser.php', 'ezcDocumentParserOptions' => $vendorDir . '/zetacomponents/document/src/options/document_parser.php', 'ezcDocumentPcssDeclarationDirective' => $vendorDir . '/zetacomponents/document/src/pcss/declaration_directive.php', 'ezcDocumentPcssDirective' => $vendorDir . '/zetacomponents/document/src/pcss/directive.php', 'ezcDocumentPcssLayoutDirective' => $vendorDir . '/zetacomponents/document/src/pcss/layout_directive.php', 'ezcDocumentPcssMeasure' => $vendorDir . '/zetacomponents/document/src/pcss/measure.php', 'ezcDocumentPcssParser' => $vendorDir . '/zetacomponents/document/src/pcss/parser.php', 'ezcDocumentPcssStyleBorderBoxValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/border_box_value.php', 'ezcDocumentPcssStyleBorderValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/border_value.php', 'ezcDocumentPcssStyleBoxValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/box_value.php', 'ezcDocumentPcssStyleColorBoxValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/color_box_value.php', 'ezcDocumentPcssStyleColorValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/color_value.php', 'ezcDocumentPcssStyleInferencer' => $vendorDir . '/zetacomponents/document/src/pcss/style_inferencer.php', 'ezcDocumentPcssStyleIntValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/int_value.php', 'ezcDocumentPcssStyleLineBoxValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/line_box_value.php', 'ezcDocumentPcssStyleLineValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/line_value.php', 'ezcDocumentPcssStyleListValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/list_value.php', 'ezcDocumentPcssStyleMeasureBoxValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/measure_box_value.php', 'ezcDocumentPcssStyleMeasureValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/measure_value.php', 'ezcDocumentPcssStyleSrcValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/src_value.php', 'ezcDocumentPcssStyleStringValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/string_value.php', 'ezcDocumentPcssStyleValue' => $vendorDir . '/zetacomponents/document/src/pcss/style/value.php', 'ezcDocumentPdf' => $vendorDir . '/zetacomponents/document/src/document/pdf.php', 'ezcDocumentPdfBlockRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/block.php', 'ezcDocumentPdfBlockquoteRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/blockquote.php', 'ezcDocumentPdfBoundingBox' => $vendorDir . '/zetacomponents/document/src/document/pdf/box.php', 'ezcDocumentPdfDefaultHyphenator' => $vendorDir . '/zetacomponents/document/src/document/pdf/hyphenator/default.php', 'ezcDocumentPdfDefaultTableColumnWidthCalculator' => $vendorDir . '/zetacomponents/document/src/document/pdf/default_table_column_width_calculator.php', 'ezcDocumentPdfDefaultTokenizer' => $vendorDir . '/zetacomponents/document/src/document/pdf/tokenizer/default.php', 'ezcDocumentPdfDriver' => $vendorDir . '/zetacomponents/document/src/document/pdf/driver.php', 'ezcDocumentPdfFooterOptions' => $vendorDir . '/zetacomponents/document/src/options/document_pdf_footer.php', 'ezcDocumentPdfFooterPdfPart' => $vendorDir . '/zetacomponents/document/src/document/pdf/part/footer.php', 'ezcDocumentPdfHaruDriver' => $vendorDir . '/zetacomponents/document/src/document/pdf/driver/haru.php', 'ezcDocumentPdfHeaderPdfPart' => $vendorDir . '/zetacomponents/document/src/document/pdf/part/header.php', 'ezcDocumentPdfHyphenator' => $vendorDir . '/zetacomponents/document/src/document/pdf/hyphenator.php', 'ezcDocumentPdfImage' => $vendorDir . '/zetacomponents/document/src/document/pdf/image.php', 'ezcDocumentPdfImageHandler' => $vendorDir . '/zetacomponents/document/src/document/pdf/image/handler.php', 'ezcDocumentPdfListItemRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/list_item.php', 'ezcDocumentPdfListRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/list.php', 'ezcDocumentPdfLiteralBlockRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/literal_block.php', 'ezcDocumentPdfLiteralTokenizer' => $vendorDir . '/zetacomponents/document/src/document/pdf/tokenizer/literal.php', 'ezcDocumentPdfMainRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/main.php', 'ezcDocumentPdfMediaObjectRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/mediaobject.php', 'ezcDocumentPdfOptions' => $vendorDir . '/zetacomponents/document/src/options/document_pdf.php', 'ezcDocumentPdfPage' => $vendorDir . '/zetacomponents/document/src/document/pdf/page.php', 'ezcDocumentPdfPart' => $vendorDir . '/zetacomponents/document/src/document/pdf/part.php', 'ezcDocumentPdfPhpImageHandler' => $vendorDir . '/zetacomponents/document/src/document/pdf/image/php.php', 'ezcDocumentPdfRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer.php', 'ezcDocumentPdfSvgDriver' => $vendorDir . '/zetacomponents/document/src/document/pdf/driver/svg.php', 'ezcDocumentPdfTableColumnWidthCalculator' => $vendorDir . '/zetacomponents/document/src/document/pdf/table_column_width_calculator.php', 'ezcDocumentPdfTableRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/table.php', 'ezcDocumentPdfTcpdfDriver' => $vendorDir . '/zetacomponents/document/src/document/pdf/driver/tcpdf.php', 'ezcDocumentPdfTextBlockRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/text_block.php', 'ezcDocumentPdfTextBoxRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/text_box.php', 'ezcDocumentPdfTitleRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/title.php', 'ezcDocumentPdfTokenizer' => $vendorDir . '/zetacomponents/document/src/document/pdf/tokenizer.php', 'ezcDocumentPdfTransactionalDriverWrapper' => $vendorDir . '/zetacomponents/document/src/document/pdf/driver/wrapper.php', 'ezcDocumentPdfTransactionalDriverWrapperState' => $vendorDir . '/zetacomponents/document/src/document/pdf/driver/wrapper_state.php', 'ezcDocumentPdfWrappingTextBoxRenderer' => $vendorDir . '/zetacomponents/document/src/document/pdf/renderer/paragraph.php', 'ezcDocumentPropertyContainerDomElement' => $vendorDir . '/zetacomponents/document/src/dom_elements/property_container.php', 'ezcDocumentRomanListItemGenerator' => $vendorDir . '/zetacomponents/document/src/document/pdf/item_generator/roman.php', 'ezcDocumentRst' => $vendorDir . '/zetacomponents/document/src/document/rst.php', 'ezcDocumentRstAnonymousLinkNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/link_anonymous.php', 'ezcDocumentRstAnonymousReferenceNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/anon_reference.php', 'ezcDocumentRstAttentionDirective' => $vendorDir . '/zetacomponents/document/src/document/rst/directive/attention.php', 'ezcDocumentRstBlockNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/block.php', 'ezcDocumentRstBlockquoteAnnotationNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/blockquote_annotation.php', 'ezcDocumentRstBlockquoteNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/blockquote.php', 'ezcDocumentRstBulletListListNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/bullet_list_list.php', 'ezcDocumentRstBulletListNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/bullet_list.php', 'ezcDocumentRstCommentNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/comment.php', 'ezcDocumentRstContentsDirective' => $vendorDir . '/zetacomponents/document/src/document/rst/directive/contents.php', 'ezcDocumentRstDangerDirective' => $vendorDir . '/zetacomponents/document/src/document/rst/directive/danger.php', 'ezcDocumentRstDefinitionListListNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/definition_list_list.php', 'ezcDocumentRstDefinitionListNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/definition_list.php', 'ezcDocumentRstDirective' => $vendorDir . '/zetacomponents/document/src/document/rst/directive.php', 'ezcDocumentRstDirectiveNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/directive.php', 'ezcDocumentRstDocbookVisitor' => $vendorDir . '/zetacomponents/document/src/document/rst/visitor/docbook.php', 'ezcDocumentRstDocumentNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/document.php', 'ezcDocumentRstEmphasisTextRole' => $vendorDir . '/zetacomponents/document/src/document/rst/role/emphasis.php', 'ezcDocumentRstEnumeratedListListNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/enumerated_list_list.php', 'ezcDocumentRstEnumeratedListNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/enumerated_list.php', 'ezcDocumentRstExternalReferenceNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/link_reference.php', 'ezcDocumentRstFieldListNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/field_list.php', 'ezcDocumentRstFigureDirective' => $vendorDir . '/zetacomponents/document/src/document/rst/directive/figure.php', 'ezcDocumentRstFootnoteNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/footnote.php', 'ezcDocumentRstImageDirective' => $vendorDir . '/zetacomponents/document/src/document/rst/directive/image.php', 'ezcDocumentRstIncludeDirective' => $vendorDir . '/zetacomponents/document/src/document/rst/directive/include.php', 'ezcDocumentRstLineBlockLineNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/line_block_line.php', 'ezcDocumentRstLineBlockNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/line_block.php', 'ezcDocumentRstLinkNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/link.php', 'ezcDocumentRstLiteralBlockNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/literal_block.php', 'ezcDocumentRstLiteralNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/literal.php', 'ezcDocumentRstLiteralTextRole' => $vendorDir . '/zetacomponents/document/src/document/rst/role/literal.php', 'ezcDocumentRstMarkupEmphasisNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/markup_emphasis.php', 'ezcDocumentRstMarkupInlineLiteralNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/markup_inline_literal.php', 'ezcDocumentRstMarkupInterpretedTextNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/markup_interpreted_text.php', 'ezcDocumentRstMarkupNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/markup.php', 'ezcDocumentRstMarkupStrongEmphasisNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/markup_strong_emphasis.php', 'ezcDocumentRstMarkupSubstitutionNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/markup_substitution.php', 'ezcDocumentRstMissingDirectiveHandlerException' => $vendorDir . '/zetacomponents/document/src/exceptions/missing_directive_handler.php', 'ezcDocumentRstMissingTextRoleHandlerException' => $vendorDir . '/zetacomponents/document/src/exceptions/missing_text_role_handler.php', 'ezcDocumentRstNamedReferenceNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/named_reference.php', 'ezcDocumentRstNode' => $vendorDir . '/zetacomponents/document/src/document/rst/node.php', 'ezcDocumentRstNoteDirective' => $vendorDir . '/zetacomponents/document/src/document/rst/directive/note.php', 'ezcDocumentRstNoticeDirective' => $vendorDir . '/zetacomponents/document/src/document/rst/directive/notice.php', 'ezcDocumentRstOptions' => $vendorDir . '/zetacomponents/document/src/options/document_rst.php', 'ezcDocumentRstParagraphNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/paragraph.php', 'ezcDocumentRstParser' => $vendorDir . '/zetacomponents/document/src/document/rst/parser.php', 'ezcDocumentRstReferenceNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/reference.php', 'ezcDocumentRstSectionNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/section.php', 'ezcDocumentRstStack' => $vendorDir . '/zetacomponents/document/src/document/rst/document_stack.php', 'ezcDocumentRstStrongTextRole' => $vendorDir . '/zetacomponents/document/src/document/rst/role/strong.php', 'ezcDocumentRstSubscriptTextRole' => $vendorDir . '/zetacomponents/document/src/document/rst/role/subscript.php', 'ezcDocumentRstSubstitutionNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/substitution.php', 'ezcDocumentRstSuperscriptTextRole' => $vendorDir . '/zetacomponents/document/src/document/rst/role/superscript.php', 'ezcDocumentRstTableBodyNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/table_body.php', 'ezcDocumentRstTableCellNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/table_cell.php', 'ezcDocumentRstTableHeadNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/table_head.php', 'ezcDocumentRstTableNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/table.php', 'ezcDocumentRstTableRowNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/table_row.php', 'ezcDocumentRstTargetNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/target.php', 'ezcDocumentRstTextLineNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/text_line.php', 'ezcDocumentRstTextRole' => $vendorDir . '/zetacomponents/document/src/document/rst/role.php', 'ezcDocumentRstTitleNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/title.php', 'ezcDocumentRstTitleReferenceTextRole' => $vendorDir . '/zetacomponents/document/src/document/rst/role/title_reference.php', 'ezcDocumentRstToken' => $vendorDir . '/zetacomponents/document/src/document/rst/token.php', 'ezcDocumentRstTokenizer' => $vendorDir . '/zetacomponents/document/src/document/rst/tokenizer.php', 'ezcDocumentRstTokenizerException' => $vendorDir . '/zetacomponents/document/src/exceptions/rst_tokenizer.php', 'ezcDocumentRstTransitionNode' => $vendorDir . '/zetacomponents/document/src/document/rst/nodes/transition.php', 'ezcDocumentRstVisitor' => $vendorDir . '/zetacomponents/document/src/document/rst/visitor.php', 'ezcDocumentRstWarningDirective' => $vendorDir . '/zetacomponents/document/src/document/rst/directive/warning.php', 'ezcDocumentRstXhtmlBodyVisitor' => $vendorDir . '/zetacomponents/document/src/document/rst/visitor/xhtml_body.php', 'ezcDocumentRstXhtmlDirective' => $vendorDir . '/zetacomponents/document/src/interfaces/rst_xhtml_directive.php', 'ezcDocumentRstXhtmlTextRole' => $vendorDir . '/zetacomponents/document/src/interfaces/rst_xhtml_role.php', 'ezcDocumentRstXhtmlVisitor' => $vendorDir . '/zetacomponents/document/src/document/rst/visitor/xhtml.php', 'ezcDocumentValidation' => $vendorDir . '/zetacomponents/document/src/interfaces/validation.php', 'ezcDocumentValidationError' => $vendorDir . '/zetacomponents/document/src/validation_error.php', 'ezcDocumentVisitException' => $vendorDir . '/zetacomponents/document/src/exceptions/visitor.php', 'ezcDocumentWiki' => $vendorDir . '/zetacomponents/document/src/document/wiki.php', 'ezcDocumentWikiBlockLevelNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/block.php', 'ezcDocumentWikiBlockMarkupToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/block_markup.php', 'ezcDocumentWikiBlockquoteNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/blockquote.php', 'ezcDocumentWikiBoldNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/bold.php', 'ezcDocumentWikiBoldToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/bold.php', 'ezcDocumentWikiBulletListItemNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/bullet_list_item.php', 'ezcDocumentWikiBulletListItemToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/bullet_list.php', 'ezcDocumentWikiBulletListNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/bullet_list.php', 'ezcDocumentWikiCodePlugin' => $vendorDir . '/zetacomponents/document/src/document/wiki/plugin/code.php', 'ezcDocumentWikiConfluenceLinkStartToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/confluence_link_start.php', 'ezcDocumentWikiConfluenceTokenizer' => $vendorDir . '/zetacomponents/document/src/document/wiki/tokenizer/confluence.php', 'ezcDocumentWikiCreoleTokenizer' => $vendorDir . '/zetacomponents/document/src/document/wiki/tokenizer/creole.php', 'ezcDocumentWikiDefinitionListItemToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/definition_list.php', 'ezcDocumentWikiDeletedNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/deleted.php', 'ezcDocumentWikiDeletedToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/deleted.php', 'ezcDocumentWikiDocbookVisitor' => $vendorDir . '/zetacomponents/document/src/document/wiki/visitor/docbook.php', 'ezcDocumentWikiDocumentNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/document.php', 'ezcDocumentWikiDokuwikiTokenizer' => $vendorDir . '/zetacomponents/document/src/document/wiki/tokenizer/dokuwiki.php', 'ezcDocumentWikiEndOfFileToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/end_of_file.php', 'ezcDocumentWikiEnumeratedListItemNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/enumerated_list_item.php', 'ezcDocumentWikiEnumeratedListItemToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/enumerated_list.php', 'ezcDocumentWikiEnumeratedListNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/enumerated_list.php', 'ezcDocumentWikiEscapeCharacterToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/escape_character.php', 'ezcDocumentWikiExternalLinkNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/external_link.php', 'ezcDocumentWikiExternalLinkToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/external_link.php', 'ezcDocumentWikiFootnoteEndNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/footnote_end.php', 'ezcDocumentWikiFootnoteEndToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/footnote_end.php', 'ezcDocumentWikiFootnoteNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/footnote.php', 'ezcDocumentWikiFootnoteStartToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/footnote_start.php', 'ezcDocumentWikiImageEndNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/image_end.php', 'ezcDocumentWikiImageEndToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/image_end.php', 'ezcDocumentWikiImageNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/image.php', 'ezcDocumentWikiImageStartToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/image_start.php', 'ezcDocumentWikiInlineLiteralNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/inline_literal.php', 'ezcDocumentWikiInlineLiteralToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/inline_literal.php', 'ezcDocumentWikiInlineMarkupToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/inline_markup.php', 'ezcDocumentWikiInlineNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/inline.php', 'ezcDocumentWikiInlineQuoteNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/inline_quote.php', 'ezcDocumentWikiInlineQuoteToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/inline_quote.php', 'ezcDocumentWikiInterWikiLinkNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/inter_wiki_link.php', 'ezcDocumentWikiInterWikiLinkToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/inter_wiki_link.php', 'ezcDocumentWikiInternalLinkNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/internal_link.php', 'ezcDocumentWikiInternalLinkToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/internal_link.php', 'ezcDocumentWikiInvisibleBreakNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/invisible_break.php', 'ezcDocumentWikiItalicNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/italic.php', 'ezcDocumentWikiItalicToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/italic.php', 'ezcDocumentWikiLineBreakNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/line_break.php', 'ezcDocumentWikiLineBreakToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/line_break.php', 'ezcDocumentWikiLineLevelNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/line.php', 'ezcDocumentWikiLineMarkupToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/line_markup.php', 'ezcDocumentWikiLinkEndNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/link_end.php', 'ezcDocumentWikiLinkEndToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/link_end.php', 'ezcDocumentWikiLinkNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/link.php', 'ezcDocumentWikiLinkStartToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/link_start.php', 'ezcDocumentWikiListNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/list.php', 'ezcDocumentWikiLiteralBlockNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/literal_block.php', 'ezcDocumentWikiLiteralBlockToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/literal_block.php', 'ezcDocumentWikiLiteralLineToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/literal_line.php', 'ezcDocumentWikiMatchingInlineNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/matching_inline.php', 'ezcDocumentWikiMediawikiEmphasisToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/mediawiki_emphasis.php', 'ezcDocumentWikiMediawikiTokenizer' => $vendorDir . '/zetacomponents/document/src/document/wiki/tokenizer/mediawiki.php', 'ezcDocumentWikiMissingPluginHandlerException' => $vendorDir . '/zetacomponents/document/src/exceptions/missing_plugin_handler.php', 'ezcDocumentWikiMonospaceNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/monospace.php', 'ezcDocumentWikiMonospaceToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/monospace.php', 'ezcDocumentWikiNewLineToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/new_line.php', 'ezcDocumentWikiNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/node.php', 'ezcDocumentWikiOptions' => $vendorDir . '/zetacomponents/document/src/options/document_wiki.php', 'ezcDocumentWikiPageBreakNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/page_break.php', 'ezcDocumentWikiPageBreakToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/page_break.php', 'ezcDocumentWikiParagraphIndentationToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/indentation.php', 'ezcDocumentWikiParagraphNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/paragraph.php', 'ezcDocumentWikiParser' => $vendorDir . '/zetacomponents/document/src/document/wiki/parser.php', 'ezcDocumentWikiPlugin' => $vendorDir . '/zetacomponents/document/src/document/wiki/plugin.php', 'ezcDocumentWikiPluginNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/plugin.php', 'ezcDocumentWikiPluginToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/plugin.php', 'ezcDocumentWikiQuoteToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/quote.php', 'ezcDocumentWikiSectionNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/section.php', 'ezcDocumentWikiSeparatorNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/separator.php', 'ezcDocumentWikiSeparatorToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/separator.php', 'ezcDocumentWikiSpecialCharsToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/special_chars.php', 'ezcDocumentWikiStrikeToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/strike.php', 'ezcDocumentWikiSubscriptNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/subscript.php', 'ezcDocumentWikiSubscriptToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/subscript.php', 'ezcDocumentWikiSuperscriptNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/superscript.php', 'ezcDocumentWikiSuperscriptToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/superscript.php', 'ezcDocumentWikiTableCellNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/table_cell.php', 'ezcDocumentWikiTableHeaderSeparatorNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/table_header_separator.php', 'ezcDocumentWikiTableHeaderToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/table_header.php', 'ezcDocumentWikiTableNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/table.php', 'ezcDocumentWikiTableRowNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/table_row.php', 'ezcDocumentWikiTableRowToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/table_row.php', 'ezcDocumentWikiTextLineToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/text_line.php', 'ezcDocumentWikiTextNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/text.php', 'ezcDocumentWikiTitleNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/title.php', 'ezcDocumentWikiTitleToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/title.php', 'ezcDocumentWikiToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token.php', 'ezcDocumentWikiTokenizer' => $vendorDir . '/zetacomponents/document/src/document/wiki/tokenizer.php', 'ezcDocumentWikiTokenizerException' => $vendorDir . '/zetacomponents/document/src/exceptions/wiki_tokenizer.php', 'ezcDocumentWikiUnderlineNode' => $vendorDir . '/zetacomponents/document/src/document/wiki/nodes/underline.php', 'ezcDocumentWikiUnderlineToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/underline.php', 'ezcDocumentWikiVisitor' => $vendorDir . '/zetacomponents/document/src/document/wiki/visitor.php', 'ezcDocumentWikiWhitespaceToken' => $vendorDir . '/zetacomponents/document/src/document/wiki/token/whitespace.php', 'ezcDocumentXhtml' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml.php', 'ezcDocumentXhtmlBaseFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/base.php', 'ezcDocumentXhtmlBlockquoteElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/blockquote.php', 'ezcDocumentXhtmlContentLocatorFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/content_locator.php', 'ezcDocumentXhtmlConversion' => $vendorDir . '/zetacomponents/document/src/interfaces/conversions/xhtml.php', 'ezcDocumentXhtmlDefinitionListElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/definitionlist.php', 'ezcDocumentXhtmlElementBaseFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/base.php', 'ezcDocumentXhtmlElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element.php', 'ezcDocumentXhtmlElementMappingFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/mapping.php', 'ezcDocumentXhtmlEnumeratedElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/enumerated.php', 'ezcDocumentXhtmlFootnoteElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/footnote.php', 'ezcDocumentXhtmlHeaderElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/header.php', 'ezcDocumentXhtmlImageElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/image.php', 'ezcDocumentXhtmlLineBlockElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/lineblock.php', 'ezcDocumentXhtmlLinkElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/link.php', 'ezcDocumentXhtmlLiteralElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/literal.php', 'ezcDocumentXhtmlMetadataFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/metadata.php', 'ezcDocumentXhtmlOptions' => $vendorDir . '/zetacomponents/document/src/options/document_xhtml.php', 'ezcDocumentXhtmlParagraphElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/paragraph.php', 'ezcDocumentXhtmlSpecialParagraphElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/special_paragraph.php', 'ezcDocumentXhtmlStrongElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/strong.php', 'ezcDocumentXhtmlTableCellElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/tablecell.php', 'ezcDocumentXhtmlTableElementFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/table.php', 'ezcDocumentXhtmlTablesFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/tables.php', 'ezcDocumentXhtmlTextToParagraphFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/element/text.php', 'ezcDocumentXhtmlXpathFilter' => $vendorDir . '/zetacomponents/document/src/document/xml/xhtml/filter/xpath.php', 'ezcDocumentXmlBase' => $vendorDir . '/zetacomponents/document/src/document/xml_base.php', 'ezcDocumentXmlOptions' => $vendorDir . '/zetacomponents/document/src/options/document_xml.php', 'ezcDocumentXsltConverter' => $vendorDir . '/zetacomponents/document/src/converters/xslt.php', 'ezcDocumentXsltConverterOptions' => $vendorDir . '/zetacomponents/document/src/options/converter_xslt.php', 'org\\bovigo\\vfs\\DotDirectory' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/DotDirectory.php', 'org\\bovigo\\vfs\\Quota' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/Quota.php', 'org\\bovigo\\vfs\\content\\FileContent' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/content/FileContent.php', 'org\\bovigo\\vfs\\content\\LargeFileContent' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/content/LargeFileContent.php', 'org\\bovigo\\vfs\\content\\SeekableFileContent' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/content/SeekableFileContent.php', 'org\\bovigo\\vfs\\content\\StringBasedFileContent' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/content/StringBasedFileContent.php', 'org\\bovigo\\vfs\\vfsStream' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStream.php', 'org\\bovigo\\vfs\\vfsStreamAbstractContent' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamAbstractContent.php', 'org\\bovigo\\vfs\\vfsStreamBlock' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamBlock.php', 'org\\bovigo\\vfs\\vfsStreamContainer' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamContainer.php', 'org\\bovigo\\vfs\\vfsStreamContainerIterator' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamContainerIterator.php', 'org\\bovigo\\vfs\\vfsStreamContent' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamContent.php', 'org\\bovigo\\vfs\\vfsStreamDirectory' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamDirectory.php', 'org\\bovigo\\vfs\\vfsStreamException' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamException.php', 'org\\bovigo\\vfs\\vfsStreamFile' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamFile.php', 'org\\bovigo\\vfs\\vfsStreamWrapper' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamWrapper.php', 'org\\bovigo\\vfs\\visitor\\vfsStreamAbstractVisitor' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitor.php', 'org\\bovigo\\vfs\\visitor\\vfsStreamPrintVisitor' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitor.php', 'org\\bovigo\\vfs\\visitor\\vfsStreamStructureVisitor' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitor.php', 'org\\bovigo\\vfs\\visitor\\vfsStreamVisitor' => $vendorDir . '/mikey179/vfsStream/src/main/php/org/bovigo/vfs/visitor/vfsStreamVisitor.php', 'phpDocumentor\\Application' => $baseDir . '/src/phpDocumentor/Application.php', 'phpDocumentor\\ApplicationTest' => $baseDir . '/tests/unit/phpDocumentor/ApplicationTest.php', 'phpDocumentor\\Bootstrap' => $baseDir . '/src/phpDocumentor/Bootstrap.php', 'phpDocumentor\\BootstrapTest' => $baseDir . '/tests/unit/phpDocumentor/BootstrapTest.php', 'phpDocumentor\\Command\\Command' => $baseDir . '/src/phpDocumentor/Command/Command.php', 'phpDocumentor\\Command\\CommandTest' => $baseDir . '/tests/unit/phpDocumentor/Command/CommandTest.php', 'phpDocumentor\\Command\\Helper\\ConfigurationHelper' => $baseDir . '/src/phpDocumentor/Command/Helper/ConfigurationHelper.php', 'phpDocumentor\\Command\\Helper\\ConfigurationHelperTest' => $baseDir . '/tests/unit/phpDocumentor/Command/Helper/ConfigurationHelperTest.php', 'phpDocumentor\\Command\\Helper\\LoggerHelper' => $baseDir . '/src/phpDocumentor/Command/Helper/LoggerHelper.php', 'phpDocumentor\\Command\\Helper\\LoggerHelperTest' => $baseDir . '/tests/unit/phpDocumentor/Command/Helper/LoggerHelperTest.php', 'phpDocumentor\\Command\\Phar\\UpdateCommand' => $baseDir . '/src/phpDocumentor/Command/Phar/UpdateCommand.php', 'phpDocumentor\\Command\\Project\\RunCommand' => $baseDir . '/src/phpDocumentor/Command/Project/RunCommand.php', 'phpDocumentor\\Compiler\\Compiler' => $baseDir . '/src/phpDocumentor/Compiler/Compiler.php', 'phpDocumentor\\Compiler\\CompilerPassInterface' => $baseDir . '/src/phpDocumentor/Compiler/CompilerPassInterface.php', 'phpDocumentor\\Compiler\\CompilerTest' => $baseDir . '/tests/unit/phpDocumentor/Compiler/CompilerTest.php', 'phpDocumentor\\Compiler\\Linker\\Linker' => $baseDir . '/src/phpDocumentor/Compiler/Linker/Linker.php', 'phpDocumentor\\Compiler\\Linker\\LinkerTest' => $baseDir . '/tests/unit/phpDocumentor/Compiler/Linker/LinkerTest.php', 'phpDocumentor\\Compiler\\Pass\\Debug' => $baseDir . '/src/phpDocumentor/Compiler/Pass/Debug.php', 'phpDocumentor\\Compiler\\Pass\\DebugTest' => $baseDir . '/tests/unit/phpDocumentor/Compiler/Pass/DebugTest.php', 'phpDocumentor\\Compiler\\Pass\\ElementsIndexBuilder' => $baseDir . '/src/phpDocumentor/Compiler/Pass/ElementsIndexBuilder.php', 'phpDocumentor\\Compiler\\Pass\\ElementsIndexBuilderTest' => $baseDir . '/tests/unit/phpDocumentor/Compiler/Pass/ElementsIndexBuilderTest.php', 'phpDocumentor\\Compiler\\Pass\\ExampleTagsEnricher' => $baseDir . '/src/phpDocumentor/Compiler/Pass/ExampleTagsEnricher.php', 'phpDocumentor\\Compiler\\Pass\\ExampleTagsEnricherTest' => $baseDir . '/tests/unit/phpDocumentor/Compiler/Pass/ExampleTagsEnricherTest.php', 'phpDocumentor\\Compiler\\Pass\\MarkerFromTagsExtractor' => $baseDir . '/src/phpDocumentor/Compiler/Pass/MarkerFromTagsExtractor.php', 'phpDocumentor\\Compiler\\Pass\\MarkerFromTagsExtractorTest' => $baseDir . '/tests/unit/phpDocumentor/Compiler/Pass/MarkerFromTagsExtractorTest.php', 'phpDocumentor\\Compiler\\Pass\\NamespaceTreeBuilder' => $baseDir . '/src/phpDocumentor/Compiler/Pass/NamespaceTreeBuilder.php', 'phpDocumentor\\Compiler\\Pass\\NamespaceTreeBuilderTest' => $baseDir . '/tests/unit/phpDocumentor/Compiler/Pass/NamespaceTreeBuilderTest.php', 'phpDocumentor\\Compiler\\Pass\\PackageTreeBuilder' => $baseDir . '/src/phpDocumentor/Compiler/Pass/PackageTreeBuilder.php', 'phpDocumentor\\Compiler\\Pass\\ResolveInlineLinkAndSeeTags' => $baseDir . '/src/phpDocumentor/Compiler/Pass/ResolveInlineLinkAndSeeTags.php', 'phpDocumentor\\Compiler\\Pass\\ResolveInlineLinkAndSeeTagsTest' => $baseDir . '/tests/unit/phpDocumentor/Compiler/Pass/ResolveInlineLinkAndSeeTagsTest.php', 'phpDocumentor\\Configuration' => $baseDir . '/src/phpDocumentor/Configuration.php', 'phpDocumentor\\ConfigurationTest' => $baseDir . '/tests/unit/phpDocumentor/ConfigurationTest.php', 'phpDocumentor\\Configuration\\Loader' => $baseDir . '/src/phpDocumentor/Configuration/Loader.php', 'phpDocumentor\\Configuration\\Logging' => $baseDir . '/src/phpDocumentor/Configuration/Logging.php', 'phpDocumentor\\Configuration\\LoggingTest' => $baseDir . '/tests/unit/phpDocumentor/Configuration/LoggingTest.php', 'phpDocumentor\\Configuration\\Merger' => $baseDir . '/src/phpDocumentor/Configuration/Merger.php', 'phpDocumentor\\Configuration\\Merger\\Annotation\\Replace' => $baseDir . '/src/phpDocumentor/Configuration/Merger/Annotation/Replace.php', 'phpDocumentor\\Configuration\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Configuration/ServiceProvider.php', 'phpDocumentor\\Console\\Input\\ArgvInput' => $baseDir . '/src/phpDocumentor/Console/Input/ArgvInput.php', 'phpDocumentor\\Console\\Input\\ArgvInputTest' => $baseDir . '/tests/unit/phpDocumentor/Console/Input/ArgvInputTest.php', 'phpDocumentor\\Console\\Output\\Output' => $baseDir . '/src/phpDocumentor/Console/Output/Output.php', 'phpDocumentor\\Console\\Output\\OutputTest' => $baseDir . '/tests/unit/phpDocumentor/Console/Output/OutputTest.php', 'phpDocumentor\\Descriptor\\ArgumentDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/ArgumentDescriptor.php', 'phpDocumentor\\Descriptor\\ArgumentDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/ArgumentDescriptorTest.php', 'phpDocumentor\\Descriptor\\Builder\\AssemblerAbstract' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/AssemblerAbstract.php', 'phpDocumentor\\Descriptor\\Builder\\AssemblerFactory' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/AssemblerFactory.php', 'phpDocumentor\\Descriptor\\Builder\\AssemblerInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/AssemblerInterface.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\ArgumentAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/ArgumentAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\ArgumentAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/ArgumentAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\AssemblerAbstract' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/AssemblerAbstract.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\ClassAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/ClassAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\ClassAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/ClassAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\ConstantAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/ConstantAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\ConstantAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/ConstantAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\FileAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/FileAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\FileAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/FileAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\FunctionAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/FunctionAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\FunctionAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/FunctionAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\InterfaceAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/InterfaceAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\MethodAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/MethodAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\MethodAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/MethodAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\PropertyAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/PropertyAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\AuthorAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/AuthorAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\DeprecatedAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/DeprecatedAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\ExampleAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/ExampleAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\ExampleAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/Tags/ExampleAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\GenericTagAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/GenericTagAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\LinkAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/LinkAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\MethodAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/MethodAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\MethodAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/Tags/MethodAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\ParamAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/ParamAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\ParamAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/Tags/ParamAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\PropertyAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/PropertyAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\PropertyAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/Tags/PropertyAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\ReturnAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/ReturnAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\ReturnAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/Tags/ReturnAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\SeeAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/SeeAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\SinceAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\ThrowsAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/ThrowsAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\ThrowsAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/Tags/ThrowsAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\TypeCollectionAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/TypeCollectionAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\UsesAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/UsesAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\VarAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/VarAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\VarAssemblerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Builder/Reflector/Tags/VarAssemblerTest.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\Tags\\VersionAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/Tags/VersionAssembler.php', 'phpDocumentor\\Descriptor\\Builder\\Reflector\\TraitAssembler' => $baseDir . '/src/phpDocumentor/Descriptor/Builder/Reflector/TraitAssembler.php', 'phpDocumentor\\Descriptor\\Cache\\ProjectDescriptorMapper' => $baseDir . '/src/phpDocumentor/Descriptor/Cache/ProjectDescriptorMapper.php', 'phpDocumentor\\Descriptor\\ClassDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/ClassDescriptor.php', 'phpDocumentor\\Descriptor\\ClassDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/ClassDescriptorTest.php', 'phpDocumentor\\Descriptor\\Collection' => $baseDir . '/src/phpDocumentor/Descriptor/Collection.php', 'phpDocumentor\\Descriptor\\CollectionTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/CollectionTest.php', 'phpDocumentor\\Descriptor\\ConstantDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/ConstantDescriptor.php', 'phpDocumentor\\Descriptor\\ConstantDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/ConstantDescriptorTest.php', 'phpDocumentor\\Descriptor\\DescriptorAbstract' => $baseDir . '/src/phpDocumentor/Descriptor/DescriptorAbstract.php', 'phpDocumentor\\Descriptor\\DescriptorAbstractTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/DescriptorAbstractTest.php', 'phpDocumentor\\Descriptor\\Example\\Finder' => $baseDir . '/src/phpDocumentor/Descriptor/Example/Finder.php', 'phpDocumentor\\Descriptor\\Example\\FinderTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Example/FinderTest.php', 'phpDocumentor\\Descriptor\\Exception\\MissingDependencyException' => $baseDir . '/src/phpDocumentor/Descriptor/Exception/MissingDependencyException.php', 'phpDocumentor\\Descriptor\\FileDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/FileDescriptor.php', 'phpDocumentor\\Descriptor\\FileDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/FileDescriptorTest.php', 'phpDocumentor\\Descriptor\\Filter\\ClassFactory' => $baseDir . '/src/phpDocumentor/Descriptor/Filter/ClassFactory.php', 'phpDocumentor\\Descriptor\\Filter\\ClassFactoryTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Filter/ClassFactoryTest.php', 'phpDocumentor\\Descriptor\\Filter\\Filter' => $baseDir . '/src/phpDocumentor/Descriptor/Filter/Filter.php', 'phpDocumentor\\Descriptor\\Filter\\FilterTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Filter/FilterTest.php', 'phpDocumentor\\Descriptor\\Filter\\Filterable' => $baseDir . '/src/phpDocumentor/Descriptor/Filter/Filterable.php', 'phpDocumentor\\Descriptor\\Filter\\StripIgnore' => $baseDir . '/src/phpDocumentor/Descriptor/Filter/StripIgnore.php', 'phpDocumentor\\Descriptor\\Filter\\StripIgnoreTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Filter/StripIgnoreTest.php', 'phpDocumentor\\Descriptor\\Filter\\StripInternal' => $baseDir . '/src/phpDocumentor/Descriptor/Filter/StripInternal.php', 'phpDocumentor\\Descriptor\\Filter\\StripInternalTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Filter/StripInternalTest.php', 'phpDocumentor\\Descriptor\\Filter\\StripOnVisibility' => $baseDir . '/src/phpDocumentor/Descriptor/Filter/StripOnVisibility.php', 'phpDocumentor\\Descriptor\\Filter\\StripOnVisibilityTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Filter/StripOnVisibilityTest.php', 'phpDocumentor\\Descriptor\\FunctionDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/FunctionDescriptor.php', 'phpDocumentor\\Descriptor\\FunctionDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/FunctionDescriptorTest.php', 'phpDocumentor\\Descriptor\\InterfaceDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/InterfaceDescriptor.php', 'phpDocumentor\\Descriptor\\InterfaceDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/InterfaceDescriptorTest.php', 'phpDocumentor\\Descriptor\\Interfaces\\ArgumentInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/ArgumentInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\ChildInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/ChildInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\ClassInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/ClassInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\ConstantInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/ConstantInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\ContainerInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/ContainerInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\ElementInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/ElementInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\FileInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/FileInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\FunctionInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/FunctionInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\InterfaceInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/InterfaceInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\MethodInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/MethodInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\NamespaceInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/NamespaceInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\PackageInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/PackageInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\ProjectInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/ProjectInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\PropertyInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/PropertyInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\TraitInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/TraitInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\TypeInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/TypeInterface.php', 'phpDocumentor\\Descriptor\\Interfaces\\VisibilityInterface' => $baseDir . '/src/phpDocumentor/Descriptor/Interfaces/VisibilityInterface.php', 'phpDocumentor\\Descriptor\\MethodDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/MethodDescriptor.php', 'phpDocumentor\\Descriptor\\MethodDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/MethodDescriptorTest.php', 'phpDocumentor\\Descriptor\\NamespaceDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/NamespaceDescriptor.php', 'phpDocumentor\\Descriptor\\NamespaceDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/NamespaceDescriptorTest.php', 'phpDocumentor\\Descriptor\\PackageDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/PackageDescriptor.php', 'phpDocumentor\\Descriptor\\ProjectAnalyzer' => $baseDir . '/src/phpDocumentor/Descriptor/ProjectAnalyzer.php', 'phpDocumentor\\Descriptor\\ProjectAnalyzerTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/ProjectAnalyzerTest.php', 'phpDocumentor\\Descriptor\\ProjectDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/ProjectDescriptor.php', 'phpDocumentor\\Descriptor\\ProjectDescriptorBuilder' => $baseDir . '/src/phpDocumentor/Descriptor/ProjectDescriptorBuilder.php', 'phpDocumentor\\Descriptor\\ProjectDescriptorBuilderTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/ProjectDescriptorBuilderTest.php', 'phpDocumentor\\Descriptor\\ProjectDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/ProjectDescriptorTest.php', 'phpDocumentor\\Descriptor\\ProjectDescriptor\\Settings' => $baseDir . '/src/phpDocumentor/Descriptor/ProjectDescriptor/Settings.php', 'phpDocumentor\\Descriptor\\PropertyDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/PropertyDescriptor.php', 'phpDocumentor\\Descriptor\\PropertyDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/PropertyDescriptorTest.php', 'phpDocumentor\\Descriptor\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Descriptor/ServiceProvider.php', 'phpDocumentor\\Descriptor\\TagDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/TagDescriptor.php', 'phpDocumentor\\Descriptor\\TagDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/TagDescriptorTest.php', 'phpDocumentor\\Descriptor\\Tag\\AuthorDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/AuthorDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\BaseTypes\\TypedAbstract' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/BaseTypes/TypedAbstract.php', 'phpDocumentor\\Descriptor\\Tag\\BaseTypes\\TypedVariableAbstract' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/BaseTypes/TypedVariableAbstract.php', 'phpDocumentor\\Descriptor\\Tag\\DeprecatedDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/DeprecatedDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\DeprecatedDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Tag/DeprecatedDescriptorTest.php', 'phpDocumentor\\Descriptor\\Tag\\ExampleDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/ExampleDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\LinkDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/LinkDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\LinkDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Tag/LinkDescriptorTest.php', 'phpDocumentor\\Descriptor\\Tag\\MethodDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/MethodDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\MethodDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Tag/MethodDescriptorTest.php', 'phpDocumentor\\Descriptor\\Tag\\ParamDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/ParamDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\PropertyDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/PropertyDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\PropertyDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Tag/PropertyDescriptorTest.php', 'phpDocumentor\\Descriptor\\Tag\\ReturnDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/ReturnDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\ReturnDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Tag/ReturnDescriptorTest.php', 'phpDocumentor\\Descriptor\\Tag\\SeeDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/SeeDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\SeeDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Tag/SeeDescriptorTest.php', 'phpDocumentor\\Descriptor\\Tag\\SinceDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/SinceDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\SinceDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Tag/SinceDescriptorTest.php', 'phpDocumentor\\Descriptor\\Tag\\ThrowsDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/ThrowsDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\UsesDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/UsesDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\UsesDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Tag/UsesDescriptorTest.php', 'phpDocumentor\\Descriptor\\Tag\\VarDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/VarDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\VersionDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Tag/VersionDescriptor.php', 'phpDocumentor\\Descriptor\\Tag\\VersionDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Tag/VersionDescriptorTest.php', 'phpDocumentor\\Descriptor\\TraitDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/TraitDescriptor.php', 'phpDocumentor\\Descriptor\\TraitDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/TraitDescriptorTest.php', 'phpDocumentor\\Descriptor\\Type\\BooleanDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Type/BooleanDescriptor.php', 'phpDocumentor\\Descriptor\\Type\\BooleanDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Type/BooleanDescriptorTest.php', 'phpDocumentor\\Descriptor\\Type\\CollectionDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Type/CollectionDescriptor.php', 'phpDocumentor\\Descriptor\\Type\\CollectionDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Type/CollectionDescriptorTest.php', 'phpDocumentor\\Descriptor\\Type\\FloatDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Type/FloatDescriptor.php', 'phpDocumentor\\Descriptor\\Type\\FloatDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Type/FloatDescriptorTest.php', 'phpDocumentor\\Descriptor\\Type\\IntegerDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Type/IntegerDescriptor.php', 'phpDocumentor\\Descriptor\\Type\\IntegerDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Type/IntegerDescriptorTest.php', 'phpDocumentor\\Descriptor\\Type\\StringDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Type/StringDescriptor.php', 'phpDocumentor\\Descriptor\\Type\\StringDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Type/StringDescriptorTest.php', 'phpDocumentor\\Descriptor\\Type\\UnknownTypeDescriptor' => $baseDir . '/src/phpDocumentor/Descriptor/Type/UnknownTypeDescriptor.php', 'phpDocumentor\\Descriptor\\Type\\UnknownTypeDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Type/UnknownTypeDescriptorTest.php', 'phpDocumentor\\Descriptor\\Validator\\Error' => $baseDir . '/src/phpDocumentor/Descriptor/Validator/Error.php', 'phpDocumentor\\Descriptor\\Validator\\ErrorTest' => $baseDir . '/tests/unit/phpDocumentor/Descriptor/Validator/ErrorTest.php', 'phpDocumentor\\Event\\DebugEvent' => $baseDir . '/src/phpDocumentor/Event/DebugEvent.php', 'phpDocumentor\\Event\\DebugEventTest' => $baseDir . '/tests/unit/phpDocumentor/Event/DebugEventTest.php', 'phpDocumentor\\Event\\Dispatcher' => $baseDir . '/src/phpDocumentor/Event/Dispatcher.php', 'phpDocumentor\\Event\\DispatcherTest' => $baseDir . '/tests/unit/phpDocumentor/Event/DispatcherTest.php', 'phpDocumentor\\Event\\EventAbstract' => $baseDir . '/src/phpDocumentor/Event/EventAbstract.php', 'phpDocumentor\\Event\\EventAbstractTest' => $baseDir . '/tests/unit/phpDocumentor/Event/EventAbstractTest.php', 'phpDocumentor\\Event\\LogEvent' => $baseDir . '/src/phpDocumentor/Event/LogEvent.php', 'phpDocumentor\\Event\\LogEventTest' => $baseDir . '/tests/unit/phpDocumentor/Event/LogEventTest.php', 'phpDocumentor\\Event\\Mock\\EventAbstract' => $baseDir . '/tests/unit/phpDocumentor/Event/Mock/EventAbstract.php', 'phpDocumentor\\Fileset\\Collection' => $vendorDir . '/phpdocumentor/fileset/src/phpDocumentor/Fileset/Collection.php', 'phpDocumentor\\Fileset\\CollectionTest' => $vendorDir . '/phpdocumentor/fileset/tests/unit/phpDocumentor/Fileset/CollectionTest.php', 'phpDocumentor\\Fileset\\Collection\\IgnorePatterns' => $vendorDir . '/phpdocumentor/fileset/src/phpDocumentor/Fileset/Collection/IgnorePatterns.php', 'phpDocumentor\\Fileset\\Collection\\IgnorePatternsTest' => $vendorDir . '/phpdocumentor/fileset/tests/unit/phpDocumentor/Fileset/Collection/IgnorePatternsTest.php', 'phpDocumentor\\Fileset\\File' => $vendorDir . '/phpdocumentor/fileset/src/phpDocumentor/Fileset/File.php', 'phpDocumentor\\Fileset\\FileTest' => $vendorDir . '/phpdocumentor/fileset/tests/unit/phpDocumentor/Fileset/FileTest.php', 'phpDocumentor\\GraphViz\\Attribute' => $vendorDir . '/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Attribute.php', 'phpDocumentor\\GraphViz\\Edge' => $vendorDir . '/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Edge.php', 'phpDocumentor\\GraphViz\\Exception' => $vendorDir . '/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Exception.php', 'phpDocumentor\\GraphViz\\Graph' => $vendorDir . '/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Graph.php', 'phpDocumentor\\GraphViz\\Node' => $vendorDir . '/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Node.php', 'phpDocumentor\\Parser\\Command\\Project\\ParseCommand' => $baseDir . '/src/phpDocumentor/Parser/Command/Project/ParseCommand.php', 'phpDocumentor\\Parser\\Configuration' => $baseDir . '/src/phpDocumentor/Parser/Configuration.php', 'phpDocumentor\\Parser\\ConfigurationTest' => $baseDir . '/tests/unit/phpDocumentor/Parser/ConfigurationTest.php', 'phpDocumentor\\Parser\\Configuration\\Files' => $baseDir . '/src/phpDocumentor/Parser/Configuration/Files.php', 'phpDocumentor\\Parser\\Configuration\\FilesTest' => $baseDir . '/tests/unit/phpDocumentor/Parser/Configuration/FilesTest.php', 'phpDocumentor\\Parser\\Event\\PreFileEvent' => $baseDir . '/src/phpDocumentor/Parser/Event/PreFileEvent.php', 'phpDocumentor\\Parser\\Event\\PreFileEventTest' => $baseDir . '/tests/unit/phpDocumentor/Parser/Event/PreFileEventTest.php', 'phpDocumentor\\Parser\\Exception' => $baseDir . '/src/phpDocumentor/Parser/Exception.php', 'phpDocumentor\\Parser\\Exception\\FilesNotFoundException' => $baseDir . '/src/phpDocumentor/Parser/Exception/FilesNotFoundException.php', 'phpDocumentor\\Parser\\Exception\\MissingDependencyException' => $baseDir . '/src/phpDocumentor/Parser/Exception/MissingDependencyException.php', 'phpDocumentor\\Parser\\File' => $baseDir . '/src/phpDocumentor/Parser/File.php', 'phpDocumentor\\Parser\\FileTest' => $baseDir . '/tests/unit/phpDocumentor/Parser/FileTest.php', 'phpDocumentor\\Parser\\Parser' => $baseDir . '/src/phpDocumentor/Parser/Parser.php', 'phpDocumentor\\Parser\\ParserTest' => $baseDir . '/tests/unit/phpDocumentor/Parser/ParserTest.php', 'phpDocumentor\\Parser\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Parser/ServiceProvider.php', 'phpDocumentor\\Parser\\Util\\ParserPopulator' => $baseDir . '/src/phpDocumentor/Parser/Util/ParserPopulator.php', 'phpDocumentor\\Parser\\Util\\ParserPopulatorTest' => $baseDir . '/tests/unit/phpDocumentor/Parser/Util/ParserPopulatorTest.php', 'phpDocumentor\\Partials\\Collection' => $baseDir . '/src/phpDocumentor/Partials/Collection.php', 'phpDocumentor\\Partials\\CollectionTest' => $baseDir . '/tests/unit/phpDocumentor/Partials/CollectionTest.php', 'phpDocumentor\\Partials\\Exception\\MissingNameForPartialException' => $baseDir . '/src/phpDocumentor/Partials/Exception/MissingNameForPartialException.php', 'phpDocumentor\\Partials\\Partial' => $baseDir . '/src/phpDocumentor/Partials/Partial.php', 'phpDocumentor\\Partials\\PartialTest' => $baseDir . '/tests/unit/phpDocumentor/Partials/PartialTest.php', 'phpDocumentor\\Partials\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Partials/ServiceProvider.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasPackageWithSubpackage' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasPackageWithSubpackage.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasPackageWithSubpackageTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasPackageWithSubpackageTest.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasPackageWithSubpackageValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasPackageWithSubpackageValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasPackageWithSubpackageValidatorTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasPackageWithSubpackageValidatorTest.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasSinglePackage' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSinglePackage.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasSinglePackageTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSinglePackageTest.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasSinglePackageValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSinglePackageValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasSinglePackageValidatorTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSinglePackageValidatorTest.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasSingleSubpackage' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSingleSubpackage.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasSingleSubpackageTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSingleSubpackageTest.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasSingleSubpackageValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSingleSubpackageValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Classes\\HasSingleSubpackageValidatorTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSingleSubpackageValidatorTest.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\AreAllArgumentsValid' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/AreAllArgumentsValid.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\AreAllArgumentsValidValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/AreAllArgumentsValidValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\DoesArgumentNameMatchParam' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesArgumentNameMatchParam.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\DoesArgumentNameMatchParamValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesArgumentNameMatchParamValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\DoesArgumentTypehintMatchParam' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesArgumentTypehintMatchParam.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\DoesArgumentTypehintMatchParamValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesArgumentTypehintMatchParamValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\DoesParamsExists' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesParamsExists.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\DoesParamsExistsValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/DoesParamsExistsValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\IsArgumentInDocBlock' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsArgumentInDocBlock.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\IsArgumentInDocBlockValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsArgumentInDocBlockValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\IsParamTypeNotAnIdeDefault' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsParamTypeNotAnIdeDefault.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\IsParamTypeNotAnIdeDefaultValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsParamTypeNotAnIdeDefaultValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\IsReturnTypeNotAnIdeDefault' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsReturnTypeNotAnIdeDefault.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Functions\\IsReturnTypeNotAnIdeDefaultValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsReturnTypeNotAnIdeDefaultValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Property\\HasSummary' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Property/HasSummary.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Constraints\\Property\\HasSummaryValidator' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Property/HasSummaryValidator.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\Functions\\AreAllArgumentsValid' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/Functions/AreAllArgumentsValid.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\ValidationValueObject' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/ValidationValueObject.php', 'phpDocumentor\\Plugin\\Core\\Descriptor\\Validator\\ValidatorAbstract' => $baseDir . '/src/phpDocumentor/Plugin/Core/Descriptor/Validator/ValidatorAbstract.php', 'phpDocumentor\\Plugin\\Core\\Exception' => $baseDir . '/src/phpDocumentor/Plugin/Core/Exception.php', 'phpDocumentor\\Plugin\\Core\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Plugin/Core/ServiceProvider.php', 'phpDocumentor\\Plugin\\Core\\ServiceProviderTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/ServiceProviderTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\AuthorTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/AuthorTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\CoversTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/CoversTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\IgnoreTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/IgnoreTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\InternalTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/InternalTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\LicenseTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/LicenseTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\MethodTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/MethodTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\ParamTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/ParamTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\PropertyTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/PropertyTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\ReturnTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/ReturnTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\UsesTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/UsesTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Behaviour\\Tag\\VarTag' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/VarTag.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\CheckStyleTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/CheckStyleTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Checkstyle' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Checkstyle.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\FileIo' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/FileIo.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Pathfinder' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Pathfinder.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Sourcecode' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Sourcecode.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Statistics' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Statistics.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\StatisticsTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/StatisticsTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\XmlTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/XmlTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\ArgumentConverter' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/ArgumentConverter.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\ArgumentConverterTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/ArgumentConverterTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\ConstantConverter' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/ConstantConverter.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\ConstantConverterTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/ConstantConverterTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\DocBlockConverter' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/DocBlockConverter.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\DocBlockConverterTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/DocBlockConverterTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\InterfaceConverter' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/InterfaceConverter.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\InterfaceConverterTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/InterfaceConverterTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\MethodConverter' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/MethodConverter.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\MethodConverterTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/MethodConverterTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\PropertyConverter' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/PropertyConverter.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\PropertyConverterTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/PropertyConverterTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\TagConverter' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/TagConverter.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\TagConverterTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/TagConverterTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\TraitConverter' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/TraitConverter.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xml\\TraitConverterTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/Core/Transformer/Writer/Xml/TraitConverterTest.php', 'phpDocumentor\\Plugin\\Core\\Transformer\\Writer\\Xsl' => $baseDir . '/src/phpDocumentor/Plugin/Core/Transformer/Writer/Xsl.php', 'phpDocumentor\\Plugin\\Core\\Xslt\\Extension' => $baseDir . '/src/phpDocumentor/Plugin/Core/Xslt/Extension.php', 'phpDocumentor\\Plugin\\Graphs\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Plugin/Graphs/ServiceProvider.php', 'phpDocumentor\\Plugin\\Graphs\\Writer\\Graph' => $baseDir . '/src/phpDocumentor/Plugin/Graphs/Writer/Graph.php', 'phpDocumentor\\Plugin\\LegacyNamespaceConverter\\LegacyNamespaceFilter' => $baseDir . '/src/phpDocumentor/Plugin/LegacyNamespaceConverter/LegacyNamespaceFilter.php', 'phpDocumentor\\Plugin\\LegacyNamespaceConverter\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Plugin/LegacyNamespaceConverter/ServiceProvider.php', 'phpDocumentor\\Plugin\\LegacyNamespaceConverter\\Tests\\LegacyNamespaceFilterTest' => $baseDir . '/src/phpDocumentor/Plugin/LegacyNamespaceConverter/Tests/LegacyNamespaceFilterTest.php', 'phpDocumentor\\Plugin\\Parameter' => $baseDir . '/src/phpDocumentor/Plugin/Parameter.php', 'phpDocumentor\\Plugin\\ParameterTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/ParameterTest.php', 'phpDocumentor\\Plugin\\Plugin' => $baseDir . '/src/phpDocumentor/Plugin/Plugin.php', 'phpDocumentor\\Plugin\\PluginTest' => $baseDir . '/tests/unit/phpDocumentor/Plugin/PluginTest.php', 'phpDocumentor\\Plugin\\Scrybe\\ApplicationTest' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/ApplicationTest.php', 'phpDocumentor\\Plugin\\Scrybe\\Command\\Manual\\BaseConvertCommand' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Command/Manual/BaseConvertCommand.php', 'phpDocumentor\\Plugin\\Scrybe\\Command\\Manual\\ToHtmlCommand' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Command/Manual/ToHtmlCommand.php', 'phpDocumentor\\Plugin\\Scrybe\\Command\\Manual\\ToLatexCommand' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Command/Manual/ToLatexCommand.php', 'phpDocumentor\\Plugin\\Scrybe\\Command\\Manual\\ToPdfCommand' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Command/Manual/ToPdfCommand.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\BaseConverter' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/BaseConverter.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\ConverterInterface' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/ConverterInterface.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Definition\\Definition' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Definition/Definition.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Definition\\Factory' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Definition/Factory.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Exception\\ConverterNotFoundException' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Exception/ConverterNotFoundException.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Factory' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Factory.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Format\\Collection' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Format/Collection.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Format\\Exception\\FormatNotFoundException' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Format/Exception/FormatNotFoundException.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Format\\Format' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Format/Format.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\Assets' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Metadata/Assets.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\Glossary' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Metadata/Glossary.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\TableOfContents' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Metadata/TableOfContents.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\TableOfContentsTest' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Converter/Metadata/TableOfContentsTest.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\TableOfContents\\BaseEntry' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Metadata/TableOfContents/BaseEntry.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\TableOfContents\\BaseEntryTest' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Converter/Metadata/TableOfContents/BaseEntryTest.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\TableOfContents\\File' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Metadata/TableOfContents/File.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\TableOfContents\\FileTest' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Converter/Metadata/TableOfContents/FileTest.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\TableOfContents\\Heading' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Metadata/TableOfContents/Heading.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\TableOfContents\\Module' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/Metadata/TableOfContents/Module.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\Metadata\\TableOfContents\\ModuleTest' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Converter/Metadata/TableOfContents/ModuleTest.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\RestructuredText\\Directives\\CodeBlock' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Directives/CodeBlock.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\RestructuredText\\Directives\\Figure' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Directives/Figure.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\RestructuredText\\Directives\\Image' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Directives/Image.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\RestructuredText\\Directives\\Toctree' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Directives/Toctree.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\RestructuredText\\Document' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Document.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\RestructuredText\\Roles\\Doc' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Roles/Doc.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\RestructuredText\\ToHtml' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/ToHtml.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\RestructuredText\\Visitors\\Creator' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Visitors/Creator.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\RestructuredText\\Visitors\\Discover' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/RestructuredText/Visitors/Discover.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\RestructuredText\\Visitors\\DiscoverTest' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Converter/RestructuredText/Visitors/DiscoverTest.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\ToHtmlInterface' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/ToHtmlInterface.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\ToLatexInterface' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/ToLatexInterface.php', 'phpDocumentor\\Plugin\\Scrybe\\Converter\\ToPdfInterface' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Converter/ToPdfInterface.php', 'phpDocumentor\\Plugin\\Scrybe\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/ServiceProvider.php', 'phpDocumentor\\Plugin\\Scrybe\\Template\\Factory' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Template/Factory.php', 'phpDocumentor\\Plugin\\Scrybe\\Template\\FactoryTest' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Template/FactoryTest.php', 'phpDocumentor\\Plugin\\Scrybe\\Template\\Mock\\Template' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Template/Mock/Template.php', 'phpDocumentor\\Plugin\\Scrybe\\Template\\TemplateInterface' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Template/TemplateInterface.php', 'phpDocumentor\\Plugin\\Scrybe\\Template\\Twig' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/Template/Twig.php', 'phpDocumentor\\Plugin\\Scrybe\\Template\\TwigTest' => $baseDir . '/src/phpDocumentor/Plugin/Scrybe/tests/phpDocumentor/Scrybe/Template/TwigTest.php', 'phpDocumentor\\Plugin\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Plugin/ServiceProvider.php', 'phpDocumentor\\Plugin\\Twig\\Extension' => $baseDir . '/src/phpDocumentor/Plugin/Twig/Extension.php', 'phpDocumentor\\Plugin\\Twig\\ExtensionInterface' => $baseDir . '/src/phpDocumentor/Plugin/Twig/ExtensionInterface.php', 'phpDocumentor\\Plugin\\Twig\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Plugin/Twig/ServiceProvider.php', 'phpDocumentor\\Plugin\\Twig\\Writer\\Twig' => $baseDir . '/src/phpDocumentor/Plugin/Twig/Writer/Twig.php', 'phpDocumentor\\Reflection\\BaseReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/BaseReflector.php', 'phpDocumentor\\Reflection\\BaseReflectorMock' => $vendorDir . '/phpdocumentor/reflection/tests/mocks/phpDocumentor/Reflection/BaseReflectorMock.php', 'phpDocumentor\\Reflection\\BaseReflectorTest' => $vendorDir . '/phpdocumentor/reflection/tests/unit/phpDocumentor/Reflection/BaseReflectorTest.php', 'phpDocumentor\\Reflection\\ClassReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector.php', 'phpDocumentor\\Reflection\\ClassReflectorMock' => $vendorDir . '/phpdocumentor/reflection/tests/mocks/phpDocumentor/Reflection/ClassReflectorMock.php', 'phpDocumentor\\Reflection\\ClassReflectorTest' => $vendorDir . '/phpdocumentor/reflection/tests/unit/phpDocumentor/Reflection/ClassReflectorTest.php', 'phpDocumentor\\Reflection\\ClassReflector\\ConstantReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector/ConstantReflector.php', 'phpDocumentor\\Reflection\\ClassReflector\\MethodReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector/MethodReflector.php', 'phpDocumentor\\Reflection\\ClassReflector\\PropertyReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector/PropertyReflector.php', 'phpDocumentor\\Reflection\\ConstantReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/ConstantReflector.php', 'phpDocumentor\\Reflection\\DocBlock' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock.php', 'phpDocumentor\\Reflection\\DocBlock\\Context' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Context.php', 'phpDocumentor\\Reflection\\DocBlock\\Description' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Description.php', 'phpDocumentor\\Reflection\\DocBlock\\Location' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Location.php', 'phpDocumentor\\Reflection\\DocBlock\\Serializer' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Serializer.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\AuthorTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/AuthorTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\CoversTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/CoversTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\DeprecatedTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/DeprecatedTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\ExampleTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ExampleTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\LinkTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/LinkTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\MethodTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/MethodTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\ParamTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ParamTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\PropertyReadTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/PropertyReadTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\PropertyTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/PropertyTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\PropertyWriteTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/PropertyWriteTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\ReturnTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ReturnTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\SeeTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/SeeTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\SinceTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/SinceTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\SourceTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/SourceTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\ThrowsTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ThrowsTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\UsesTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/UsesTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\VarTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/VarTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Tag\\VersionTag' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/VersionTag.php', 'phpDocumentor\\Reflection\\DocBlock\\Type\\Collection' => $vendorDir . '/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Type/Collection.php', 'phpDocumentor\\Reflection\\Event\\ExportDocBlockTagEvent' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/Event/ExportDocBlockTagEvent.php', 'phpDocumentor\\Reflection\\Event\\PostDocBlockExtractionEvent' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/Event/PostDocBlockExtractionEvent.php', 'phpDocumentor\\Reflection\\Exception' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/Exception.php', 'phpDocumentor\\Reflection\\Exception\\UnparsableFile' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/Exception/UnparsableFile.php', 'phpDocumentor\\Reflection\\Exception\\UnreadableFile' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/Exception/UnreadableFile.php', 'phpDocumentor\\Reflection\\FileReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/FileReflector.php', 'phpDocumentor\\Reflection\\FunctionReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/FunctionReflector.php', 'phpDocumentor\\Reflection\\FunctionReflector\\ArgumentReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/FunctionReflector/ArgumentReflector.php', 'phpDocumentor\\Reflection\\IncludeReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/IncludeReflector.php', 'phpDocumentor\\Reflection\\InterfaceReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/InterfaceReflector.php', 'phpDocumentor\\Reflection\\Lexer' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/Lexer.php', 'phpDocumentor\\Reflection\\NodeExprMock' => $vendorDir . '/phpdocumentor/reflection/tests/mocks/phpDocumentor/Reflection/NodeExprMock.php', 'phpDocumentor\\Reflection\\NodeStmtMock' => $vendorDir . '/phpdocumentor/reflection/tests/mocks/phpDocumentor/Reflection/NodeStmtMock.php', 'phpDocumentor\\Reflection\\NodeStmtMock2' => $vendorDir . '/phpdocumentor/reflection/tests/mocks/phpDocumentor/Reflection/NodeStmtMock2.php', 'phpDocumentor\\Reflection\\PrettyPrinter' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/PrettyPrinter.php', 'phpDocumentor\\Reflection\\PrettyPrinterTest' => $vendorDir . '/phpdocumentor/reflection/tests/unit/phpDocumentor/Reflection/PrettyPrinterTest.php', 'phpDocumentor\\Reflection\\ReflectionAbstract' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/ReflectionAbstract.php', 'phpDocumentor\\Reflection\\TraitReflector' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/TraitReflector.php', 'phpDocumentor\\Reflection\\Traverser' => $vendorDir . '/phpdocumentor/reflection/src/phpDocumentor/Reflection/Traverser.php', 'phpDocumentor\\Transformer\\Behaviour\\BehaviourAbstract' => $baseDir . '/src/phpDocumentor/Transformer/Behaviour/BehaviourAbstract.php', 'phpDocumentor\\Transformer\\Behaviour\\BehaviourAbstractTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Behaviour/BehaviourAbstractTest.php', 'phpDocumentor\\Transformer\\Behaviour\\Collection' => $baseDir . '/src/phpDocumentor/Transformer/Behaviour/Collection.php', 'phpDocumentor\\Transformer\\Behaviour\\CollectionTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Behaviour/CollectionTest.php', 'phpDocumentor\\Transformer\\Command\\Project\\TransformCommand' => $baseDir . '/src/phpDocumentor/Transformer/Command/Project/TransformCommand.php', 'phpDocumentor\\Transformer\\Command\\Template\\ListCommand' => $baseDir . '/src/phpDocumentor/Transformer/Command/Template/ListCommand.php', 'phpDocumentor\\Transformer\\Command\\Template\\ListCommandTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Command/Template/ListCommandTest.php', 'phpDocumentor\\Transformer\\Configuration' => $baseDir . '/src/phpDocumentor/Transformer/Configuration.php', 'phpDocumentor\\Transformer\\ConfigurationTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/ConfigurationTest.php', 'phpDocumentor\\Transformer\\Configuration\\ExternalClassDocumentation' => $baseDir . '/src/phpDocumentor/Transformer/Configuration/ExternalClassDocumentation.php', 'phpDocumentor\\Transformer\\Configuration\\ExternalClassDocumentationTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Configuration/ExternalClassDocumentationTest.php', 'phpDocumentor\\Transformer\\Configuration\\Transformations' => $baseDir . '/src/phpDocumentor/Transformer/Configuration/Transformations.php', 'phpDocumentor\\Transformer\\Configuration\\TransformationsTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Configuration/TransformationsTest.php', 'phpDocumentor\\Transformer\\Configuration\\Transformations\\Template' => $baseDir . '/src/phpDocumentor/Transformer/Configuration/Transformations/Template.php', 'phpDocumentor\\Transformer\\Configuration\\Transformations\\TemplateTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Configuration/Transformations/TemplateTest.php', 'phpDocumentor\\Transformer\\Event\\PostTransformEvent' => $baseDir . '/src/phpDocumentor/Transformer/Event/PostTransformEvent.php', 'phpDocumentor\\Transformer\\Event\\PostTransformationEvent' => $baseDir . '/src/phpDocumentor/Transformer/Event/PostTransformationEvent.php', 'phpDocumentor\\Transformer\\Event\\PreTransformEvent' => $baseDir . '/src/phpDocumentor/Transformer/Event/PreTransformEvent.php', 'phpDocumentor\\Transformer\\Event\\PreTransformEventTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Event/PreTransformEventTest.php', 'phpDocumentor\\Transformer\\Event\\PreTransformationEvent' => $baseDir . '/src/phpDocumentor/Transformer/Event/PreTransformationEvent.php', 'phpDocumentor\\Transformer\\Event\\PreTransformationEventTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Event/PreTransformationEventTest.php', 'phpDocumentor\\Transformer\\Event\\PreXslWriterEvent' => $baseDir . '/src/phpDocumentor/Transformer/Event/PreXslWriterEvent.php', 'phpDocumentor\\Transformer\\Event\\PreXslWriterEventTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Event/PreXslWriterEventTest.php', 'phpDocumentor\\Transformer\\Event\\WriterInitializationEvent' => $baseDir . '/src/phpDocumentor/Transformer/Event/WriterInitializationEvent.php', 'phpDocumentor\\Transformer\\Exception' => $baseDir . '/src/phpDocumentor/Transformer/Exception.php', 'phpDocumentor\\Transformer\\Exception\\MissingDependencyException' => $baseDir . '/src/phpDocumentor/Transformer/Exception/MissingDependencyException.php', 'phpDocumentor\\Transformer\\Exception\\UnknownWriter' => $baseDir . '/src/phpDocumentor/Transformer/Exception/UnknownWriter.php', 'phpDocumentor\\Transformer\\Router\\ExternalRouter' => $baseDir . '/src/phpDocumentor/Transformer/Router/ExternalRouter.php', 'phpDocumentor\\Transformer\\Router\\ExternalRouterTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/ExternalRouterTest.php', 'phpDocumentor\\Transformer\\Router\\ForFileProxy' => $baseDir . '/src/phpDocumentor/Transformer/Router/ForFileProxy.php', 'phpDocumentor\\Transformer\\Router\\ForFileProxyTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/ForFileProxyTest.php', 'phpDocumentor\\Transformer\\Router\\Matcher\\MatcherInterface' => $baseDir . '/src/phpDocumentor/Transformer/Router/Matcher/MatcherInterface.php', 'phpDocumentor\\Transformer\\Router\\Queue' => $baseDir . '/src/phpDocumentor/Transformer/Router/Queue.php', 'phpDocumentor\\Transformer\\Router\\QueueTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/QueueTest.php', 'phpDocumentor\\Transformer\\Router\\Renderer' => $baseDir . '/src/phpDocumentor/Transformer/Router/Renderer.php', 'phpDocumentor\\Transformer\\Router\\RouterAbstract' => $baseDir . '/src/phpDocumentor/Transformer/Router/RouterAbstract.php', 'phpDocumentor\\Transformer\\Router\\Rule' => $baseDir . '/src/phpDocumentor/Transformer/Router/Rule.php', 'phpDocumentor\\Transformer\\Router\\RuleTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/RuleTest.php', 'phpDocumentor\\Transformer\\Router\\StandardRouter' => $baseDir . '/src/phpDocumentor/Transformer/Router/StandardRouter.php', 'phpDocumentor\\Transformer\\Router\\StandardRouterTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/StandardRouterTest.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\ClassDescriptor' => $baseDir . '/src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/ClassDescriptor.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\ClassDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/UrlGenerator/Standard/ClassDescriptorTest.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\ConstantDescriptor' => $baseDir . '/src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/ConstantDescriptor.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\ConstantDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/UrlGenerator/Standard/ConstantDescriptorTest.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\FileDescriptor' => $baseDir . '/src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/FileDescriptor.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\FileDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/UrlGenerator/Standard/FileDescriptorTest.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\FunctionDescriptor' => $baseDir . '/src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/FunctionDescriptor.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\FunctionDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/UrlGenerator/Standard/FunctionDescriptorTest.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\MethodDescriptor' => $baseDir . '/src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/MethodDescriptor.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\MethodDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/UrlGenerator/Standard/MethodDescriptorTest.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\NamespaceDescriptor' => $baseDir . '/src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/NamespaceDescriptor.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\NamespaceDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/UrlGenerator/Standard/NamespaceDescriptorTest.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\PackageDescriptor' => $baseDir . '/src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/PackageDescriptor.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\PackageDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/UrlGenerator/Standard/PackageDescriptorTest.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\PropertyDescriptor' => $baseDir . '/src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/PropertyDescriptor.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\PropertyDescriptorTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Router/UrlGenerator/Standard/PropertyDescriptorTest.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\Standard\\QualifiedNameToUrlConverter' => $baseDir . '/src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/QualifiedNameToUrlConverter.php', 'phpDocumentor\\Transformer\\Router\\UrlGenerator\\UrlGeneratorInterface' => $baseDir . '/src/phpDocumentor/Transformer/Router/UrlGenerator/UrlGeneratorInterface.php', 'phpDocumentor\\Transformer\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Transformer/ServiceProvider.php', 'phpDocumentor\\Transformer\\Template' => $baseDir . '/src/phpDocumentor/Transformer/Template.php', 'phpDocumentor\\Transformer\\Template\\Collection' => $baseDir . '/src/phpDocumentor/Transformer/Template/Collection.php', 'phpDocumentor\\Transformer\\Template\\CollectionTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Template/CollectionTest.php', 'phpDocumentor\\Transformer\\Template\\Factory' => $baseDir . '/src/phpDocumentor/Transformer/Template/Factory.php', 'phpDocumentor\\Transformer\\Template\\FactoryTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Template/FactoryTest.php', 'phpDocumentor\\Transformer\\Template\\Parameter' => $baseDir . '/src/phpDocumentor/Transformer/Template/Parameter.php', 'phpDocumentor\\Transformer\\Template\\ParameterTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Template/ParameterTest.php', 'phpDocumentor\\Transformer\\Template\\PathResolver' => $baseDir . '/src/phpDocumentor/Transformer/Template/PathResolver.php', 'phpDocumentor\\Transformer\\Template\\PathResolverTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Template/PathResolverTest.php', 'phpDocumentor\\Transformer\\Transformation' => $baseDir . '/src/phpDocumentor/Transformer/Transformation.php', 'phpDocumentor\\Transformer\\TransformationTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/TransformationTest.php', 'phpDocumentor\\Transformer\\Transformer' => $baseDir . '/src/phpDocumentor/Transformer/Transformer.php', 'phpDocumentor\\Transformer\\TransformerTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/TransformerTest.php', 'phpDocumentor\\Transformer\\Writer\\Collection' => $baseDir . '/src/phpDocumentor/Transformer/Writer/Collection.php', 'phpDocumentor\\Transformer\\Writer\\CollectionTest' => $baseDir . '/tests/unit/phpDocumentor/Transformer/Writer/CollectionTest.php', 'phpDocumentor\\Transformer\\Writer\\Exception\\RequirementMissing' => $baseDir . '/src/phpDocumentor/Transformer/Writer/Exception/RequirementMissing.php', 'phpDocumentor\\Transformer\\Writer\\Initializable' => $baseDir . '/src/phpDocumentor/Transformer/Writer/Initializable.php', 'phpDocumentor\\Transformer\\Writer\\Routable' => $baseDir . '/src/phpDocumentor/Transformer/Writer/Routable.php', 'phpDocumentor\\Transformer\\Writer\\Translatable' => $baseDir . '/src/phpDocumentor/Transformer/Writer/Translatable.php', 'phpDocumentor\\Transformer\\Writer\\WriterAbstract' => $baseDir . '/src/phpDocumentor/Transformer/Writer/WriterAbstract.php', 'phpDocumentor\\Translator\\Configuration' => $baseDir . '/src/phpDocumentor/Translator/Configuration.php', 'phpDocumentor\\Translator\\ConfigurationTest' => $baseDir . '/tests/unit/phpDocumentor/Translator/ConfigurationTest.php', 'phpDocumentor\\Translator\\ServiceProvider' => $baseDir . '/src/phpDocumentor/Translator/ServiceProvider.php', 'phpDocumentor\\Translator\\ServiceProviderTest' => $baseDir . '/tests/unit/phpDocumentor/Translator/ServiceProviderTest.php', 'phpDocumentor\\Translator\\Translator' => $baseDir . '/src/phpDocumentor/Translator/Translator.php', 'phpDocumentor\\Translator\\TranslatorTest' => $baseDir . '/tests/unit/phpDocumentor/Translator/TranslatorTest.php', ); $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest.php', '742b7e606e92b28dd726e835467f413a' => $vendorDir . '/herrera-io/json/src/lib/json_version.php', 'fe1bcd0336136e435eaf197895daf81a' => $vendorDir . '/nikic/php-parser/lib/bootstrap.php', 'f0e9d233388e461ee3c460665eb265f0' => $vendorDir . '/herrera-io/phar-update/src/lib/constants.php', ); array($baseDir . '/src', $baseDir . '/tests/unit', $vendorDir . '/phpdocumentor/fileset/src', $vendorDir . '/phpdocumentor/fileset/tests/unit', $vendorDir . '/phpdocumentor/graphviz/src', $vendorDir . '/phpdocumentor/graphviz/tests/unit', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/reflection/src', $vendorDir . '/phpdocumentor/reflection/tests/unit', $vendorDir . '/phpdocumentor/reflection/tests/mocks'), 'org\\bovigo\\vfs\\' => array($vendorDir . '/mikey179/vfsStream/src/main/php'), 'Twig_' => array($vendorDir . '/twig/twig/lib'), 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), 'Symfony\\Component\\Validator\\' => array($vendorDir . '/symfony/validator'), 'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'), 'Symfony\\Component\\Stopwatch\\' => array($vendorDir . '/symfony/stopwatch'), 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'), 'Symfony\\Component\\ExpressionLanguage\\' => array($vendorDir . '/symfony/expression-language'), 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), 'Symfony\\Component\\DependencyInjection\\' => array($vendorDir . '/symfony/dependency-injection'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), 'Symfony\\Component\\Config\\' => array($vendorDir . '/symfony/config'), 'Symfony\\Component\\ClassLoader\\' => array($vendorDir . '/symfony/class-loader'), 'Psr\\Log\\' => array($vendorDir . '/psr/log'), 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'), 'Pimple' => array($vendorDir . '/pimple/pimple/lib'), 'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src'), 'PhpCollection' => array($vendorDir . '/phpcollection/phpcollection/src'), 'Parsedown' => array($vendorDir . '/erusev/parsedown'), 'Mockery' => array($vendorDir . '/mockery/mockery/library'), 'Metadata\\' => array($vendorDir . '/jms/metadata/src'), 'KevinGH\\Version' => array($vendorDir . '/kherge/version/src/lib'), 'JMS\\Serializer' => array($vendorDir . '/jms/serializer/src'), 'JMS\\' => array($vendorDir . '/jms/parser-lib/src'), 'Herrera\\Phar\\Update' => array($vendorDir . '/herrera-io/phar-update/src/lib'), 'Herrera\\Json' => array($vendorDir . '/herrera-io/json/src/lib'), 'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src'), 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib'), 'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib'), 'Cilex\\Provider\\Console' => array($vendorDir . '/cilex/console-service-provider/src'), 'Cilex\\Provider' => array($baseDir . '/src'), 'Cilex' => array($vendorDir . '/cilex/cilex/src'), 'Behat\\Transliterator' => array($vendorDir . '/behat/transliterator/src'), 'Behat\\Testwork' => array($vendorDir . '/behat/behat/src'), 'Behat\\Gherkin' => array($vendorDir . '/behat/gherkin/src'), 'Behat\\Behat' => array($vendorDir . '/behat/behat/src'), ); * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Extends \SplFileInfo to support relative paths. * * @author Fabien Potencier */ class SplFileInfo extends \SplFileInfo { private $relativePath; private $relativePathname; /** * Constructor. * * @param string $file The file name * @param string $relativePath The relative path * @param string $relativePathname The relative path name */ public function __construct($file, $relativePath, $relativePathname) { parent::__construct($file); $this->relativePath = $relativePath; $this->relativePathname = $relativePathname; } /** * Returns the relative path. * * @return string the relative path */ public function getRelativePath() { return $this->relativePath; } /** * Returns the relative path name. * * @return string the relative path name */ public function getRelativePathname() { return $this->relativePathname; } /** * Returns the contents of the file. * * @return string the contents of the file * * @throws \RuntimeException */ public function getContents() { $level = error_reporting(0); $content = file_get_contents($this->getPathname()); error_reporting($level); if (false === $content) { $error = error_get_last(); throw new \RuntimeException($error['message']); } return $content; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Glob matches globbing patterns against text. * * if match_glob("foo.*", "foo.bar") echo "matched\n"; * * // prints foo.bar and foo.baz * $regex = glob_to_regex("foo.*"); * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t) * { * if (/$regex/) echo "matched: $car\n"; * } * * Glob implements glob(3) style matching that can be used to match * against text, rather than fetching names from a filesystem. * * Based on the Perl Text::Glob module. * * @author Fabien Potencier PHP port * @author Richard Clamp Perl version * @copyright 2004-2005 Fabien Potencier * @copyright 2002 Richard Clamp */ class Glob { /** * Returns a regexp which is the equivalent of the glob pattern. * * @param string $glob The glob pattern * @param bool $strictLeadingDot * @param bool $strictWildcardSlash * * @return string regex The regexp */ public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true) { $firstByte = true; $escaping = false; $inCurlies = 0; $regex = ''; $sizeGlob = strlen($glob); for ($i = 0; $i < $sizeGlob; ++$i) { $car = $glob[$i]; if ($firstByte) { if ($strictLeadingDot && '.' !== $car) { $regex .= '(?=[^\.])'; } $firstByte = false; } if ('/' === $car) { $firstByte = true; } if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { $regex .= "\\$car"; } elseif ('*' === $car) { $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); } elseif ('?' === $car) { $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); } elseif ('{' === $car) { $regex .= $escaping ? '\\{' : '('; if (!$escaping) { ++$inCurlies; } } elseif ('}' === $car && $inCurlies) { $regex .= $escaping ? '}' : ')'; if (!$escaping) { --$inCurlies; } } elseif (',' === $car && $inCurlies) { $regex .= $escaping ? ',' : '|'; } elseif ('\\' === $car) { if ($escaping) { $regex .= '\\\\'; $escaping = false; } else { $escaping = true; } continue; } else { $regex .= $car; } $escaping = false; } return '#^'.$regex.'$#'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Glob implements ValueInterface { /** * @var string */ private $pattern; /** * @param string $pattern */ public function __construct($pattern) { $this->pattern = $pattern; } /** * {@inheritdoc} */ public function render() { return $this->pattern; } /** * {@inheritdoc} */ public function renderPattern() { return $this->pattern; } /** * {@inheritdoc} */ public function getType() { return Expression::TYPE_GLOB; } /** * {@inheritdoc} */ public function isCaseSensitive() { return true; } /** * {@inheritdoc} */ public function prepend($expr) { $this->pattern = $expr.$this->pattern; return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->pattern .= $expr; return $this; } /** * Tests if glob is expandable ("*.{a,b}" syntax). * * @return bool */ public function isExpandable() { return false !== strpos($this->pattern, '{') && false !== strpos($this->pattern, '}'); } /** * @param bool $strictLeadingDot * @param bool $strictWildcardSlash * * @return Regex */ public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true) { $firstByte = true; $escaping = false; $inCurlies = 0; $regex = ''; $sizeGlob = strlen($this->pattern); for ($i = 0; $i < $sizeGlob; ++$i) { $car = $this->pattern[$i]; if ($firstByte) { if ($strictLeadingDot && '.' !== $car) { $regex .= '(?=[^\.])'; } $firstByte = false; } if ('/' === $car) { $firstByte = true; } if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { $regex .= "\\$car"; } elseif ('*' === $car) { $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); } elseif ('?' === $car) { $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); } elseif ('{' === $car) { $regex .= $escaping ? '\\{' : '('; if (!$escaping) { ++$inCurlies; } } elseif ('}' === $car && $inCurlies) { $regex .= $escaping ? '}' : ')'; if (!$escaping) { --$inCurlies; } } elseif (',' === $car && $inCurlies) { $regex .= $escaping ? ',' : '|'; } elseif ('\\' === $car) { if ($escaping) { $regex .= '\\\\'; $escaping = false; } else { $escaping = true; } continue; } else { $regex .= $car; } $escaping = false; } return new Regex('^'.$regex.'$'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ interface ValueInterface { /** * Renders string representation of expression. * * @return string */ public function render(); /** * Renders string representation of pattern. * * @return string */ public function renderPattern(); /** * Returns value case sensitivity. * * @return bool */ public function isCaseSensitive(); /** * Returns expression type. * * @return int */ public function getType(); /** * @param string $expr * * @return ValueInterface */ public function prepend($expr); /** * @param string $expr * * @return ValueInterface */ public function append($expr); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Expression implements ValueInterface { const TYPE_REGEX = 1; const TYPE_GLOB = 2; /** * @var ValueInterface */ private $value; /** * @param string $expr * * @return Expression */ public static function create($expr) { return new self($expr); } /** * @param string $expr */ public function __construct($expr) { try { $this->value = Regex::create($expr); } catch (\InvalidArgumentException $e) { $this->value = new Glob($expr); } } /** * @return string */ public function __toString() { return $this->render(); } /** * {@inheritdoc} */ public function render() { return $this->value->render(); } /** * {@inheritdoc} */ public function renderPattern() { return $this->value->renderPattern(); } /** * @return bool */ public function isCaseSensitive() { return $this->value->isCaseSensitive(); } /** * @return int */ public function getType() { return $this->value->getType(); } /** * {@inheritdoc} */ public function prepend($expr) { $this->value->prepend($expr); return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->value->append($expr); return $this; } /** * @return bool */ public function isRegex() { return self::TYPE_REGEX === $this->value->getType(); } /** * @return bool */ public function isGlob() { return self::TYPE_GLOB === $this->value->getType(); } /** * @throws \LogicException * * @return Glob */ public function getGlob() { if (self::TYPE_GLOB !== $this->value->getType()) { throw new \LogicException('Regex can\'t be transformed to glob.'); } return $this->value; } /** * @return Regex */ public function getRegex() { return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Regex implements ValueInterface { const START_FLAG = '^'; const END_FLAG = '$'; const BOUNDARY = '~'; const JOKER = '.*'; const ESCAPING = '\\'; /** * @var string */ private $pattern; /** * @var array */ private $options; /** * @var bool */ private $startFlag; /** * @var bool */ private $endFlag; /** * @var bool */ private $startJoker; /** * @var bool */ private $endJoker; /** * @param string $expr * * @return Regex * * @throws \InvalidArgumentException */ public static function create($expr) { if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) { $start = substr($m[1], 0, 1); $end = substr($m[1], -1); if ( ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start)) || ($start === '{' && $end === '}') || ($start === '(' && $end === ')') ) { return new self(substr($m[1], 1, -1), $m[2], $end); } } throw new \InvalidArgumentException('Given expression is not a regex.'); } /** * @param string $pattern * @param string $options * @param string $delimiter */ public function __construct($pattern, $options = '', $delimiter = null) { if (null !== $delimiter) { // removes delimiter escaping $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern); } $this->parsePattern($pattern); $this->options = $options; } /** * @return string */ public function __toString() { return $this->render(); } /** * {@inheritdoc} */ public function render() { return self::BOUNDARY .$this->renderPattern() .self::BOUNDARY .$this->options; } /** * {@inheritdoc} */ public function renderPattern() { return ($this->startFlag ? self::START_FLAG : '') .($this->startJoker ? self::JOKER : '') .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern) .($this->endJoker ? self::JOKER : '') .($this->endFlag ? self::END_FLAG : ''); } /** * {@inheritdoc} */ public function isCaseSensitive() { return !$this->hasOption('i'); } /** * {@inheritdoc} */ public function getType() { return Expression::TYPE_REGEX; } /** * {@inheritdoc} */ public function prepend($expr) { $this->pattern = $expr.$this->pattern; return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->pattern .= $expr; return $this; } /** * @param string $option * * @return bool */ public function hasOption($option) { return false !== strpos($this->options, $option); } /** * @param string $option * * @return Regex */ public function addOption($option) { if (!$this->hasOption($option)) { $this->options .= $option; } return $this; } /** * @param string $option * * @return Regex */ public function removeOption($option) { $this->options = str_replace($option, '', $this->options); return $this; } /** * @param bool $startFlag * * @return Regex */ public function setStartFlag($startFlag) { $this->startFlag = $startFlag; return $this; } /** * @return bool */ public function hasStartFlag() { return $this->startFlag; } /** * @param bool $endFlag * * @return Regex */ public function setEndFlag($endFlag) { $this->endFlag = (bool) $endFlag; return $this; } /** * @return bool */ public function hasEndFlag() { return $this->endFlag; } /** * @param bool $startJoker * * @return Regex */ public function setStartJoker($startJoker) { $this->startJoker = $startJoker; return $this; } /** * @return bool */ public function hasStartJoker() { return $this->startJoker; } /** * @param bool $endJoker * * @return Regex */ public function setEndJoker($endJoker) { $this->endJoker = (bool) $endJoker; return $this; } /** * @return bool */ public function hasEndJoker() { return $this->endJoker; } /** * @param array $replacement * * @return Regex */ public function replaceJokers($replacement) { $replace = function ($subject) use ($replacement) { $subject = $subject[0]; $replace = 0 === substr_count($subject, '\\') % 2; return $replace ? str_replace('.', $replacement, $subject) : $subject; }; $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern); return $this; } /** * @param string $pattern */ private function parsePattern($pattern) { if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) { $pattern = substr($pattern, 1); } if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) { $pattern = substr($pattern, 2); } if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) { $pattern = substr($pattern, 0, -1); } if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) { $pattern = substr($pattern, 0, -2); } $this->pattern = $pattern; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Shell; /** * @author Jean-François Simon */ class Shell { const TYPE_UNIX = 1; const TYPE_DARWIN = 2; const TYPE_CYGWIN = 3; const TYPE_WINDOWS = 4; const TYPE_BSD = 5; /** * @var string|null */ private $type; /** * Returns guessed OS type. * * @return int */ public function getType() { if (null === $this->type) { $this->type = $this->guessType(); } return $this->type; } /** * Tests if a command is available. * * @param string $command * * @return bool */ public function testCommand($command) { if (!function_exists('exec')) { return false; } // todo: find a better way (command could not be available) $testCommand = 'which '; if (self::TYPE_WINDOWS === $this->type) { $testCommand = 'where '; } $command = escapeshellcmd($command); exec($testCommand.$command, $output, $code); return 0 === $code && count($output) > 0; } /** * Guesses OS type. * * @return int */ private function guessType() { $os = strtolower(PHP_OS); if (false !== strpos($os, 'cygwin')) { return self::TYPE_CYGWIN; } if (false !== strpos($os, 'darwin')) { return self::TYPE_DARWIN; } if (false !== strpos($os, 'bsd')) { return self::TYPE_BSD; } if (0 === strpos($os, 'win')) { return self::TYPE_WINDOWS; } return self::TYPE_UNIX; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Shell; /** * @author Jean-François Simon */ class Command { /** * @var Command|null */ private $parent; /** * @var array */ private $bits = array(); /** * @var array */ private $labels = array(); /** * @var \Closure|null */ private $errorHandler; /** * Constructor. * * @param Command|null $parent Parent command */ public function __construct(Command $parent = null) { $this->parent = $parent; } /** * Returns command as string. * * @return string */ public function __toString() { return $this->join(); } /** * Creates a new Command instance. * * @param Command|null $parent Parent command * * @return Command New Command instance */ public static function create(Command $parent = null) { return new self($parent); } /** * Escapes special chars from input. * * @param string $input A string to escape * * @return string The escaped string */ public static function escape($input) { return escapeshellcmd($input); } /** * Quotes input. * * @param string $input An argument string * * @return string The quoted string */ public static function quote($input) { return escapeshellarg($input); } /** * Appends a string or a Command instance. * * @param string|Command $bit * * @return Command The current Command instance */ public function add($bit) { $this->bits[] = $bit; return $this; } /** * Prepends a string or a command instance. * * @param string|Command $bit * * @return Command The current Command instance */ public function top($bit) { array_unshift($this->bits, $bit); foreach ($this->labels as $label => $index) { $this->labels[$label] += 1; } return $this; } /** * Appends an argument, will be quoted. * * @param string $arg * * @return Command The current Command instance */ public function arg($arg) { $this->bits[] = self::quote($arg); return $this; } /** * Appends escaped special command chars. * * @param string $esc * * @return Command The current Command instance */ public function cmd($esc) { $this->bits[] = self::escape($esc); return $this; } /** * Inserts a labeled command to feed later. * * @param string $label The unique label * * @return Command The current Command instance * * @throws \RuntimeException If label already exists */ public function ins($label) { if (isset($this->labels[$label])) { throw new \RuntimeException(sprintf('Label "%s" already exists.', $label)); } $this->bits[] = self::create($this); $this->labels[$label] = count($this->bits) - 1; return $this->bits[$this->labels[$label]]; } /** * Retrieves a previously labeled command. * * @param string $label * * @return Command The labeled command * * @throws \RuntimeException */ public function get($label) { if (!isset($this->labels[$label])) { throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label)); } return $this->bits[$this->labels[$label]]; } /** * Returns parent command (if any). * * @return Command Parent command * * @throws \RuntimeException If command has no parent */ public function end() { if (null === $this->parent) { throw new \RuntimeException('Calling end on root command doesn\'t make sense.'); } return $this->parent; } /** * Counts bits stored in command. * * @return int The bits count */ public function length() { return count($this->bits); } /** * @param \Closure $errorHandler * * @return Command */ public function setErrorHandler(\Closure $errorHandler) { $this->errorHandler = $errorHandler; return $this; } /** * @return \Closure|null */ public function getErrorHandler() { return $this->errorHandler; } /** * Executes current command. * * @return array The command result * * @throws \RuntimeException */ public function execute() { if (null === $errorHandler = $this->errorHandler) { exec($this->join(), $output); } else { $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes); $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY); if ($error = stream_get_contents($pipes[2])) { $errorHandler($error); } proc_close($process); } return $output ?: array(); } /** * Joins bits. * * @return string */ public function join() { return implode(' ', array_filter( array_map(function ($bit) { return $bit instanceof Command ? $bit->join() : ($bit ?: null); }, $this->bits), function ($bit) { return null !== $bit; } )); } /** * Insert a string or a Command instance before the bit at given position $index (index starts from 0). * * @param string|Command $bit * @param int $index * * @return Command The current Command instance */ public function addAtIndex($bit, $index) { array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit); return $this; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * DateCompare compiles date comparisons. * * @author Fabien Potencier */ class DateComparator extends Comparator { /** * Constructor. * * @param string $test A comparison string * * @throws \InvalidArgumentException If the test is not understood */ public function __construct($test) { if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); } try { $date = new \DateTime($matches[2]); $target = $date->format('U'); } catch (\Exception $e) { throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); } $operator = isset($matches[1]) ? $matches[1] : '=='; if ('since' === $operator || 'after' === $operator) { $operator = '>'; } if ('until' === $operator || 'before' === $operator) { $operator = '<'; } $this->setOperator($operator); $this->setTarget($target); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * Comparator. * * @author Fabien Potencier */ class Comparator { private $target; private $operator = '=='; /** * Gets the target value. * * @return string The target value */ public function getTarget() { return $this->target; } /** * Sets the target value. * * @param string $target The target value */ public function setTarget($target) { $this->target = $target; } /** * Gets the comparison operator. * * @return string The operator */ public function getOperator() { return $this->operator; } /** * Sets the comparison operator. * * @param string $operator A valid operator * * @throws \InvalidArgumentException */ public function setOperator($operator) { if (!$operator) { $operator = '=='; } if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) { throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); } $this->operator = $operator; } /** * Tests against the target. * * @param mixed $test A test value * * @return bool */ public function test($test) { switch ($this->operator) { case '>': return $test > $this->target; case '>=': return $test >= $this->target; case '<': return $test < $this->target; case '<=': return $test <= $this->target; case '!=': return $test != $this->target; } return $test == $this->target; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * NumberComparator compiles a simple comparison to an anonymous * subroutine, which you can call with a value to be tested again. * * Now this would be very pointless, if NumberCompare didn't understand * magnitudes. * * The target value may use magnitudes of kilobytes (k, ki), * megabytes (m, mi), or gigabytes (g, gi). Those suffixed * with an i use the appropriate 2**n version in accordance with the * IEC standard: http://physics.nist.gov/cuu/Units/binary.html * * Based on the Perl Number::Compare module. * * @author Fabien Potencier PHP port * @author Richard Clamp Perl version * @copyright 2004-2005 Fabien Potencier * @copyright 2002 Richard Clamp * * @see http://physics.nist.gov/cuu/Units/binary.html */ class NumberComparator extends Comparator { /** * Constructor. * * @param string $test A comparison string * * @throws \InvalidArgumentException If the test is not understood */ public function __construct($test) { if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test)); } $target = $matches[2]; if (!is_numeric($target)) { throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); } if (isset($matches[3])) { // magnitude switch (strtolower($matches[3])) { case 'k': $target *= 1000; break; case 'ki': $target *= 1024; break; case 'm': $target *= 1000000; break; case 'mi': $target *= 1024 * 1024; break; case 'g': $target *= 1000000000; break; case 'gi': $target *= 1024 * 1024 * 1024; break; } } $this->setTarget($target); $this->setOperator(isset($matches[1]) ? $matches[1] : '=='); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * DepthRangeFilterIterator limits the directory depth. * * @author Fabien Potencier */ class DepthRangeFilterIterator extends FilterIterator { private $minDepth = 0; /** * Constructor. * * @param \RecursiveIteratorIterator $iterator The Iterator to filter * @param int $minDepth The min depth * @param int $maxDepth The max depth */ public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX) { $this->minDepth = $minDepth; $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { return $this->getInnerIterator()->getDepth() >= $this->minDepth; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\SplFileInfo; /** * Iterate over shell command result. * * @author Jean-François Simon */ class FilePathsIterator extends \ArrayIterator { /** * @var string */ private $baseDir; /** * @var int */ private $baseDirLength; /** * @var string */ private $subPath; /** * @var string */ private $subPathname; /** * @var SplFileInfo */ private $current; /** * @param array $paths List of paths returned by shell command * @param string $baseDir Base dir for relative path building */ public function __construct(array $paths, $baseDir) { $this->baseDir = $baseDir; $this->baseDirLength = strlen($baseDir); parent::__construct($paths); } /** * @param string $name * @param array $arguments * * @return mixed */ public function __call($name, array $arguments) { return call_user_func_array(array($this->current(), $name), $arguments); } /** * Return an instance of SplFileInfo with support for relative paths. * * @return SplFileInfo File information */ public function current() { return $this->current; } /** * @return string */ public function key() { return $this->current->getPathname(); } public function next() { parent::next(); $this->buildProperties(); } public function rewind() { parent::rewind(); $this->buildProperties(); } /** * @return string */ public function getSubPath() { return $this->subPath; } /** * @return string */ public function getSubPathname() { return $this->subPathname; } private function buildProperties() { $absolutePath = parent::current(); if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) { $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\'); $dir = dirname($this->subPathname); $this->subPath = '.' === $dir ? '' : $dir; } else { $this->subPath = $this->subPathname = ''; } $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * This iterator just overrides the rewind method in order to correct a PHP bug. * * @see https://bugs.php.net/bug.php?id=49104 * * @author Alex Bogomazov */ abstract class FilterIterator extends \FilterIterator { /** * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after * rewind in some cases. * * @see FilterIterator::rewind() */ public function rewind() { $iterator = $this; while ($iterator instanceof \OuterIterator) { $innerIterator = $iterator->getInnerIterator(); if ($innerIterator instanceof RecursiveDirectoryIterator) { if ($innerIterator->isRewindable()) { $innerIterator->next(); $innerIterator->rewind(); } } elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) { $iterator->getInnerIterator()->next(); $iterator->getInnerIterator()->rewind(); } $iterator = $iterator->getInnerIterator(); } parent::rewind(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Expression\Expression; /** * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). * * @author Fabien Potencier */ abstract class MultiplePcreFilterIterator extends FilterIterator { protected $matchRegexps = array(); protected $noMatchRegexps = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $matchPatterns An array of patterns that need to match * @param array $noMatchPatterns An array of patterns that need to not match */ public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) { foreach ($matchPatterns as $pattern) { $this->matchRegexps[] = $this->toRegex($pattern); } foreach ($noMatchPatterns as $pattern) { $this->noMatchRegexps[] = $this->toRegex($pattern); } parent::__construct($iterator); } /** * Checks whether the string is a regex. * * @param string $str * * @return bool Whether the given string is a regex */ protected function isRegex($str) { return Expression::create($str)->isRegex(); } /** * Converts string into regexp. * * @param string $str Pattern * * @return string regexp corresponding to a given string */ abstract protected function toRegex($str); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * PathFilterIterator filters files by path patterns (e.g. some/special/dir). * * @author Fabien Potencier * @author Włodzimierz Gajda */ class PathFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $filename = $this->current()->getRelativePathname(); if ('\\' === DIRECTORY_SEPARATOR) { $filename = strtr($filename, '\\', '/'); } // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $filename)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $filename)) { return true; } } } return $match; } /** * Converts strings to regexp. * * PCRE patterns are left unchanged. * * Default conversion: * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/' * * Use only / as directory separator (on Windows also). * * @param string $str Pattern: regexp or dirname. * * @return string regexp corresponding to a given string or regexp */ protected function toRegex($str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Expression\Expression; /** * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). * * @author Fabien Potencier */ class FilenameFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $filename = $this->current()->getFilename(); // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $filename)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $filename)) { return true; } } } return $match; } /** * Converts glob to regexp. * * PCRE patterns are left unchanged. * Glob strings are transformed with Glob::toRegex(). * * @param string $str Pattern: glob or regexp * * @return string regexp corresponding to a given glob or regexp */ protected function toRegex($str) { return Expression::create($str)->getRegex()->render(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Comparator\NumberComparator; /** * SizeRangeFilterIterator filters out files that are not in the given size range. * * @author Fabien Potencier */ class SizeRangeFilterIterator extends FilterIterator { private $comparators = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param NumberComparator[] $comparators An array of NumberComparator instances */ public function __construct(\Iterator $iterator, array $comparators) { $this->comparators = $comparators; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (!$fileinfo->isFile()) { return true; } $filesize = $fileinfo->getSize(); foreach ($this->comparators as $compare) { if (!$compare->test($filesize)) { return false; } } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * SortableIterator applies a sort on a given Iterator. * * @author Fabien Potencier */ class SortableIterator implements \IteratorAggregate { const SORT_BY_NAME = 1; const SORT_BY_TYPE = 2; const SORT_BY_ACCESSED_TIME = 3; const SORT_BY_CHANGED_TIME = 4; const SORT_BY_MODIFIED_TIME = 5; private $iterator; private $sort; /** * Constructor. * * @param \Traversable $iterator The Iterator to filter * @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) * * @throws \InvalidArgumentException */ public function __construct(\Traversable $iterator, $sort) { $this->iterator = $iterator; if (self::SORT_BY_NAME === $sort) { $this->sort = function ($a, $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }; } elseif (self::SORT_BY_TYPE === $sort) { $this->sort = function ($a, $b) { if ($a->isDir() && $b->isFile()) { return -1; } elseif ($a->isFile() && $b->isDir()) { return 1; } return strcmp($a->getRealpath(), $b->getRealpath()); }; } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getATime() - $b->getATime()); }; } elseif (self::SORT_BY_CHANGED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getCTime() - $b->getCTime()); }; } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getMTime() - $b->getMTime()); }; } elseif (is_callable($sort)) { $this->sort = $sort; } else { throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.'); } } public function getIterator() { $array = iterator_to_array($this->iterator, true); uasort($array, $this->sort); return new \ArrayIterator($array); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). * * @author Fabien Potencier * @author Włodzimierz Gajda */ class FilecontentFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { if (!$this->matchRegexps && !$this->noMatchRegexps) { return true; } $fileinfo = $this->current(); if ($fileinfo->isDir() || !$fileinfo->isReadable()) { return false; } $content = $fileinfo->getContents(); if (!$content) { return false; } // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $content)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $content)) { return true; } } } return $match; } /** * Converts string to regexp if necessary. * * @param string $str Pattern: string or regexp * * @return string regexp corresponding to a given string or regexp */ protected function toRegex($str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Comparator\DateComparator; /** * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). * * @author Fabien Potencier */ class DateRangeFilterIterator extends FilterIterator { private $comparators = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param DateComparator[] $comparators An array of DateComparator instances */ public function __construct(\Iterator $iterator, array $comparators) { $this->comparators = $comparators; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (!file_exists($fileinfo->getRealPath())) { return false; } $filedate = $fileinfo->getMTime(); foreach ($this->comparators as $compare) { if (!$compare->test($filedate)) { return false; } } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * FileTypeFilterIterator only keeps files, directories, or both. * * @author Fabien Potencier */ class FileTypeFilterIterator extends FilterIterator { const ONLY_FILES = 1; const ONLY_DIRECTORIES = 2; private $mode; /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) */ public function __construct(\Iterator $iterator, $mode) { $this->mode = $mode; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) { return false; } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) { return false; } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * ExcludeDirectoryFilterIterator filters out directories. * * @author Fabien Potencier */ class ExcludeDirectoryFilterIterator extends FilterIterator { private $patterns = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $directories An array of directories to exclude */ public function __construct(\Iterator $iterator, array $directories) { foreach ($directories as $directory) { $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#'; } parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); $path = strtr($path, '\\', '/'); foreach ($this->patterns as $pattern) { if (preg_match($pattern, $path)) { return false; } } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * CustomFilterIterator filters files by applying anonymous functions. * * The anonymous function receives a \SplFileInfo and must return false * to remove files. * * @author Fabien Potencier */ class CustomFilterIterator extends FilterIterator { private $filters = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $filters An array of PHP callbacks * * @throws \InvalidArgumentException */ public function __construct(\Iterator $iterator, array $filters) { foreach ($filters as $filter) { if (!is_callable($filter)) { throw new \InvalidArgumentException('Invalid PHP callback.'); } } $this->filters = $filters; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); foreach ($this->filters as $filter) { if (false === call_user_func($filter, $fileinfo)) { return false; } } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Exception\AccessDeniedException; use Symfony\Component\Finder\SplFileInfo; /** * Extends the \RecursiveDirectoryIterator to support relative paths. * * @author Victor Berchet */ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator { /** * @var bool */ private $ignoreUnreadableDirs; /** * @var bool */ private $rewindable; /** * Constructor. * * @param string $path * @param int $flags * @param bool $ignoreUnreadableDirs * * @throws \RuntimeException */ public function __construct($path, $flags, $ignoreUnreadableDirs = false) { if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { throw new \RuntimeException('This iterator only support returning current as fileinfo.'); } parent::__construct($path, $flags); $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; } /** * Return an instance of SplFileInfo with support for relative paths. * * @return SplFileInfo File information */ public function current() { return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname()); } /** * @return \RecursiveIterator * * @throws AccessDeniedException */ public function getChildren() { try { $children = parent::getChildren(); if ($children instanceof self) { // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; } return $children; } catch (\UnexpectedValueException $e) { if ($this->ignoreUnreadableDirs) { // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. return new \RecursiveArrayIterator(array()); } else { throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); } } } /** * Do nothing for non rewindable stream. */ public function rewind() { if (false === $this->isRewindable()) { return; } // @see https://bugs.php.net/bug.php?id=49104 parent::next(); parent::rewind(); } /** * Checks if the stream is rewindable. * * @return bool true when the stream is rewindable, false otherwise */ public function isRewindable() { if (null !== $this->rewindable) { return $this->rewindable; } if (false !== $stream = @opendir($this->getPath())) { $infos = stream_get_meta_data($stream); closedir($stream); if ($infos['seekable']) { return $this->rewindable = true; } } return $this->rewindable = false; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; use Symfony\Component\Finder\Adapter\AdapterInterface; use Symfony\Component\Finder\Adapter\GnuFindAdapter; use Symfony\Component\Finder\Adapter\BsdFindAdapter; use Symfony\Component\Finder\Adapter\PhpAdapter; use Symfony\Component\Finder\Comparator\DateComparator; use Symfony\Component\Finder\Comparator\NumberComparator; use Symfony\Component\Finder\Exception\ExceptionInterface; use Symfony\Component\Finder\Iterator\CustomFilterIterator; use Symfony\Component\Finder\Iterator\DateRangeFilterIterator; use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator; use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator; use Symfony\Component\Finder\Iterator\FilecontentFilterIterator; use Symfony\Component\Finder\Iterator\FilenameFilterIterator; use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator; use Symfony\Component\Finder\Iterator\SortableIterator; /** * Finder allows to build rules to find files and directories. * * It is a thin wrapper around several specialized iterator classes. * * All rules may be invoked several times. * * All methods return the current Finder object to allow easy chaining: * * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); * * @author Fabien Potencier * * @api */ class Finder implements \IteratorAggregate, \Countable { const IGNORE_VCS_FILES = 1; const IGNORE_DOT_FILES = 2; private $mode = 0; private $names = array(); private $notNames = array(); private $exclude = array(); private $filters = array(); private $depths = array(); private $sizes = array(); private $followLinks = false; private $sort = false; private $ignore = 0; private $dirs = array(); private $dates = array(); private $iterators = array(); private $contains = array(); private $notContains = array(); private $adapters = array(); private $paths = array(); private $notPaths = array(); private $ignoreUnreadableDirs = false; private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'); /** * Constructor. */ public function __construct() { $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; $this ->addAdapter(new GnuFindAdapter()) ->addAdapter(new BsdFindAdapter()) ->addAdapter(new PhpAdapter(), -50) ->setAdapter('php') ; } /** * Creates a new Finder. * * @return Finder A new Finder instance * * @api */ public static function create() { return new static(); } /** * Registers a finder engine implementation. * * @param AdapterInterface $adapter An adapter instance * @param int $priority Highest is selected first * * @return Finder The current Finder instance */ public function addAdapter(AdapterInterface $adapter, $priority = 0) { $this->adapters[$adapter->getName()] = array( 'adapter' => $adapter, 'priority' => $priority, 'selected' => false, ); return $this->sortAdapters(); } /** * Sets the selected adapter to the best one according to the current platform the code is run on. * * @return Finder The current Finder instance */ public function useBestAdapter() { $this->resetAdapterSelection(); return $this->sortAdapters(); } /** * Selects the adapter to use. * * @param string $name * * @throws \InvalidArgumentException * * @return Finder The current Finder instance */ public function setAdapter($name) { if (!isset($this->adapters[$name])) { throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name)); } $this->resetAdapterSelection(); $this->adapters[$name]['selected'] = true; return $this->sortAdapters(); } /** * Removes all adapters registered in the finder. * * @return Finder The current Finder instance */ public function removeAdapters() { $this->adapters = array(); return $this; } /** * Returns registered adapters ordered by priority without extra information. * * @return AdapterInterface[] */ public function getAdapters() { return array_values(array_map(function (array $adapter) { return $adapter['adapter']; }, $this->adapters)); } /** * Restricts the matching to directories only. * * @return Finder The current Finder instance * * @api */ public function directories() { $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES; return $this; } /** * Restricts the matching to files only. * * @return Finder The current Finder instance * * @api */ public function files() { $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES; return $this; } /** * Adds tests for the directory depth. * * Usage: * * $finder->depth('> 1') // the Finder will start matching at level 1. * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. * * @param int $level The depth level expression * * @return Finder The current Finder instance * * @see DepthRangeFilterIterator * @see NumberComparator * * @api */ public function depth($level) { $this->depths[] = new Comparator\NumberComparator($level); return $this; } /** * Adds tests for file dates (last modified). * * The date must be something that strtotime() is able to parse: * * $finder->date('since yesterday'); * $finder->date('until 2 days ago'); * $finder->date('> now - 2 hours'); * $finder->date('>= 2005-10-15'); * * @param string $date A date range string * * @return Finder The current Finder instance * * @see strtotime * @see DateRangeFilterIterator * @see DateComparator * * @api */ public function date($date) { $this->dates[] = new Comparator\DateComparator($date); return $this; } /** * Adds rules that files must match. * * You can use patterns (delimited with / sign), globs or simple strings. * * $finder->name('*.php') * $finder->name('/\.php$/') // same as above * $finder->name('test.php') * * @param string $pattern A pattern (a regexp, a glob, or a string) * * @return Finder The current Finder instance * * @see FilenameFilterIterator * * @api */ public function name($pattern) { $this->names[] = $pattern; return $this; } /** * Adds rules that files must not match. * * @param string $pattern A pattern (a regexp, a glob, or a string) * * @return Finder The current Finder instance * * @see FilenameFilterIterator * * @api */ public function notName($pattern) { $this->notNames[] = $pattern; return $this; } /** * Adds tests that file contents must match. * * Strings or PCRE patterns can be used: * * $finder->contains('Lorem ipsum') * $finder->contains('/Lorem ipsum/i') * * @param string $pattern A pattern (string or regexp) * * @return Finder The current Finder instance * * @see FilecontentFilterIterator */ public function contains($pattern) { $this->contains[] = $pattern; return $this; } /** * Adds tests that file contents must not match. * * Strings or PCRE patterns can be used: * * $finder->notContains('Lorem ipsum') * $finder->notContains('/Lorem ipsum/i') * * @param string $pattern A pattern (string or regexp) * * @return Finder The current Finder instance * * @see FilecontentFilterIterator */ public function notContains($pattern) { $this->notContains[] = $pattern; return $this; } /** * Adds rules that filenames must match. * * You can use patterns (delimited with / sign) or simple strings. * * $finder->path('some/special/dir') * $finder->path('/some\/special\/dir/') // same as above * * Use only / as dirname separator. * * @param string $pattern A pattern (a regexp or a string) * * @return Finder The current Finder instance * * @see FilenameFilterIterator */ public function path($pattern) { $this->paths[] = $pattern; return $this; } /** * Adds rules that filenames must not match. * * You can use patterns (delimited with / sign) or simple strings. * * $finder->notPath('some/special/dir') * $finder->notPath('/some\/special\/dir/') // same as above * * Use only / as dirname separator. * * @param string $pattern A pattern (a regexp or a string) * * @return Finder The current Finder instance * * @see FilenameFilterIterator */ public function notPath($pattern) { $this->notPaths[] = $pattern; return $this; } /** * Adds tests for file sizes. * * $finder->size('> 10K'); * $finder->size('<= 1Ki'); * $finder->size(4); * * @param string $size A size range string * * @return Finder The current Finder instance * * @see SizeRangeFilterIterator * @see NumberComparator * * @api */ public function size($size) { $this->sizes[] = new Comparator\NumberComparator($size); return $this; } /** * Excludes directories. * * @param string|array $dirs A directory path or an array of directories * * @return Finder The current Finder instance * * @see ExcludeDirectoryFilterIterator * * @api */ public function exclude($dirs) { $this->exclude = array_merge($this->exclude, (array) $dirs); return $this; } /** * Excludes "hidden" directories and files (starting with a dot). * * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not * * @return Finder The current Finder instance * * @see ExcludeDirectoryFilterIterator * * @api */ public function ignoreDotFiles($ignoreDotFiles) { if ($ignoreDotFiles) { $this->ignore |= static::IGNORE_DOT_FILES; } else { $this->ignore &= ~static::IGNORE_DOT_FILES; } return $this; } /** * Forces the finder to ignore version control directories. * * @param bool $ignoreVCS Whether to exclude VCS files or not * * @return Finder The current Finder instance * * @see ExcludeDirectoryFilterIterator * * @api */ public function ignoreVCS($ignoreVCS) { if ($ignoreVCS) { $this->ignore |= static::IGNORE_VCS_FILES; } else { $this->ignore &= ~static::IGNORE_VCS_FILES; } return $this; } /** * Adds VCS patterns. * * @see ignoreVCS() * * @param string|string[] $pattern VCS patterns to ignore */ public static function addVCSPattern($pattern) { foreach ((array) $pattern as $p) { self::$vcsPatterns[] = $p; } self::$vcsPatterns = array_unique(self::$vcsPatterns); } /** * Sorts files and directories by an anonymous function. * * The anonymous function receives two \SplFileInfo instances to compare. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @param \Closure $closure An anonymous function * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sort(\Closure $closure) { $this->sort = $closure; return $this; } /** * Sorts files and directories by name. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sortByName() { $this->sort = Iterator\SortableIterator::SORT_BY_NAME; return $this; } /** * Sorts files and directories by type (directories before files), then by name. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sortByType() { $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; return $this; } /** * Sorts files and directories by the last accessed time. * * This is the time that the file was last accessed, read or written to. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sortByAccessedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; return $this; } /** * Sorts files and directories by the last inode changed time. * * This is the time that the inode information was last modified (permissions, owner, group or other metadata). * * On Windows, since inode is not available, changed time is actually the file creation time. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sortByChangedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; return $this; } /** * Sorts files and directories by the last modified time. * * This is the last time the actual contents of the file were last modified. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sortByModifiedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; return $this; } /** * Filters the iterator with an anonymous function. * * The anonymous function receives a \SplFileInfo and must return false * to remove files. * * @param \Closure $closure An anonymous function * * @return Finder The current Finder instance * * @see CustomFilterIterator * * @api */ public function filter(\Closure $closure) { $this->filters[] = $closure; return $this; } /** * Forces the following of symlinks. * * @return Finder The current Finder instance * * @api */ public function followLinks() { $this->followLinks = true; return $this; } /** * Tells finder to ignore unreadable directories. * * By default, scanning unreadable directories content throws an AccessDeniedException. * * @param bool $ignore * * @return Finder The current Finder instance */ public function ignoreUnreadableDirs($ignore = true) { $this->ignoreUnreadableDirs = (bool) $ignore; return $this; } /** * Searches files and directories which match defined rules. * * @param string|array $dirs A directory path or an array of directories * * @return Finder The current Finder instance * * @throws \InvalidArgumentException if one of the directories does not exist * * @api */ public function in($dirs) { $resolvedDirs = array(); foreach ((array) $dirs as $dir) { if (is_dir($dir)) { $resolvedDirs[] = $dir; } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) { $resolvedDirs = array_merge($resolvedDirs, $glob); } else { throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir)); } } $this->dirs = array_merge($this->dirs, $resolvedDirs); return $this; } /** * Returns an Iterator for the current Finder configuration. * * This method implements the IteratorAggregate interface. * * @return \Iterator An iterator * * @throws \LogicException if the in() method has not been called */ public function getIterator() { if (0 === count($this->dirs) && 0 === count($this->iterators)) { throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.'); } if (1 === count($this->dirs) && 0 === count($this->iterators)) { return $this->searchInDirectory($this->dirs[0]); } $iterator = new \AppendIterator(); foreach ($this->dirs as $dir) { $iterator->append($this->searchInDirectory($dir)); } foreach ($this->iterators as $it) { $iterator->append($it); } return $iterator; } /** * Appends an existing set of files/directories to the finder. * * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. * * @param mixed $iterator * * @return Finder The finder * * @throws \InvalidArgumentException When the given argument is not iterable. */ public function append($iterator) { if ($iterator instanceof \IteratorAggregate) { $this->iterators[] = $iterator->getIterator(); } elseif ($iterator instanceof \Iterator) { $this->iterators[] = $iterator; } elseif ($iterator instanceof \Traversable || is_array($iterator)) { $it = new \ArrayIterator(); foreach ($iterator as $file) { $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file)); } $this->iterators[] = $it; } else { throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); } return $this; } /** * Counts all the results collected by the iterators. * * @return int */ public function count() { return iterator_count($this->getIterator()); } /** * @return Finder The current Finder instance */ private function sortAdapters() { uasort($this->adapters, function (array $a, array $b) { if ($a['selected'] || $b['selected']) { return $a['selected'] ? -1 : 1; } return $a['priority'] > $b['priority'] ? -1 : 1; }); return $this; } /** * @param $dir * * @return \Iterator * * @throws \RuntimeException When none of the adapters are supported */ private function searchInDirectory($dir) { if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { $this->exclude = array_merge($this->exclude, self::$vcsPatterns); } if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { $this->notPaths[] = '#(^|/)\..+(/|$)#'; } foreach ($this->adapters as $adapter) { if ($adapter['adapter']->isSupported()) { try { return $this ->buildAdapter($adapter['adapter']) ->searchInDirectory($dir); } catch (ExceptionInterface $e) { } } } throw new \RuntimeException('No supported adapter found.'); } /** * @param AdapterInterface $adapter * * @return AdapterInterface */ private function buildAdapter(AdapterInterface $adapter) { return $adapter ->setFollowLinks($this->followLinks) ->setDepths($this->depths) ->setMode($this->mode) ->setExclude($this->exclude) ->setNames($this->names) ->setNotNames($this->notNames) ->setContains($this->contains) ->setNotContains($this->notContains) ->setSizes($this->sizes) ->setDates($this->dates) ->setFilters($this->filters) ->setSort($this->sort) ->setPath($this->paths) ->setNotPath($this->notPaths) ->ignoreUnreadableDirs($this->ignoreUnreadableDirs); } /** * Unselects all adapters. */ private function resetAdapterSelection() { $this->adapters = array_map(function (array $properties) { $properties['selected'] = false; return $properties; }, $this->adapters); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; /** * Interface for finder engine implementations. * * @author Jean-François Simon */ abstract class AbstractAdapter implements AdapterInterface { protected $followLinks = false; protected $mode = 0; protected $minDepth = 0; protected $maxDepth = PHP_INT_MAX; protected $exclude = array(); protected $names = array(); protected $notNames = array(); protected $contains = array(); protected $notContains = array(); protected $sizes = array(); protected $dates = array(); protected $filters = array(); protected $sort = false; protected $paths = array(); protected $notPaths = array(); protected $ignoreUnreadableDirs = false; private static $areSupported = array(); /** * {@inheritdoc} */ public function isSupported() { $name = $this->getName(); if (!array_key_exists($name, self::$areSupported)) { self::$areSupported[$name] = $this->canBeUsed(); } return self::$areSupported[$name]; } /** * {@inheritdoc} */ public function setFollowLinks($followLinks) { $this->followLinks = $followLinks; return $this; } /** * {@inheritdoc} */ public function setMode($mode) { $this->mode = $mode; return $this; } /** * {@inheritdoc} */ public function setDepths(array $depths) { $this->minDepth = 0; $this->maxDepth = PHP_INT_MAX; foreach ($depths as $comparator) { switch ($comparator->getOperator()) { case '>': $this->minDepth = $comparator->getTarget() + 1; break; case '>=': $this->minDepth = $comparator->getTarget(); break; case '<': $this->maxDepth = $comparator->getTarget() - 1; break; case '<=': $this->maxDepth = $comparator->getTarget(); break; default: $this->minDepth = $this->maxDepth = $comparator->getTarget(); } } return $this; } /** * {@inheritdoc} */ public function setExclude(array $exclude) { $this->exclude = $exclude; return $this; } /** * {@inheritdoc} */ public function setNames(array $names) { $this->names = $names; return $this; } /** * {@inheritdoc} */ public function setNotNames(array $notNames) { $this->notNames = $notNames; return $this; } /** * {@inheritdoc} */ public function setContains(array $contains) { $this->contains = $contains; return $this; } /** * {@inheritdoc} */ public function setNotContains(array $notContains) { $this->notContains = $notContains; return $this; } /** * {@inheritdoc} */ public function setSizes(array $sizes) { $this->sizes = $sizes; return $this; } /** * {@inheritdoc} */ public function setDates(array $dates) { $this->dates = $dates; return $this; } /** * {@inheritdoc} */ public function setFilters(array $filters) { $this->filters = $filters; return $this; } /** * {@inheritdoc} */ public function setSort($sort) { $this->sort = $sort; return $this; } /** * {@inheritdoc} */ public function setPath(array $paths) { $this->paths = $paths; return $this; } /** * {@inheritdoc} */ public function setNotPath(array $notPaths) { $this->notPaths = $notPaths; return $this; } /** * {@inheritdoc} */ public function ignoreUnreadableDirs($ignore = true) { $this->ignoreUnreadableDirs = (bool) $ignore; return $this; } /** * Returns whether the adapter is supported in the current environment. * * This method should be implemented in all adapters. Do not implement * isSupported in the adapters as the generic implementation provides a cache * layer. * * @see isSupported() * * @return bool Whether the adapter is supported */ abstract protected function canBeUsed(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; /** * @author Jean-François Simon */ interface AdapterInterface { /** * @param bool $followLinks * * @return AdapterInterface Current instance */ public function setFollowLinks($followLinks); /** * @param int $mode * * @return AdapterInterface Current instance */ public function setMode($mode); /** * @param array $exclude * * @return AdapterInterface Current instance */ public function setExclude(array $exclude); /** * @param array $depths * * @return AdapterInterface Current instance */ public function setDepths(array $depths); /** * @param array $names * * @return AdapterInterface Current instance */ public function setNames(array $names); /** * @param array $notNames * * @return AdapterInterface Current instance */ public function setNotNames(array $notNames); /** * @param array $contains * * @return AdapterInterface Current instance */ public function setContains(array $contains); /** * @param array $notContains * * @return AdapterInterface Current instance */ public function setNotContains(array $notContains); /** * @param array $sizes * * @return AdapterInterface Current instance */ public function setSizes(array $sizes); /** * @param array $dates * * @return AdapterInterface Current instance */ public function setDates(array $dates); /** * @param array $filters * * @return AdapterInterface Current instance */ public function setFilters(array $filters); /** * @param \Closure|int $sort * * @return AdapterInterface Current instance */ public function setSort($sort); /** * @param array $paths * * @return AdapterInterface Current instance */ public function setPath(array $paths); /** * @param array $notPaths * * @return AdapterInterface Current instance */ public function setNotPath(array $notPaths); /** * @param bool $ignore * * @return AdapterInterface Current instance */ public function ignoreUnreadableDirs($ignore = true); /** * @param string $dir * * @return \Iterator Result iterator */ public function searchInDirectory($dir); /** * Tests adapter support for current platform. * * @return bool */ public function isSupported(); /** * Returns adapter name. * * @return string */ public function getName(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; use Symfony\Component\Finder\Expression\Expression; /** * Shell engine implementation using GNU find command. * * @author Jean-François Simon */ class GnuFindAdapter extends AbstractFindAdapter { /** * {@inheritdoc} */ public function getName() { return 'gnu_find'; } /** * {@inheritdoc} */ protected function buildFormatSorting(Command $command, $sort) { switch ($sort) { case SortableIterator::SORT_BY_NAME: $command->ins('sort')->add('| sort'); return; case SortableIterator::SORT_BY_TYPE: $format = '%y'; break; case SortableIterator::SORT_BY_ACCESSED_TIME: $format = '%A@'; break; case SortableIterator::SORT_BY_CHANGED_TIME: $format = '%C@'; break; case SortableIterator::SORT_BY_MODIFIED_TIME: $format = '%T@'; break; default: throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); } $command ->get('find') ->add('-printf') ->arg($format.' %h/%f\\n') ->add('| sort | cut') ->arg('-d ') ->arg('-f2-') ; } /** * {@inheritdoc} */ protected function canBeUsed() { return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed(); } /** * {@inheritdoc} */ protected function buildFindCommand(Command $command, $dir) { return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended'); } /** * {@inheritdoc} */ protected function buildContentFiltering(Command $command, array $contains, $not = false) { foreach ($contains as $contain) { $expr = Expression::create($contain); // todo: avoid forking process for each $pattern by using multiple -e options $command ->add('| xargs -I{} -r grep -I') ->add($expr->isCaseSensitive() ? null : '-i') ->add($not ? '-L' : '-l') ->add('-Ee')->arg($expr->renderPattern()) ->add('{}') ; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Iterator; /** * PHP finder engine implementation. * * @author Jean-François Simon */ class PhpAdapter extends AbstractAdapter { /** * {@inheritdoc} */ public function searchInDirectory($dir) { $flags = \RecursiveDirectoryIterator::SKIP_DOTS; if ($this->followLinks) { $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; } $iterator = new \RecursiveIteratorIterator( new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs), \RecursiveIteratorIterator::SELF_FIRST ); if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) { $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth); } if ($this->mode) { $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); } if ($this->exclude) { $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); } if ($this->names || $this->notNames) { $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); } if ($this->contains || $this->notContains) { $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); } if ($this->sizes) { $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); } if ($this->dates) { $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); } if ($this->filters) { $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } if ($this->sort) { $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); $iterator = $iteratorAggregate->getIterator(); } if ($this->paths || $this->notPaths) { $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); } return $iterator; } /** * {@inheritdoc} */ public function getName() { return 'php'; } /** * {@inheritdoc} */ protected function canBeUsed() { return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Exception\AccessDeniedException; use Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Expression\Expression; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Comparator\NumberComparator; use Symfony\Component\Finder\Comparator\DateComparator; /** * Shell engine implementation using GNU find command. * * @author Jean-François Simon */ abstract class AbstractFindAdapter extends AbstractAdapter { /** * @var Shell */ protected $shell; /** * Constructor. */ public function __construct() { $this->shell = new Shell(); } /** * {@inheritdoc} */ public function searchInDirectory($dir) { // having "/../" in path make find fail $dir = realpath($dir); // searching directories containing or not containing strings leads to no result if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) { return new Iterator\FilePathsIterator(array(), $dir); } $command = Command::create(); $find = $this->buildFindCommand($command, $dir); if ($this->followLinks) { $find->add('-follow'); } $find->add('-mindepth')->add($this->minDepth + 1); if (PHP_INT_MAX !== $this->maxDepth) { $find->add('-maxdepth')->add($this->maxDepth + 1); } if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) { $find->add('-type d'); } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) { $find->add('-type f'); } $this->buildNamesFiltering($find, $this->names); $this->buildNamesFiltering($find, $this->notNames, true); $this->buildPathsFiltering($find, $dir, $this->paths); $this->buildPathsFiltering($find, $dir, $this->notPaths, true); $this->buildSizesFiltering($find, $this->sizes); $this->buildDatesFiltering($find, $this->dates); $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs'); $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut'); if ($useGrep && ($this->contains || $this->notContains)) { $grep = $command->ins('grep'); $this->buildContentFiltering($grep, $this->contains); $this->buildContentFiltering($grep, $this->notContains, true); } if ($useSort) { $this->buildSorting($command, $this->sort); } $command->setErrorHandler( $this->ignoreUnreadableDirs // If directory is unreadable and finder is set to ignore it, `stderr` is ignored. ? function ($stderr) { return; } : function ($stderr) { throw new AccessDeniedException($stderr); } ); $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute()); $iterator = new Iterator\FilePathsIterator($paths, $dir); if ($this->exclude) { $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); } if (!$useGrep && ($this->contains || $this->notContains)) { $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); } if ($this->filters) { $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } if (!$useSort && $this->sort) { $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); $iterator = $iteratorAggregate->getIterator(); } return $iterator; } /** * {@inheritdoc} */ protected function canBeUsed() { return $this->shell->testCommand('find'); } /** * @param Command $command * @param string $dir * * @return Command */ protected function buildFindCommand(Command $command, $dir) { return $command ->ins('find') ->add('find ') ->arg($dir) ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions } /** * @param Command $command * @param string[] $names * @param bool $not */ private function buildNamesFiltering(Command $command, array $names, $not = false) { if (0 === count($names)) { return; } $command->add($not ? '-not' : null)->cmd('('); foreach ($names as $i => $name) { $expr = Expression::create($name); // Find does not support expandable globs ("*.{a,b}" syntax). if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { $expr = Expression::create($expr->getGlob()->toRegex(false)); } // Fixes 'not search' and 'full path matching' regex problems. // - Jokers '.' are replaced by [^/]. // - We add '[^/]*' before and after regex (if no ^|$ flags are present). if ($expr->isRegex()) { $regex = $expr->getRegex(); $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*') ->setStartFlag(false) ->setStartJoker(true) ->replaceJokers('[^/]'); if (!$regex->hasEndFlag() || $regex->hasEndJoker()) { $regex->setEndJoker(false)->append('[^/]*'); } } $command ->add($i > 0 ? '-or' : null) ->add($expr->isRegex() ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') : ($expr->isCaseSensitive() ? '-name' : '-iname') ) ->arg($expr->renderPattern()); } $command->cmd(')'); } /** * @param Command $command * @param string $dir * @param string[] $paths * @param bool $not */ private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false) { if (0 === count($paths)) { return; } $command->add($not ? '-not' : null)->cmd('('); foreach ($paths as $i => $path) { $expr = Expression::create($path); // Find does not support expandable globs ("*.{a,b}" syntax). if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { $expr = Expression::create($expr->getGlob()->toRegex(false)); } // Fixes 'not search' regex problems. if ($expr->isRegex()) { $regex = $expr->getRegex(); $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag()); } else { $expr->prepend('*')->append('*'); } $command ->add($i > 0 ? '-or' : null) ->add($expr->isRegex() ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') : ($expr->isCaseSensitive() ? '-path' : '-ipath') ) ->arg($expr->renderPattern()); } $command->cmd(')'); } /** * @param Command $command * @param NumberComparator[] $sizes */ private function buildSizesFiltering(Command $command, array $sizes) { foreach ($sizes as $i => $size) { $command->add($i > 0 ? '-and' : null); switch ($size->getOperator()) { case '<=': $command->add('-size -'.($size->getTarget() + 1).'c'); break; case '>=': $command->add('-size +'.($size->getTarget() - 1).'c'); break; case '>': $command->add('-size +'.$size->getTarget().'c'); break; case '!=': $command->add('-size -'.$size->getTarget().'c'); $command->add('-size +'.$size->getTarget().'c'); break; case '<': default: $command->add('-size -'.$size->getTarget().'c'); } } } /** * @param Command $command * @param DateComparator[] $dates */ private function buildDatesFiltering(Command $command, array $dates) { foreach ($dates as $i => $date) { $command->add($i > 0 ? '-and' : null); $mins = (int) round((time() - $date->getTarget()) / 60); if (0 > $mins) { // mtime is in the future $command->add(' -mmin -0'); // we will have no result so we don't need to continue return; } switch ($date->getOperator()) { case '<=': $command->add('-mmin +'.($mins - 1)); break; case '>=': $command->add('-mmin -'.($mins + 1)); break; case '>': $command->add('-mmin -'.$mins); break; case '!=': $command->add('-mmin +'.$mins.' -or -mmin -'.$mins); break; case '<': default: $command->add('-mmin +'.$mins); } } } /** * @param Command $command * @param string $sort * * @throws \InvalidArgumentException */ private function buildSorting(Command $command, $sort) { $this->buildFormatSorting($command, $sort); } /** * @param Command $command * @param string $sort */ abstract protected function buildFormatSorting(Command $command, $sort); /** * @param Command $command * @param array $contains * @param bool $not */ abstract protected function buildContentFiltering(Command $command, array $contains, $not = false); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; use Symfony\Component\Finder\Expression\Expression; /** * Shell engine implementation using BSD find command. * * @author Jean-François Simon */ class BsdFindAdapter extends AbstractFindAdapter { /** * {@inheritdoc} */ public function getName() { return 'bsd_find'; } /** * {@inheritdoc} */ protected function canBeUsed() { return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed(); } /** * {@inheritdoc} */ protected function buildFormatSorting(Command $command, $sort) { switch ($sort) { case SortableIterator::SORT_BY_NAME: $command->ins('sort')->add('| sort'); return; case SortableIterator::SORT_BY_TYPE: $format = '%HT'; break; case SortableIterator::SORT_BY_ACCESSED_TIME: $format = '%a'; break; case SortableIterator::SORT_BY_CHANGED_TIME: $format = '%c'; break; case SortableIterator::SORT_BY_MODIFIED_TIME: $format = '%m'; break; default: throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); } $command ->add('-print0 | xargs -0 stat -f') ->arg($format.'%t%N') ->add('| sort | cut -f 2'); } /** * {@inheritdoc} */ protected function buildFindCommand(Command $command, $dir) { parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1); return $command; } /** * {@inheritdoc} */ protected function buildContentFiltering(Command $command, array $contains, $not = false) { foreach ($contains as $contain) { $expr = Expression::create($contain); // todo: avoid forking process for each $pattern by using multiple -e options $command ->add('| grep -v \'^$\'') ->add('| xargs -I{} grep -I') ->add($expr->isCaseSensitive() ? null : '-i') ->add($not ? '-L' : '-l') ->add('-Ee')->arg($expr->renderPattern()) ->add('{}') ; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ class AccessDeniedException extends \UnexpectedValueException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ interface ExceptionInterface { /** * @return \Symfony\Component\Finder\Adapter\AdapterInterface */ public function getAdapter(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ class OperationNotPermitedException extends AdapterFailureException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; use Symfony\Component\Finder\Adapter\AdapterInterface; /** * Base exception for all adapter failures. * * @author Jean-François Simon */ class AdapterFailureException extends \RuntimeException implements ExceptionInterface { /** * @var \Symfony\Component\Finder\Adapter\AdapterInterface */ private $adapter; /** * @param AdapterInterface $adapter * @param string|null $message * @param \Exception|null $previous */ public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null) { $this->adapter = $adapter; parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous); } /** * {@inheritdoc} */ public function getAdapter() { return $this->adapter; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; use Symfony\Component\Finder\Adapter\AdapterInterface; use Symfony\Component\Finder\Shell\Command; /** * @author Jean-François Simon */ class ShellCommandFailureException extends AdapterFailureException { /** * @var Command */ private $command; /** * @param AdapterInterface $adapter * @param Command $command * @param \Exception|null $previous */ public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null) { $this->command = $command; parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous); } /** * @return Command */ public function getCommand() { return $this->command; } } $path) { $loader->set($namespace, $path); } $map = require __DIR__ . '/autoload_psr4.php'; foreach ($map as $namespace => $path) { $loader->setPsr4($namespace, $path); } $classMap = require __DIR__ . '/autoload_classmap.php'; if ($classMap) { $loader->addClassMap($classMap); } $loader->register(true); $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $fileIdentifier => $file) { composerRequireeb98732a8a0d2fa4f661cadff54b9cce($fileIdentifier, $file); } return $loader; } } function composerRequireeb98732a8a0d2fa4f661cadff54b9cce($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { require $file; $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; } } _xpath = $xpath; $this->_matcher = $matcher; } /** * Matches if the XPath matches against the DOM node and the matcher. * * @param string|\DOMNode $actual * @param Description $mismatchDescription * @return bool */ protected function matchesWithDiagnosticDescription($actual, Description $mismatchDescription) { if (is_string($actual)) { $actual = $this->createDocument($actual); } elseif (!$actual instanceof \DOMNode) { $mismatchDescription->appendText('was ')->appendValue($actual); return false; } $result = $this->evaluate($actual); if ($result instanceof \DOMNodeList) { return $this->matchesContent($result, $mismatchDescription); } else { return $this->matchesExpression($result, $mismatchDescription); } } /** * Creates and returns a DOMDocument from the given * XML or HTML string. * * @param string $text * @return \DOMDocument built from $text * @throws \InvalidArgumentException if the document is not valid */ protected function createDocument($text) { $document = new \DOMDocument(); if (preg_match('/^\s*<\?xml/', $text)) { if (!@$document->loadXML($text)) { throw new \InvalidArgumentException('Must pass a valid XML document'); } } else { if (!@$document->loadHTML($text)) { throw new \InvalidArgumentException('Must pass a valid HTML or XHTML document'); } } return $document; } /** * Applies the configured XPath to the DOM node and returns either * the result if it's an expression or the node list if it's a query. * * @param \DOMNode $node context from which to issue query * @return mixed result of expression or DOMNodeList from query */ protected function evaluate(\DOMNode $node) { if ($node instanceof \DOMDocument) { $xpathDocument = new \DOMXPath($node); return $xpathDocument->evaluate($this->_xpath); } else { $xpathDocument = new \DOMXPath($node->ownerDocument); return $xpathDocument->evaluate($this->_xpath, $node); } } /** * Matches if the list of nodes is not empty and the content of at least * one node matches the configured matcher, if supplied. * * @param \DOMNodeList $nodes selected by the XPath query * @param Description $mismatchDescription * @return bool */ protected function matchesContent(\DOMNodeList $nodes, Description $mismatchDescription) { if ($nodes->length == 0) { $mismatchDescription->appendText('XPath returned no results'); } elseif ($this->_matcher === null) { return true; } else { foreach ($nodes as $node) { if ($this->_matcher->matches($node->textContent)) { return true; } } $content = array(); foreach ($nodes as $node) { $content[] = $node->textContent; } $mismatchDescription->appendText('XPath returned ') ->appendValue($content); } return false; } /** * Matches if the result of the XPath expression matches the configured * matcher or evaluates to true if there is none. * * @param mixed $result result of the XPath expression * @param Description $mismatchDescription * @return bool */ protected function matchesExpression($result, Description $mismatchDescription) { if ($this->_matcher === null) { if ($result) { return true; } $mismatchDescription->appendText('XPath expression result was ') ->appendValue($result); } else { if ($this->_matcher->matches($result)) { return true; } $mismatchDescription->appendText('XPath expression result '); $this->_matcher->describeMismatch($result, $mismatchDescription); } return false; } public function describeTo(Description $description) { $description->appendText('XML or HTML document with XPath "') ->appendText($this->_xpath) ->appendText('"'); if ($this->_matcher !== null) { $description->appendText(' '); $this->_matcher->describeTo($description); } } /** * Wraps $matcher with {@link Hamcrest\Core\IsEqual) * if it's not a matcher and the XPath in count() * if it's an integer. * * @factory */ public static function hasXPath($xpath, $matcher = null) { if ($matcher === null || $matcher instanceof Matcher) { return new self($xpath, $matcher); } elseif (is_int($matcher) && strpos($xpath, 'count(') !== 0) { $xpath = 'count(' . $xpath . ')'; } return new self($xpath, IsEqual::equalTo($matcher)); } } _substring)) === $this->_substring); } protected function relationship() { return 'starting with'; } } _substring = $substring; } protected function matchesSafely($item) { return $this->evalSubstringOf($item); } protected function describeMismatchSafely($item, Description $mismatchDescription) { $mismatchDescription->appendText('was "')->appendText($item)->appendText('"'); } public function describeTo(Description $description) { $description->appendText('a string ') ->appendText($this->relationship()) ->appendText(' ') ->appendValue($this->_substring) ; } abstract protected function evalSubstringOf($string); abstract protected function relationship(); } _string = $string; } protected function matchesSafely($item) { return strtolower($this->_string) === strtolower($item); } protected function describeMismatchSafely($item, Description $mismatchDescription) { $mismatchDescription->appendText('was ')->appendText($item); } public function describeTo(Description $description) { $description->appendText('equalToIgnoringCase(') ->appendValue($this->_string) ->appendText(')') ; } /** * Matches if value is a string equal to $string, regardless of the case. * * @factory */ public static function equalToIgnoringCase($string) { return new self($string); } } _empty = $empty; } public function matches($item) { return $this->_empty ? ($item === '') : is_string($item) && $item !== ''; } public function describeTo(Description $description) { $description->appendText($this->_empty ? 'an empty string' : 'a non-empty string'); } /** * Matches if value is a zero-length string. * * @factory emptyString */ public static function isEmptyString() { if (!self::$_INSTANCE) { self::$_INSTANCE = new self(true); } return self::$_INSTANCE; } /** * Matches if value is null or a zero-length string. * * @factory nullOrEmptyString */ public static function isEmptyOrNullString() { if (!self::$_NULL_OR_EMPTY_INSTANCE) { self::$_NULL_OR_EMPTY_INSTANCE = AnyOf::anyOf( IsNull::nullvalue(), self::isEmptyString() ); } return self::$_NULL_OR_EMPTY_INSTANCE; } /** * Matches if value is a non-zero-length string. * * @factory nonEmptyString */ public static function isNonEmptyString() { if (!self::$_NOT_INSTANCE) { self::$_NOT_INSTANCE = new self(false); } return self::$_NOT_INSTANCE; } } _substring, (string) $item) >= 1; } protected function relationship() { return 'matching'; } } _substrings = $substrings; } protected function matchesSafely($item) { $fromIndex = 0; foreach ($this->_substrings as $substring) { if (false === $fromIndex = strpos($item, $substring, $fromIndex)) { return false; } } return true; } protected function describeMismatchSafely($item, Description $mismatchDescription) { $mismatchDescription->appendText('was ')->appendText($item); } public function describeTo(Description $description) { $description->appendText('a string containing ') ->appendValueList('', ', ', '', $this->_substrings) ->appendText(' in order') ; } /** * Matches if value contains $substrings in a constrained order. * * @factory ... */ public static function stringContainsInOrder(/* args... */) { $args = func_get_args(); if (isset($args[0]) && is_array($args[0])) { $args = $args[0]; } return new self($args); } } _substring)); } protected function relationship() { return 'containing in any case'; } } _substring); } /** * Matches if value is a string that contains $substring. * * @factory */ public static function containsString($substring) { return new self($substring); } // -- Protected Methods protected function evalSubstringOf($item) { return (false !== strpos((string) $item, $this->_substring)); } protected function relationship() { return 'containing'; } } _string = $string; } protected function matchesSafely($item) { return (strtolower($this->_stripSpace($item)) === strtolower($this->_stripSpace($this->_string))); } protected function describeMismatchSafely($item, Description $mismatchDescription) { $mismatchDescription->appendText('was ')->appendText($item); } public function describeTo(Description $description) { $description->appendText('equalToIgnoringWhiteSpace(') ->appendValue($this->_string) ->appendText(')') ; } /** * Matches if value is a string equal to $string, regardless of whitespace. * * @factory */ public static function equalToIgnoringWhiteSpace($string) { return new self($string); } // -- Private Methods private function _stripSpace($string) { $parts = preg_split("/[\r\n\t ]+/", $string); foreach ($parts as $i => $part) { $parts[$i] = trim($part, " \r\n\t"); } return trim(implode(' ', $parts), " \r\n\t"); } } _substring))) === $this->_substring); } protected function relationship() { return 'ending with'; } } * Matcher implementations should NOT directly implement this interface. * Instead, extend the {@link Hamcrest\BaseMatcher} abstract class, * which will ensure that the Matcher API can grow to support * new features and remain compatible with all Matcher implementations. *

* For easy access to common Matcher implementations, use the static factory * methods in {@link Hamcrest\CoreMatchers}. * * @see Hamcrest\CoreMatchers * @see Hamcrest\BaseMatcher */ interface Matcher extends SelfDescribing { /** * Evaluates the matcher for argument $item. * * @param mixed $item the object against which the matcher is evaluated. * * @return boolean true if $item matches, * otherwise false. * * @see Hamcrest\BaseMatcher */ public function matches($item); /** * Generate a description of why the matcher has not accepted the item. * The description will be part of a larger description of why a matching * failed, so it should be concise. * This method assumes that matches($item) is false, but * will not check this. * * @param mixed $item The item that the Matcher has rejected. * @param Description $description * @return */ public function describeMismatch($item, Description $description); } * // With an identifier * assertThat("apple flavour", $apple->flavour(), equalTo("tasty")); * // Without an identifier * assertThat($apple->flavour(), equalTo("tasty")); * // Evaluating a boolean expression * assertThat("some error", $a > $b); * assertThat($a > $b); * */ public static function assertThat(/* $args ... */) { $args = func_get_args(); switch (count($args)) { case 1: self::$_count++; if (!$args[0]) { throw new AssertionError(); } break; case 2: self::$_count++; if ($args[1] instanceof Matcher) { self::doAssert('', $args[0], $args[1]); } elseif (!$args[1]) { throw new AssertionError($args[0]); } break; case 3: self::$_count++; self::doAssert( $args[0], $args[1], Util::wrapValueWithIsEqual($args[2]) ); break; default: throw new \InvalidArgumentException('assertThat() requires one to three arguments'); } } /** * Returns the number of assertions performed. * * @return int */ public static function getCount() { return self::$_count; } /** * Resets the number of assertions performed to zero. */ public static function resetCount() { self::$_count = 0; } /** * Performs the actual assertion logic. * * If $matcher doesn't match $actual, * throws a {@link Hamcrest\AssertionError} with a description * of the failure along with the optional $identifier. * * @param string $identifier added to the message upon failure * @param mixed $actual value to compare against $matcher * @param \Hamcrest\Matcher $matcher applied to $actual * @throws AssertionError */ private static function doAssert($identifier, $actual, Matcher $matcher) { if (!$matcher->matches($actual)) { $description = new StringDescription(); if (!empty($identifier)) { $description->appendText($identifier . PHP_EOL); } $description->appendText('Expected: ') ->appendDescriptionOf($matcher) ->appendText(PHP_EOL . ' but: '); $matcher->describeMismatch($actual, $description); throw new AssertionError((string) $description); } } } _empty = $empty; } public function matches($item) { if (!$item instanceof \Traversable) { return false; } foreach ($item as $value) { return !$this->_empty; } return $this->_empty; } public function describeTo(Description $description) { $description->appendText($this->_empty ? 'an empty traversable' : 'a non-empty traversable'); } /** * Returns true if traversable is empty. * * @factory */ public static function emptyTraversable() { if (!self::$_INSTANCE) { self::$_INSTANCE = new self; } return self::$_INSTANCE; } /** * Returns true if traversable is not empty. * * @factory */ public static function nonEmptyTraversable() { if (!self::$_NOT_INSTANCE) { self::$_NOT_INSTANCE = new self(false); } return self::$_NOT_INSTANCE; } } append($text); return $this; } public function appendDescriptionOf(SelfDescribing $value) { $value->describeTo($this); return $this; } public function appendValue($value) { if (is_null($value)) { $this->append('null'); } elseif (is_string($value)) { $this->_toPhpSyntax($value); } elseif (is_float($value)) { $this->append('<'); $this->append($value); $this->append('F>'); } elseif (is_bool($value)) { $this->append('<'); $this->append($value ? 'true' : 'false'); $this->append('>'); } elseif (is_array($value) || $value instanceof \Iterator || $value instanceof \IteratorAggregate) { $this->appendValueList('[', ', ', ']', $value); } elseif (is_object($value) && !method_exists($value, '__toString')) { $this->append('<'); $this->append(get_class($value)); $this->append('>'); } else { $this->append('<'); $this->append($value); $this->append('>'); } return $this; } public function appendValueList($start, $separator, $end, $values) { $list = array(); foreach ($values as $v) { $list[] = new SelfDescribingValue($v); } $this->appendList($start, $separator, $end, $list); return $this; } public function appendList($start, $separator, $end, $values) { $this->append($start); $separate = false; foreach ($values as $value) { /*if (!($value instanceof Hamcrest\SelfDescribing)) { $value = new Hamcrest\Internal\SelfDescribingValue($value); }*/ if ($separate) { $this->append($separator); } $this->appendDescriptionOf($value); $separate = true; } $this->append($end); return $this; } // -- Protected Methods /** * Append the String $str to the description. */ abstract protected function append($str); // -- Private Methods private function _toPhpSyntax($value) { $str = '"'; for ($i = 0, $len = strlen($value); $i < $len; ++$i) { switch ($value[$i]) { case '"': $str .= '\\"'; break; case "\t": $str .= '\\t'; break; case "\r": $str .= '\\r'; break; case "\n": $str .= '\\n'; break; default: $str .= $value[$i]; } } $str .= '"'; $this->append($str); } } _value = $value; } public function describeTo(Description $description) { $description->appendValue($this->_value); } } * assertThat(array('a', 'b'), set('b')); * assertThat($foo, set('bar')); * assertThat('Server', notSet('defaultPort')); * * * @todo Replace $property with a matcher and iterate all property names. */ class Set extends BaseMatcher { private $_property; private $_not; public function __construct($property, $not = false) { $this->_property = $property; $this->_not = $not; } public function matches($item) { if ($item === null) { return false; } $property = $this->_property; if (is_array($item)) { $result = isset($item[$property]); } elseif (is_object($item)) { $result = isset($item->$property); } elseif (is_string($item)) { $result = isset($item::$$property); } else { throw new \InvalidArgumentException('Must pass an object, array, or class name'); } return $this->_not ? !$result : $result; } public function describeTo(Description $description) { $description->appendText($this->_not ? 'unset property ' : 'set property ')->appendText($this->_property); } public function describeMismatch($item, Description $description) { $value = ''; if (!$this->_not) { $description->appendText('was not set'); } else { $property = $this->_property; if (is_array($item)) { $value = $item[$property]; } elseif (is_object($item)) { $value = $item->$property; } elseif (is_string($item)) { $value = $item::$$property; } parent::describeMismatch($value, $description); } } /** * Matches if value (class, object, or array) has named $property. * * @factory */ public static function set($property) { return new self($property); } /** * Matches if value (class, object, or array) does not have named $property. * * @factory */ public static function notSet($property) { return new self($property, true); } } _object = $object; } public function matches($object) { return ($object === $this->_object) && ($this->_object === $object); } public function describeTo(Description $description) { $description->appendText('sameInstance(') ->appendValue($this->_object) ->appendText(')') ; } /** * Creates a new instance of IsSame. * * @param mixed $object * The predicate evaluates to true only when the argument is * this object. * * @return \Hamcrest\Core\IsSame * @factory */ public static function sameInstance($object) { return new self($object); } } toString(); } return (string) $actual; } /** * Does array size satisfy a given matcher? * * @factory */ public static function hasToString($matcher) { return new self(Util::wrapValueWithIsEqual($matcher)); } } _theClass = $theClass; } protected function matchesWithDiagnosticDescription($item, Description $mismatchDescription) { if (!is_object($item)) { $mismatchDescription->appendText('was ')->appendValue($item); return false; } if (!($item instanceof $this->_theClass)) { $mismatchDescription->appendText('[' . get_class($item) . '] ') ->appendValue($item); return false; } return true; } public function describeTo(Description $description) { $description->appendText('an instance of ') ->appendText($this->_theClass) ; } /** * Is the value an instance of a particular type? * This version assumes no relationship between the required type and * the signature of the method that sets it up, for example in * assertThat($anObject, anInstanceOf('Thing')); * * @factory any */ public static function anInstanceOf($theClass) { return new self($theClass); } } _item = $item; } public function matches($arg) { return (($arg == $this->_item) && ($this->_item == $arg)); } public function describeTo(Description $description) { $description->appendValue($this->_item); } /** * Is the value equal to another value, as tested by the use of the "==" * comparison operator? * * @factory */ public static function equalTo($item) { return new self($item); } } _matcher = $matcher; } public function matches($arg) { return !$this->_matcher->matches($arg); } public function describeTo(Description $description) { $description->appendText('not ')->appendDescriptionOf($this->_matcher); } /** * Matches if value does not match $value. * * @factory */ public static function not($value) { return new self(Util::wrapValueWithIsEqual($value)); } } _descriptionTemplate = $descriptionTemplate; $this->_matcher = $matcher; $this->_values = $values; } public function matches($item) { return $this->_matcher->matches($item); } public function describeTo(Description $description) { $textStart = 0; while (preg_match(self::ARG_PATTERN, $this->_descriptionTemplate, $matches, PREG_OFFSET_CAPTURE, $textStart)) { $text = $matches[0][0]; $index = $matches[1][0]; $offset = $matches[0][1]; $description->appendText(substr($this->_descriptionTemplate, $textStart, $offset - $textStart)); $description->appendValue($this->_values[$index]); $textStart = $offset + strlen($text); } if ($textStart < strlen($this->_descriptionTemplate)) { $description->appendText(substr($this->_descriptionTemplate, $textStart)); } } /** * Wraps an existing matcher and overrides the description when it fails. * * @factory ... */ public static function describedAs(/* $description, Hamcrest\Matcher $matcher, $values... */) { $args = func_get_args(); $description = array_shift($args); $matcher = array_shift($args); $values = $args; return new self($description, $matcher, $values); } } _elementMatcher = $elementMatcher; } protected function matchesSafely($items) { foreach ($items as $item) { if ($this->_elementMatcher->matches($item)) { return true; } } return false; } protected function describeMismatchSafely($items, Description $mismatchDescription) { $mismatchDescription->appendText('was ')->appendValue($items); } public function describeTo(Description $description) { $description ->appendText('a collection containing ') ->appendDescriptionOf($this->_elementMatcher) ; } /** * Test if the value is an array containing this matcher. * * Example: *

     * assertThat(array('a', 'b'), hasItem(equalTo('b')));
     * //Convenience defaults to equalTo()
     * assertThat(array('a', 'b'), hasItem('b'));
     * 
* * @factory ... */ public static function hasItem() { $args = func_get_args(); $firstArg = array_shift($args); return new self(Util::wrapValueWithIsEqual($firstArg)); } /** * Test if the value is an array containing elements that match all of these * matchers. * * Example: *
     * assertThat(array('a', 'b', 'c'), hasItems(equalTo('a'), equalTo('b')));
     * 
* * @factory ... */ public static function hasItems(/* args... */) { $args = func_get_args(); $matchers = array(); foreach ($args as $arg) { $matchers[] = self::hasItem($arg); } return AllOf::allOf($matchers); } } _matcher = $matcher; } protected function matchesSafelyWithDiagnosticDescription($items, Description $mismatchDescription) { foreach ($items as $item) { if (!$this->_matcher->matches($item)) { $mismatchDescription->appendText('an item '); $this->_matcher->describeMismatch($item, $mismatchDescription); return false; } } return true; } public function describeTo(Description $description) { $description->appendText('every item is ')->appendDescriptionOf($this->_matcher); } /** * @param Matcher $itemMatcher * A matcher to apply to every element in an array. * * @return \Hamcrest\Core\Every * Evaluates to TRUE for a collection in which every item matches $itemMatcher * * @factory */ public static function everyItem(Matcher $itemMatcher) { return new self($itemMatcher); } } _value = $value; } public function describeTo(Description $description) { $description->appendValue($this->_value); } /** * Tests of the value is identical to $value as tested by the "===" operator. * * @factory */ public static function identicalTo($value) { return new self($value); } } */ private $_matchers; public function __construct(array $matchers) { Util::checkAllAreMatchers($matchers); $this->_matchers = $matchers; } protected function matchesWithShortcut($item, $shortcut) { /** @var $matcher \Hamcrest\Matcher */ foreach ($this->_matchers as $matcher) { if ($matcher->matches($item) == $shortcut) { return $shortcut; } } return !$shortcut; } public function describeToWithOperator(Description $description, $operator) { $description->appendList('(', ' ' . $operator . ' ', ')', $this->_matchers); } } true. */ class IsAnything extends BaseMatcher { private $_message; public function __construct($message = 'ANYTHING') { $this->_message = $message; } public function matches($item) { return true; } public function describeTo(Description $description) { $description->appendText($this->_message); } /** * This matcher always evaluates to true. * * @param string $description A meaningful string used when describing itself. * * @return \Hamcrest\Core\IsAnything * @factory */ public static function anything($description = 'ANYTHING') { return new self($description); } } _matcher = $matcher; } public function matches($arg) { return $this->_matcher->matches($arg); } public function describeTo(Description $description) { $description->appendText('is ')->appendDescriptionOf($this->_matcher); } public function describeMismatch($item, Description $mismatchDescription) { $this->_matcher->describeMismatch($item, $mismatchDescription); } /** * Decorates another Matcher, retaining the behavior but allowing tests * to be slightly more expressive. * * For example: assertThat($cheese, equalTo($smelly)) * vs. assertThat($cheese, is(equalTo($smelly))) * * @factory */ public static function is($value) { return new self(Util::wrapValueWithIsEqual($value)); } } appendText('null'); } /** * Matches if value is null. * * @factory */ public static function nullValue() { if (!self::$_INSTANCE) { self::$_INSTANCE = new self(); } return self::$_INSTANCE; } /** * Matches if value is not null. * * @factory */ public static function notNullValue() { if (!self::$_NOT_INSTANCE) { self::$_NOT_INSTANCE = IsNot::not(self::nullValue()); } return self::$_NOT_INSTANCE; } } _matcher = $matcher; } public function matches($item) { return $this->_matcher->matches($item); } public function describeTo(Description $description) { $description->appendDescriptionOf($this->_matcher); } /** Diversion from Hamcrest-Java... Logical "and" not permitted */ public function andAlso(Matcher $other) { return new self(new AllOf($this->_templatedListWith($other))); } /** Diversion from Hamcrest-Java... Logical "or" not permitted */ public function orElse(Matcher $other) { return new self(new AnyOf($this->_templatedListWith($other))); } /** * This is useful for fluently combining matchers that must both pass. * For example: *
     *   assertThat($string, both(containsString("a"))->andAlso(containsString("b")));
     * 
* * @factory */ public static function both(Matcher $matcher) { return new self($matcher); } /** * This is useful for fluently combining matchers where either may pass, * for example: *
     *   assertThat($string, either(containsString("a"))->orElse(containsString("b")));
     * 
* * @factory */ public static function either(Matcher $matcher) { return new self($matcher); } // -- Private Methods private function _templatedListWith(Matcher $other) { return array($this->_matcher, $other); } } true. */ class AnyOf extends ShortcutCombination { public function __construct(array $matchers) { parent::__construct($matchers); } public function matches($item) { return $this->matchesWithShortcut($item, true); } public function describeTo(Description $description) { $this->describeToWithOperator($description, 'or'); } /** * Evaluates to true if ANY of the passed in matchers evaluate to true. * * @factory ... */ public static function anyOf(/* args... */) { $args = func_get_args(); return new self(Util::createMatcherArray($args)); } /** * Evaluates to false if ANY of the passed in matchers evaluate to true. * * @factory ... */ public static function noneOf(/* args... */) { $args = func_get_args(); return IsNot::not( new self(Util::createMatcherArray($args)) ); } } false. */ class AllOf extends DiagnosingMatcher { private $_matchers; public function __construct(array $matchers) { Util::checkAllAreMatchers($matchers); $this->_matchers = $matchers; } public function matchesWithDiagnosticDescription($item, Description $mismatchDescription) { /** @var $matcher \Hamcrest\Matcher */ foreach ($this->_matchers as $matcher) { if (!$matcher->matches($item)) { $mismatchDescription->appendDescriptionOf($matcher)->appendText(' '); $matcher->describeMismatch($item, $mismatchDescription); return false; } } return true; } public function describeTo(Description $description) { $description->appendList('(', ' and ', ')', $this->_matchers); } /** * Evaluates to true only if ALL of the passed in matchers evaluate to true. * * @factory ... */ public static function allOf(/* args... */) { $args = func_get_args(); return new self(Util::createMatcherArray($args)); } } _theType = strtolower($theType); } public function matches($item) { return strtolower(gettype($item)) == $this->_theType; } public function describeTo(Description $description) { $description->appendText(self::getTypeDescription($this->_theType)); } public function describeMismatch($item, Description $description) { if ($item === null) { $description->appendText('was null'); } else { $description->appendText('was ') ->appendText(self::getTypeDescription(strtolower(gettype($item)))) ->appendText(' ') ->appendValue($item) ; } } public static function getTypeDescription($type) { if ($type == 'null') { return 'null'; } return (strpos('aeiou', substr($type, 0, 1)) === false ? 'a ' : 'an ') . $type; } /** * Is the value a particular built-in type? * * @factory */ public static function typeOf($theType) { return new self($theType); } } matchesWithDiagnosticDescription($item, new NullDescription()); } public function describeMismatch($item, Description $mismatchDescription) { $this->matchesWithDiagnosticDescription($item, $mismatchDescription); } abstract protected function matchesWithDiagnosticDescription($item, Description $mismatchDescription); } appendText('was ')->appendValue($item); } public function __toString() { return StringDescription::toString($this); } } _expectedType = $expectedType; $this->_expectedSubtype = $expectedSubtype; } final public function matches($item) { return $this->_isSafeType($item) && $this->matchesSafely($item); } final public function describeMismatch($item, Description $mismatchDescription) { if (!$this->_isSafeType($item)) { parent::describeMismatch($item, $mismatchDescription); } else { $this->describeMismatchSafely($item, $mismatchDescription); } } // -- Protected Methods /** * The item will already have been checked for the specific type and subtype. */ abstract protected function matchesSafely($item); /** * The item will already have been checked for the specific type and subtype. */ abstract protected function describeMismatchSafely($item, Description $mismatchDescription); // -- Private Methods private function _isSafeType($value) { switch ($this->_expectedType) { case self::TYPE_ANY: return true; case self::TYPE_STRING: return is_string($value) || is_numeric($value); case self::TYPE_NUMERIC: return is_numeric($value) || is_string($value); case self::TYPE_ARRAY: return is_array($value); case self::TYPE_OBJECT: return is_object($value) && ($this->_expectedSubtype === null || $value instanceof $this->_expectedSubtype); case self::TYPE_RESOURCE: return is_resource($value) && ($this->_expectedSubtype === null || get_resource_type($value) == $this->_expectedSubtype); case self::TYPE_BOOLEAN: return true; default: return true; } } } _out = (string) $out; } public function __toString() { return $this->_out; } /** * Return the description of a {@link Hamcrest\SelfDescribing} object as a * String. * * @param \Hamcrest\SelfDescribing $selfDescribing * The object to be described. * * @return string * The description of the object. */ public static function toString(SelfDescribing $selfDescribing) { $self = new self(); return (string) $self->appendDescriptionOf($selfDescribing); } /** * Alias for {@link toString()}. */ public static function asString(SelfDescribing $selfDescribing) { return self::toString($selfDescribing); } // -- Protected Methods protected function append($str) { $this->_out .= $str; } } featureValueOf() in a subclass to pull out the feature to be * matched against. */ abstract class FeatureMatcher extends TypeSafeDiagnosingMatcher { private $_subMatcher; private $_featureDescription; private $_featureName; /** * Constructor. * * @param string $type * @param string $subtype * @param \Hamcrest\Matcher $subMatcher The matcher to apply to the feature * @param string $featureDescription Descriptive text to use in describeTo * @param string $featureName Identifying text for mismatch message */ public function __construct($type, $subtype, Matcher $subMatcher, $featureDescription, $featureName) { parent::__construct($type, $subtype); $this->_subMatcher = $subMatcher; $this->_featureDescription = $featureDescription; $this->_featureName = $featureName; } /** * Implement this to extract the interesting feature. * * @param mixed $actual the target object * * @return mixed the feature to be matched */ abstract protected function featureValueOf($actual); public function matchesSafelyWithDiagnosticDescription($actual, Description $mismatchDescription) { $featureValue = $this->featureValueOf($actual); if (!$this->_subMatcher->matches($featureValue)) { $mismatchDescription->appendText($this->_featureName) ->appendText(' was ')->appendValue($featureValue); return false; } return true; } final public function describeTo(Description $description) { $description->appendText($this->_featureDescription)->appendText(' ') ->appendDescriptionOf($this->_subMatcher) ; } } * assertThat($string, both(containsString("a"))->andAlso(containsString("b"))); * */ public static function both(\Hamcrest\Matcher $matcher) { return \Hamcrest\Core\CombinableMatcher::both($matcher); } /** * This is useful for fluently combining matchers where either may pass, * for example: *
     *   assertThat($string, either(containsString("a"))->orElse(containsString("b")));
     * 
*/ public static function either(\Hamcrest\Matcher $matcher) { return \Hamcrest\Core\CombinableMatcher::either($matcher); } /** * Wraps an existing matcher and overrides the description when it fails. */ public static function describedAs(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Core\DescribedAs', 'describedAs'), $args); } /** * @param Matcher $itemMatcher * A matcher to apply to every element in an array. * * @return \Hamcrest\Core\Every * Evaluates to TRUE for a collection in which every item matches $itemMatcher */ public static function everyItem(\Hamcrest\Matcher $itemMatcher) { return \Hamcrest\Core\Every::everyItem($itemMatcher); } /** * Does array size satisfy a given matcher? */ public static function hasToString($matcher) { return \Hamcrest\Core\HasToString::hasToString($matcher); } /** * Decorates another Matcher, retaining the behavior but allowing tests * to be slightly more expressive. * * For example: assertThat($cheese, equalTo($smelly)) * vs. assertThat($cheese, is(equalTo($smelly))) */ public static function is($value) { return \Hamcrest\Core\Is::is($value); } /** * This matcher always evaluates to true. * * @param string $description A meaningful string used when describing itself. * * @return \Hamcrest\Core\IsAnything */ public static function anything($description = 'ANYTHING') { return \Hamcrest\Core\IsAnything::anything($description); } /** * Test if the value is an array containing this matcher. * * Example: *
     * assertThat(array('a', 'b'), hasItem(equalTo('b')));
     * //Convenience defaults to equalTo()
     * assertThat(array('a', 'b'), hasItem('b'));
     * 
*/ public static function hasItem(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItem'), $args); } /** * Test if the value is an array containing elements that match all of these * matchers. * * Example: *
     * assertThat(array('a', 'b', 'c'), hasItems(equalTo('a'), equalTo('b')));
     * 
*/ public static function hasItems(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItems'), $args); } /** * Is the value equal to another value, as tested by the use of the "==" * comparison operator? */ public static function equalTo($item) { return \Hamcrest\Core\IsEqual::equalTo($item); } /** * Tests of the value is identical to $value as tested by the "===" operator. */ public static function identicalTo($value) { return \Hamcrest\Core\IsIdentical::identicalTo($value); } /** * Is the value an instance of a particular type? * This version assumes no relationship between the required type and * the signature of the method that sets it up, for example in * assertThat($anObject, anInstanceOf('Thing')); */ public static function anInstanceOf($theClass) { return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); } /** * Is the value an instance of a particular type? * This version assumes no relationship between the required type and * the signature of the method that sets it up, for example in * assertThat($anObject, anInstanceOf('Thing')); */ public static function any($theClass) { return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); } /** * Matches if value does not match $value. */ public static function not($value) { return \Hamcrest\Core\IsNot::not($value); } /** * Matches if value is null. */ public static function nullValue() { return \Hamcrest\Core\IsNull::nullValue(); } /** * Matches if value is not null. */ public static function notNullValue() { return \Hamcrest\Core\IsNull::notNullValue(); } /** * Creates a new instance of IsSame. * * @param mixed $object * The predicate evaluates to true only when the argument is * this object. * * @return \Hamcrest\Core\IsSame */ public static function sameInstance($object) { return \Hamcrest\Core\IsSame::sameInstance($object); } /** * Is the value a particular built-in type? */ public static function typeOf($theType) { return \Hamcrest\Core\IsTypeOf::typeOf($theType); } /** * Matches if value (class, object, or array) has named $property. */ public static function set($property) { return \Hamcrest\Core\Set::set($property); } /** * Matches if value (class, object, or array) does not have named $property. */ public static function notSet($property) { return \Hamcrest\Core\Set::notSet($property); } /** * Matches if value is a number equal to $value within some range of * acceptable error $delta. */ public static function closeTo($value, $delta) { return \Hamcrest\Number\IsCloseTo::closeTo($value, $delta); } /** * The value is not > $value, nor < $value. */ public static function comparesEqualTo($value) { return \Hamcrest\Number\OrderingComparison::comparesEqualTo($value); } /** * The value is > $value. */ public static function greaterThan($value) { return \Hamcrest\Number\OrderingComparison::greaterThan($value); } /** * The value is >= $value. */ public static function greaterThanOrEqualTo($value) { return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); } /** * The value is >= $value. */ public static function atLeast($value) { return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); } /** * The value is < $value. */ public static function lessThan($value) { return \Hamcrest\Number\OrderingComparison::lessThan($value); } /** * The value is <= $value. */ public static function lessThanOrEqualTo($value) { return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); } /** * The value is <= $value. */ public static function atMost($value) { return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); } /** * Matches if value is a zero-length string. */ public static function isEmptyString() { return \Hamcrest\Text\IsEmptyString::isEmptyString(); } /** * Matches if value is a zero-length string. */ public static function emptyString() { return \Hamcrest\Text\IsEmptyString::isEmptyString(); } /** * Matches if value is null or a zero-length string. */ public static function isEmptyOrNullString() { return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); } /** * Matches if value is null or a zero-length string. */ public static function nullOrEmptyString() { return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); } /** * Matches if value is a non-zero-length string. */ public static function isNonEmptyString() { return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); } /** * Matches if value is a non-zero-length string. */ public static function nonEmptyString() { return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); } /** * Matches if value is a string equal to $string, regardless of the case. */ public static function equalToIgnoringCase($string) { return \Hamcrest\Text\IsEqualIgnoringCase::equalToIgnoringCase($string); } /** * Matches if value is a string equal to $string, regardless of whitespace. */ public static function equalToIgnoringWhiteSpace($string) { return \Hamcrest\Text\IsEqualIgnoringWhiteSpace::equalToIgnoringWhiteSpace($string); } /** * Matches if value is a string that matches regular expression $pattern. */ public static function matchesPattern($pattern) { return \Hamcrest\Text\MatchesPattern::matchesPattern($pattern); } /** * Matches if value is a string that contains $substring. */ public static function containsString($substring) { return \Hamcrest\Text\StringContains::containsString($substring); } /** * Matches if value is a string that contains $substring regardless of the case. */ public static function containsStringIgnoringCase($substring) { return \Hamcrest\Text\StringContainsIgnoringCase::containsStringIgnoringCase($substring); } /** * Matches if value contains $substrings in a constrained order. */ public static function stringContainsInOrder(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Text\StringContainsInOrder', 'stringContainsInOrder'), $args); } /** * Matches if value is a string that ends with $substring. */ public static function endsWith($substring) { return \Hamcrest\Text\StringEndsWith::endsWith($substring); } /** * Matches if value is a string that starts with $substring. */ public static function startsWith($substring) { return \Hamcrest\Text\StringStartsWith::startsWith($substring); } /** * Is the value an array? */ public static function arrayValue() { return \Hamcrest\Type\IsArray::arrayValue(); } /** * Is the value a boolean? */ public static function booleanValue() { return \Hamcrest\Type\IsBoolean::booleanValue(); } /** * Is the value a boolean? */ public static function boolValue() { return \Hamcrest\Type\IsBoolean::booleanValue(); } /** * Is the value callable? */ public static function callableValue() { return \Hamcrest\Type\IsCallable::callableValue(); } /** * Is the value a float/double? */ public static function doubleValue() { return \Hamcrest\Type\IsDouble::doubleValue(); } /** * Is the value a float/double? */ public static function floatValue() { return \Hamcrest\Type\IsDouble::doubleValue(); } /** * Is the value an integer? */ public static function integerValue() { return \Hamcrest\Type\IsInteger::integerValue(); } /** * Is the value an integer? */ public static function intValue() { return \Hamcrest\Type\IsInteger::integerValue(); } /** * Is the value a numeric? */ public static function numericValue() { return \Hamcrest\Type\IsNumeric::numericValue(); } /** * Is the value an object? */ public static function objectValue() { return \Hamcrest\Type\IsObject::objectValue(); } /** * Is the value an object? */ public static function anObject() { return \Hamcrest\Type\IsObject::objectValue(); } /** * Is the value a resource? */ public static function resourceValue() { return \Hamcrest\Type\IsResource::resourceValue(); } /** * Is the value a scalar (boolean, integer, double, or string)? */ public static function scalarValue() { return \Hamcrest\Type\IsScalar::scalarValue(); } /** * Is the value a string? */ public static function stringValue() { return \Hamcrest\Type\IsString::stringValue(); } /** * Wraps $matcher with {@link Hamcrest\Core\IsEqual) * if it's not a matcher and the XPath in count() * if it's an integer. */ public static function hasXPath($xpath, $matcher = null) { return \Hamcrest\Xml\HasXPath::hasXPath($xpath, $matcher); } } all items are */ public static function createMatcherArray(array $items) { //Extract single array item if (count($items) == 1 && is_array($items[0])) { $items = $items[0]; } //Replace non-matchers foreach ($items as &$item) { if (!($item instanceof Matcher)) { $item = Core\IsEqual::equalTo($item); } } return $items; } } _elementMatchers = $elementMatchers; } protected function matchesSafelyWithDiagnosticDescription($array, Description $mismatchDescription) { $series = new SeriesMatchingOnce($this->_elementMatchers, $mismatchDescription); foreach ($array as $element) { if (!$series->matches($element)) { return false; } } return $series->isFinished(); } public function describeTo(Description $description) { $description->appendList('[', ', ', ']', $this->_elementMatchers); } /** * An array with elements that match the given matchers in the same order. * * @factory contains ... */ public static function arrayContaining(/* args... */) { $args = func_get_args(); return new self(Util::createMatcherArray($args)); } } _elementMatchers = $elementMatchers; $this->_keys = array_keys($elementMatchers); $this->_mismatchDescription = $mismatchDescription; } public function matches($item) { return $this->_isNotSurplus($item) && $this->_isMatched($item); } public function isFinished() { if (!empty($this->_elementMatchers)) { $nextMatcher = current($this->_elementMatchers); $this->_mismatchDescription->appendText('No item matched: ')->appendDescriptionOf($nextMatcher); return false; } return true; } // -- Private Methods private function _isNotSurplus($item) { if (empty($this->_elementMatchers)) { $this->_mismatchDescription->appendText('Not matched: ')->appendValue($item); return false; } return true; } private function _isMatched($item) { $this->_nextMatchKey = array_shift($this->_keys); $nextMatcher = array_shift($this->_elementMatchers); if (!$nextMatcher->matches($item)) { $this->_describeMismatch($nextMatcher, $item); return false; } return true; } private function _describeMismatch(Matcher $matcher, $item) { $this->_mismatchDescription->appendText('item with key ' . $this->_nextMatchKey . ': '); $matcher->describeMismatch($item, $this->_mismatchDescription); } } _elementMatchers = $elementMatchers; } protected function matchesSafely($array) { if (array_keys($array) != array_keys($this->_elementMatchers)) { return false; } /** @var $matcher \Hamcrest\Matcher */ foreach ($this->_elementMatchers as $k => $matcher) { if (!$matcher->matches($array[$k])) { return false; } } return true; } protected function describeMismatchSafely($actual, Description $mismatchDescription) { if (count($actual) != count($this->_elementMatchers)) { $mismatchDescription->appendText('array length was ' . count($actual)); return; } elseif (array_keys($actual) != array_keys($this->_elementMatchers)) { $mismatchDescription->appendText('array keys were ') ->appendValueList( $this->descriptionStart(), $this->descriptionSeparator(), $this->descriptionEnd(), array_keys($actual) ) ; return; } /** @var $matcher \Hamcrest\Matcher */ foreach ($this->_elementMatchers as $k => $matcher) { if (!$matcher->matches($actual[$k])) { $mismatchDescription->appendText('element ')->appendValue($k) ->appendText(' was ')->appendValue($actual[$k]); return; } } } public function describeTo(Description $description) { $description->appendList( $this->descriptionStart(), $this->descriptionSeparator(), $this->descriptionEnd(), $this->_elementMatchers ); } /** * Evaluates to true only if each $matcher[$i] is satisfied by $array[$i]. * * @factory ... */ public static function anArray(/* args... */) { $args = func_get_args(); return new self(Util::createMatcherArray($args)); } // -- Protected Methods protected function descriptionStart() { return '['; } protected function descriptionSeparator() { return ', '; } protected function descriptionEnd() { return ']'; } } _elementMatcher = $elementMatcher; } protected function matchesSafely($array) { foreach ($array as $element) { if ($this->_elementMatcher->matches($element)) { return true; } } return false; } protected function describeMismatchSafely($array, Description $mismatchDescription) { $mismatchDescription->appendText('was ')->appendValue($array); } public function describeTo(Description $description) { $description ->appendText('an array containing ') ->appendDescriptionOf($this->_elementMatcher) ; } /** * Evaluates to true if any item in an array satisfies the given matcher. * * @param mixed $item as a {@link Hamcrest\Matcher} or a value. * * @return \Hamcrest\Arrays\IsArrayContaining * @factory hasValue */ public static function hasItemInArray($item) { return new self(Util::wrapValueWithIsEqual($item)); } } _keyMatcher = $keyMatcher; } protected function matchesSafely($array) { foreach ($array as $key => $element) { if ($this->_keyMatcher->matches($key)) { return true; } } return false; } protected function describeMismatchSafely($array, Description $mismatchDescription) { //Not using appendValueList() so that keys can be shown $mismatchDescription->appendText('array was ') ->appendText('[') ; $loop = false; foreach ($array as $key => $value) { if ($loop) { $mismatchDescription->appendText(', '); } $mismatchDescription->appendValue($key)->appendText(' => ')->appendValue($value); $loop = true; } $mismatchDescription->appendText(']'); } public function describeTo(Description $description) { $description ->appendText('array with key ') ->appendDescriptionOf($this->_keyMatcher) ; } /** * Evaluates to true if any key in an array matches the given matcher. * * @param mixed $key as a {@link Hamcrest\Matcher} or a value. * * @return \Hamcrest\Arrays\IsArrayContainingKey * @factory hasKey */ public static function hasKeyInArray($key) { return new self(Util::wrapValueWithIsEqual($key)); } } _keyMatcher = $keyMatcher; $this->_valueMatcher = $valueMatcher; } protected function matchesSafely($array) { foreach ($array as $key => $value) { if ($this->_keyMatcher->matches($key) && $this->_valueMatcher->matches($value)) { return true; } } return false; } protected function describeMismatchSafely($array, Description $mismatchDescription) { //Not using appendValueList() so that keys can be shown $mismatchDescription->appendText('array was ') ->appendText('[') ; $loop = false; foreach ($array as $key => $value) { if ($loop) { $mismatchDescription->appendText(', '); } $mismatchDescription->appendValue($key)->appendText(' => ')->appendValue($value); $loop = true; } $mismatchDescription->appendText(']'); } public function describeTo(Description $description) { $description->appendText('array containing [') ->appendDescriptionOf($this->_keyMatcher) ->appendText(' => ') ->appendDescriptionOf($this->_valueMatcher) ->appendText(']') ; } /** * Test if an array has both an key and value in parity with each other. * * @factory hasEntry */ public static function hasKeyValuePair($key, $value) { return new self( Util::wrapValueWithIsEqual($key), Util::wrapValueWithIsEqual($value) ); } } _elementMatchers = $elementMatchers; } protected function matchesSafelyWithDiagnosticDescription($array, Description $mismatchDescription) { $matching = new MatchingOnce($this->_elementMatchers, $mismatchDescription); foreach ($array as $element) { if (!$matching->matches($element)) { return false; } } return $matching->isFinished($array); } public function describeTo(Description $description) { $description->appendList('[', ', ', ']', $this->_elementMatchers) ->appendText(' in any order') ; } /** * An array with elements that match the given matchers. * * @factory containsInAnyOrder ... */ public static function arrayContainingInAnyOrder(/* args... */) { $args = func_get_args(); return new self(Util::createMatcherArray($args)); } } _elementMatchers = $elementMatchers; $this->_mismatchDescription = $mismatchDescription; } public function matches($item) { return $this->_isNotSurplus($item) && $this->_isMatched($item); } public function isFinished($items) { if (empty($this->_elementMatchers)) { return true; } $this->_mismatchDescription ->appendText('No item matches: ')->appendList('', ', ', '', $this->_elementMatchers) ->appendText(' in ')->appendValueList('[', ', ', ']', $items) ; return false; } // -- Private Methods private function _isNotSurplus($item) { if (empty($this->_elementMatchers)) { $this->_mismatchDescription->appendText('Not matched: ')->appendValue($item); return false; } return true; } private function _isMatched($item) { /** @var $matcher \Hamcrest\Matcher */ foreach ($this->_elementMatchers as $i => $matcher) { if ($matcher->matches($item)) { unset($this->_elementMatchers[$i]); return true; } } $this->_mismatchDescription->appendText('Not matched: ')->appendValue($item); return false; } } matchesSafelyWithDiagnosticDescription($item, new NullDescription()); } final public function describeMismatchSafely($item, Description $mismatchDescription) { $this->matchesSafelyWithDiagnosticDescription($item, $mismatchDescription); } // -- Protected Methods /** * Subclasses should implement these. The item will already have been checked for * the specific type. */ abstract protected function matchesSafelyWithDiagnosticDescription($item, Description $mismatchDescription); } _value = $value; $this->_minCompare = $minCompare; $this->_maxCompare = $maxCompare; } protected function matchesSafely($other) { $compare = $this->_compare($this->_value, $other); return ($this->_minCompare <= $compare) && ($compare <= $this->_maxCompare); } protected function describeMismatchSafely($item, Description $mismatchDescription) { $mismatchDescription ->appendValue($item)->appendText(' was ') ->appendText($this->_comparison($this->_compare($this->_value, $item))) ->appendText(' ')->appendValue($this->_value) ; } public function describeTo(Description $description) { $description->appendText('a value ') ->appendText($this->_comparison($this->_minCompare)) ; if ($this->_minCompare != $this->_maxCompare) { $description->appendText(' or ') ->appendText($this->_comparison($this->_maxCompare)) ; } $description->appendText(' ')->appendValue($this->_value); } /** * The value is not > $value, nor < $value. * * @factory */ public static function comparesEqualTo($value) { return new self($value, 0, 0); } /** * The value is > $value. * * @factory */ public static function greaterThan($value) { return new self($value, -1, -1); } /** * The value is >= $value. * * @factory atLeast */ public static function greaterThanOrEqualTo($value) { return new self($value, -1, 0); } /** * The value is < $value. * * @factory */ public static function lessThan($value) { return new self($value, 1, 1); } /** * The value is <= $value. * * @factory atMost */ public static function lessThanOrEqualTo($value) { return new self($value, 0, 1); } // -- Private Methods private function _compare($left, $right) { $a = $left; $b = $right; if ($a < $b) { return -1; } elseif ($a == $b) { return 0; } else { return 1; } } private function _comparison($compare) { if ($compare > 0) { return 'less than'; } elseif ($compare == 0) { return 'equal to'; } else { return 'greater than'; } } } _value = $value; $this->_delta = $delta; } protected function matchesSafely($item) { return $this->_actualDelta($item) <= 0.0; } protected function describeMismatchSafely($item, Description $mismatchDescription) { $mismatchDescription->appendValue($item) ->appendText(' differed by ') ->appendValue($this->_actualDelta($item)) ; } public function describeTo(Description $description) { $description->appendText('a numeric value within ') ->appendValue($this->_delta) ->appendText(' of ') ->appendValue($this->_value) ; } /** * Matches if value is a number equal to $value within some range of * acceptable error $delta. * * @factory */ public static function closeTo($value, $delta) { return new self($value, $delta); } // -- Private Methods private function _actualDelta($item) { return (abs(($item - $this->_value)) - $this->_delta); } } * //With an identifier * assertThat("assertion identifier", $apple->flavour(), equalTo("tasty")); * //Without an identifier * assertThat($apple->flavour(), equalTo("tasty")); * //Evaluating a boolean expression * assertThat("some error", $a > $b); * */ function assertThat() { $args = func_get_args(); call_user_func_array( array('Hamcrest\MatcherAssert', 'assertThat'), $args ); } } if (!function_exists('anArray')) { /** * Evaluates to true only if each $matcher[$i] is satisfied by $array[$i]. */ function anArray(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Arrays\IsArray', 'anArray'), $args); } } if (!function_exists('hasItemInArray')) { /** * Evaluates to true if any item in an array satisfies the given matcher. * * @param mixed $item as a {@link Hamcrest\Matcher} or a value. * * @return \Hamcrest\Arrays\IsArrayContaining */ function hasItemInArray($item) { return \Hamcrest\Arrays\IsArrayContaining::hasItemInArray($item); } } if (!function_exists('hasValue')) { /** * Evaluates to true if any item in an array satisfies the given matcher. * * @param mixed $item as a {@link Hamcrest\Matcher} or a value. * * @return \Hamcrest\Arrays\IsArrayContaining */ function hasValue($item) { return \Hamcrest\Arrays\IsArrayContaining::hasItemInArray($item); } } if (!function_exists('arrayContainingInAnyOrder')) { /** * An array with elements that match the given matchers. */ function arrayContainingInAnyOrder(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInAnyOrder', 'arrayContainingInAnyOrder'), $args); } } if (!function_exists('containsInAnyOrder')) { /** * An array with elements that match the given matchers. */ function containsInAnyOrder(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInAnyOrder', 'arrayContainingInAnyOrder'), $args); } } if (!function_exists('arrayContaining')) { /** * An array with elements that match the given matchers in the same order. */ function arrayContaining(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInOrder', 'arrayContaining'), $args); } } if (!function_exists('contains')) { /** * An array with elements that match the given matchers in the same order. */ function contains(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInOrder', 'arrayContaining'), $args); } } if (!function_exists('hasKeyInArray')) { /** * Evaluates to true if any key in an array matches the given matcher. * * @param mixed $key as a {@link Hamcrest\Matcher} or a value. * * @return \Hamcrest\Arrays\IsArrayContainingKey */ function hasKeyInArray($key) { return \Hamcrest\Arrays\IsArrayContainingKey::hasKeyInArray($key); } } if (!function_exists('hasKey')) { /** * Evaluates to true if any key in an array matches the given matcher. * * @param mixed $key as a {@link Hamcrest\Matcher} or a value. * * @return \Hamcrest\Arrays\IsArrayContainingKey */ function hasKey($key) { return \Hamcrest\Arrays\IsArrayContainingKey::hasKeyInArray($key); } } if (!function_exists('hasKeyValuePair')) { /** * Test if an array has both an key and value in parity with each other. */ function hasKeyValuePair($key, $value) { return \Hamcrest\Arrays\IsArrayContainingKeyValuePair::hasKeyValuePair($key, $value); } } if (!function_exists('hasEntry')) { /** * Test if an array has both an key and value in parity with each other. */ function hasEntry($key, $value) { return \Hamcrest\Arrays\IsArrayContainingKeyValuePair::hasKeyValuePair($key, $value); } } if (!function_exists('arrayWithSize')) { /** * Does array size satisfy a given matcher? * * @param \Hamcrest\Matcher|int $size as a {@link Hamcrest\Matcher} or a value. * * @return \Hamcrest\Arrays\IsArrayWithSize */ function arrayWithSize($size) { return \Hamcrest\Arrays\IsArrayWithSize::arrayWithSize($size); } } if (!function_exists('emptyArray')) { /** * Matches an empty array. */ function emptyArray() { return \Hamcrest\Arrays\IsArrayWithSize::emptyArray(); } } if (!function_exists('nonEmptyArray')) { /** * Matches an empty array. */ function nonEmptyArray() { return \Hamcrest\Arrays\IsArrayWithSize::nonEmptyArray(); } } if (!function_exists('emptyTraversable')) { /** * Returns true if traversable is empty. */ function emptyTraversable() { return \Hamcrest\Collection\IsEmptyTraversable::emptyTraversable(); } } if (!function_exists('nonEmptyTraversable')) { /** * Returns true if traversable is not empty. */ function nonEmptyTraversable() { return \Hamcrest\Collection\IsEmptyTraversable::nonEmptyTraversable(); } } if (!function_exists('traversableWithSize')) { /** * Does traversable size satisfy a given matcher? */ function traversableWithSize($size) { return \Hamcrest\Collection\IsTraversableWithSize::traversableWithSize($size); } } if (!function_exists('allOf')) { /** * Evaluates to true only if ALL of the passed in matchers evaluate to true. */ function allOf(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Core\AllOf', 'allOf'), $args); } } if (!function_exists('anyOf')) { /** * Evaluates to true if ANY of the passed in matchers evaluate to true. */ function anyOf(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Core\AnyOf', 'anyOf'), $args); } } if (!function_exists('noneOf')) { /** * Evaluates to false if ANY of the passed in matchers evaluate to true. */ function noneOf(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Core\AnyOf', 'noneOf'), $args); } } if (!function_exists('both')) { /** * This is useful for fluently combining matchers that must both pass. * For example: *
     *   assertThat($string, both(containsString("a"))->andAlso(containsString("b")));
     * 
*/ function both(\Hamcrest\Matcher $matcher) { return \Hamcrest\Core\CombinableMatcher::both($matcher); } } if (!function_exists('either')) { /** * This is useful for fluently combining matchers where either may pass, * for example: *
     *   assertThat($string, either(containsString("a"))->orElse(containsString("b")));
     * 
*/ function either(\Hamcrest\Matcher $matcher) { return \Hamcrest\Core\CombinableMatcher::either($matcher); } } if (!function_exists('describedAs')) { /** * Wraps an existing matcher and overrides the description when it fails. */ function describedAs(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Core\DescribedAs', 'describedAs'), $args); } } if (!function_exists('everyItem')) { /** * @param Matcher $itemMatcher * A matcher to apply to every element in an array. * * @return \Hamcrest\Core\Every * Evaluates to TRUE for a collection in which every item matches $itemMatcher */ function everyItem(\Hamcrest\Matcher $itemMatcher) { return \Hamcrest\Core\Every::everyItem($itemMatcher); } } if (!function_exists('hasToString')) { /** * Does array size satisfy a given matcher? */ function hasToString($matcher) { return \Hamcrest\Core\HasToString::hasToString($matcher); } } if (!function_exists('is')) { /** * Decorates another Matcher, retaining the behavior but allowing tests * to be slightly more expressive. * * For example: assertThat($cheese, equalTo($smelly)) * vs. assertThat($cheese, is(equalTo($smelly))) */ function is($value) { return \Hamcrest\Core\Is::is($value); } } if (!function_exists('anything')) { /** * This matcher always evaluates to true. * * @param string $description A meaningful string used when describing itself. * * @return \Hamcrest\Core\IsAnything */ function anything($description = 'ANYTHING') { return \Hamcrest\Core\IsAnything::anything($description); } } if (!function_exists('hasItem')) { /** * Test if the value is an array containing this matcher. * * Example: *
     * assertThat(array('a', 'b'), hasItem(equalTo('b')));
     * //Convenience defaults to equalTo()
     * assertThat(array('a', 'b'), hasItem('b'));
     * 
*/ function hasItem(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItem'), $args); } } if (!function_exists('hasItems')) { /** * Test if the value is an array containing elements that match all of these * matchers. * * Example: *
     * assertThat(array('a', 'b', 'c'), hasItems(equalTo('a'), equalTo('b')));
     * 
*/ function hasItems(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItems'), $args); } } if (!function_exists('equalTo')) { /** * Is the value equal to another value, as tested by the use of the "==" * comparison operator? */ function equalTo($item) { return \Hamcrest\Core\IsEqual::equalTo($item); } } if (!function_exists('identicalTo')) { /** * Tests of the value is identical to $value as tested by the "===" operator. */ function identicalTo($value) { return \Hamcrest\Core\IsIdentical::identicalTo($value); } } if (!function_exists('anInstanceOf')) { /** * Is the value an instance of a particular type? * This version assumes no relationship between the required type and * the signature of the method that sets it up, for example in * assertThat($anObject, anInstanceOf('Thing')); */ function anInstanceOf($theClass) { return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); } } if (!function_exists('any')) { /** * Is the value an instance of a particular type? * This version assumes no relationship between the required type and * the signature of the method that sets it up, for example in * assertThat($anObject, anInstanceOf('Thing')); */ function any($theClass) { return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); } } if (!function_exists('not')) { /** * Matches if value does not match $value. */ function not($value) { return \Hamcrest\Core\IsNot::not($value); } } if (!function_exists('nullValue')) { /** * Matches if value is null. */ function nullValue() { return \Hamcrest\Core\IsNull::nullValue(); } } if (!function_exists('notNullValue')) { /** * Matches if value is not null. */ function notNullValue() { return \Hamcrest\Core\IsNull::notNullValue(); } } if (!function_exists('sameInstance')) { /** * Creates a new instance of IsSame. * * @param mixed $object * The predicate evaluates to true only when the argument is * this object. * * @return \Hamcrest\Core\IsSame */ function sameInstance($object) { return \Hamcrest\Core\IsSame::sameInstance($object); } } if (!function_exists('typeOf')) { /** * Is the value a particular built-in type? */ function typeOf($theType) { return \Hamcrest\Core\IsTypeOf::typeOf($theType); } } if (!function_exists('set')) { /** * Matches if value (class, object, or array) has named $property. */ function set($property) { return \Hamcrest\Core\Set::set($property); } } if (!function_exists('notSet')) { /** * Matches if value (class, object, or array) does not have named $property. */ function notSet($property) { return \Hamcrest\Core\Set::notSet($property); } } if (!function_exists('closeTo')) { /** * Matches if value is a number equal to $value within some range of * acceptable error $delta. */ function closeTo($value, $delta) { return \Hamcrest\Number\IsCloseTo::closeTo($value, $delta); } } if (!function_exists('comparesEqualTo')) { /** * The value is not > $value, nor < $value. */ function comparesEqualTo($value) { return \Hamcrest\Number\OrderingComparison::comparesEqualTo($value); } } if (!function_exists('greaterThan')) { /** * The value is > $value. */ function greaterThan($value) { return \Hamcrest\Number\OrderingComparison::greaterThan($value); } } if (!function_exists('greaterThanOrEqualTo')) { /** * The value is >= $value. */ function greaterThanOrEqualTo($value) { return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); } } if (!function_exists('atLeast')) { /** * The value is >= $value. */ function atLeast($value) { return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); } } if (!function_exists('lessThan')) { /** * The value is < $value. */ function lessThan($value) { return \Hamcrest\Number\OrderingComparison::lessThan($value); } } if (!function_exists('lessThanOrEqualTo')) { /** * The value is <= $value. */ function lessThanOrEqualTo($value) { return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); } } if (!function_exists('atMost')) { /** * The value is <= $value. */ function atMost($value) { return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); } } if (!function_exists('isEmptyString')) { /** * Matches if value is a zero-length string. */ function isEmptyString() { return \Hamcrest\Text\IsEmptyString::isEmptyString(); } } if (!function_exists('emptyString')) { /** * Matches if value is a zero-length string. */ function emptyString() { return \Hamcrest\Text\IsEmptyString::isEmptyString(); } } if (!function_exists('isEmptyOrNullString')) { /** * Matches if value is null or a zero-length string. */ function isEmptyOrNullString() { return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); } } if (!function_exists('nullOrEmptyString')) { /** * Matches if value is null or a zero-length string. */ function nullOrEmptyString() { return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); } } if (!function_exists('isNonEmptyString')) { /** * Matches if value is a non-zero-length string. */ function isNonEmptyString() { return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); } } if (!function_exists('nonEmptyString')) { /** * Matches if value is a non-zero-length string. */ function nonEmptyString() { return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); } } if (!function_exists('equalToIgnoringCase')) { /** * Matches if value is a string equal to $string, regardless of the case. */ function equalToIgnoringCase($string) { return \Hamcrest\Text\IsEqualIgnoringCase::equalToIgnoringCase($string); } } if (!function_exists('equalToIgnoringWhiteSpace')) { /** * Matches if value is a string equal to $string, regardless of whitespace. */ function equalToIgnoringWhiteSpace($string) { return \Hamcrest\Text\IsEqualIgnoringWhiteSpace::equalToIgnoringWhiteSpace($string); } } if (!function_exists('matchesPattern')) { /** * Matches if value is a string that matches regular expression $pattern. */ function matchesPattern($pattern) { return \Hamcrest\Text\MatchesPattern::matchesPattern($pattern); } } if (!function_exists('containsString')) { /** * Matches if value is a string that contains $substring. */ function containsString($substring) { return \Hamcrest\Text\StringContains::containsString($substring); } } if (!function_exists('containsStringIgnoringCase')) { /** * Matches if value is a string that contains $substring regardless of the case. */ function containsStringIgnoringCase($substring) { return \Hamcrest\Text\StringContainsIgnoringCase::containsStringIgnoringCase($substring); } } if (!function_exists('stringContainsInOrder')) { /** * Matches if value contains $substrings in a constrained order. */ function stringContainsInOrder(/* args... */) { $args = func_get_args(); return call_user_func_array(array('\Hamcrest\Text\StringContainsInOrder', 'stringContainsInOrder'), $args); } } if (!function_exists('endsWith')) { /** * Matches if value is a string that ends with $substring. */ function endsWith($substring) { return \Hamcrest\Text\StringEndsWith::endsWith($substring); } } if (!function_exists('startsWith')) { /** * Matches if value is a string that starts with $substring. */ function startsWith($substring) { return \Hamcrest\Text\StringStartsWith::startsWith($substring); } } if (!function_exists('arrayValue')) { /** * Is the value an array? */ function arrayValue() { return \Hamcrest\Type\IsArray::arrayValue(); } } if (!function_exists('booleanValue')) { /** * Is the value a boolean? */ function booleanValue() { return \Hamcrest\Type\IsBoolean::booleanValue(); } } if (!function_exists('boolValue')) { /** * Is the value a boolean? */ function boolValue() { return \Hamcrest\Type\IsBoolean::booleanValue(); } } if (!function_exists('callableValue')) { /** * Is the value callable? */ function callableValue() { return \Hamcrest\Type\IsCallable::callableValue(); } } if (!function_exists('doubleValue')) { /** * Is the value a float/double? */ function doubleValue() { return \Hamcrest\Type\IsDouble::doubleValue(); } } if (!function_exists('floatValue')) { /** * Is the value a float/double? */ function floatValue() { return \Hamcrest\Type\IsDouble::doubleValue(); } } if (!function_exists('integerValue')) { /** * Is the value an integer? */ function integerValue() { return \Hamcrest\Type\IsInteger::integerValue(); } } if (!function_exists('intValue')) { /** * Is the value an integer? */ function intValue() { return \Hamcrest\Type\IsInteger::integerValue(); } } if (!function_exists('numericValue')) { /** * Is the value a numeric? */ function numericValue() { return \Hamcrest\Type\IsNumeric::numericValue(); } } if (!function_exists('objectValue')) { /** * Is the value an object? */ function objectValue() { return \Hamcrest\Type\IsObject::objectValue(); } } if (!function_exists('anObject')) { /** * Is the value an object? */ function anObject() { return \Hamcrest\Type\IsObject::objectValue(); } } if (!function_exists('resourceValue')) { /** * Is the value a resource? */ function resourceValue() { return \Hamcrest\Type\IsResource::resourceValue(); } } if (!function_exists('scalarValue')) { /** * Is the value a scalar (boolean, integer, double, or string)? */ function scalarValue() { return \Hamcrest\Type\IsScalar::scalarValue(); } } if (!function_exists('stringValue')) { /** * Is the value a string? */ function stringValue() { return \Hamcrest\Type\IsString::stringValue(); } } if (!function_exists('hasXPath')) { /** * Wraps $matcher with {@link Hamcrest\Core\IsEqual) * if it's not a matcher and the XPath in count() * if it's an integer. */ function hasXPath($xpath, $matcher = null) { return \Hamcrest\Xml\HasXPath::hasXPath($xpath, $matcher); } } methods = ''; } public function addCall(FactoryCall $call) { $this->methods .= PHP_EOL . $this->generateFactoryCall($call); } public function getDeclarationModifiers() { return 'public static '; } public function build() { $this->addFileHeader(); $this->addPart('matchers_imports'); $this->addPart('matchers_header'); $this->addCode($this->methods); $this->addPart('matchers_footer'); } } class = $class; $this->reflector = $reflector; $this->extractCommentWithoutLeadingShashesAndStars(); $this->extractFactoryNamesFromComment(); $this->extractParameters(); } public function extractCommentWithoutLeadingShashesAndStars() { $this->comment = explode("\n", $this->reflector->getDocComment()); foreach ($this->comment as &$line) { $line = preg_replace('#^\s*(/\\*+|\\*+/|\\*)\s?#', '', $line); } $this->trimLeadingBlankLinesFromComment(); $this->trimTrailingBlankLinesFromComment(); } public function trimLeadingBlankLinesFromComment() { while (count($this->comment) > 0) { $line = array_shift($this->comment); if (trim($line) != '') { array_unshift($this->comment, $line); break; } } } public function trimTrailingBlankLinesFromComment() { while (count($this->comment) > 0) { $line = array_pop($this->comment); if (trim($line) != '') { array_push($this->comment, $line); break; } } } public function extractFactoryNamesFromComment() { $this->calls = array(); for ($i = 0; $i < count($this->comment); $i++) { if ($this->extractFactoryNamesFromLine($this->comment[$i])) { unset($this->comment[$i]); } } $this->trimTrailingBlankLinesFromComment(); } public function extractFactoryNamesFromLine($line) { if (preg_match('/^\s*@factory(\s+(.+))?$/', $line, $match)) { $this->createCalls( $this->extractFactoryNamesFromAnnotation( isset($match[2]) ? trim($match[2]) : null ) ); return true; } return false; } public function extractFactoryNamesFromAnnotation($value) { $primaryName = $this->reflector->getName(); if (empty($value)) { return array($primaryName); } preg_match_all('/(\.{3}|-|[a-zA-Z_][a-zA-Z_0-9]*)/', $value, $match); $names = $match[0]; if (in_array('...', $names)) { $this->isVarArgs = true; } if (!in_array('-', $names) && !in_array($primaryName, $names)) { array_unshift($names, $primaryName); } return $names; } public function createCalls(array $names) { $names = array_unique($names); foreach ($names as $name) { if ($name != '-' && $name != '...') { $this->calls[] = new FactoryCall($this, $name); } } } public function extractParameters() { $this->parameters = array(); if (!$this->isVarArgs) { foreach ($this->reflector->getParameters() as $parameter) { $this->parameters[] = new FactoryParameter($this, $parameter); } } } public function getParameterDeclarations() { if ($this->isVarArgs || !$this->hasParameters()) { return ''; } $params = array(); foreach ($this->parameters as /** @var $parameter FactoryParameter */ $parameter) { $params[] = $parameter->getDeclaration(); } return implode(', ', $params); } public function getParameterInvocations() { if ($this->isVarArgs) { return ''; } $params = array(); foreach ($this->parameters as $parameter) { $params[] = $parameter->getInvocation(); } return implode(', ', $params); } public function getClass() { return $this->class; } public function getClassName() { return $this->class->getName(); } public function getName() { return $this->reflector->name; } public function isFactory() { return count($this->calls) > 0; } public function getCalls() { return $this->calls; } public function acceptsVariableArguments() { return $this->isVarArgs; } public function hasParameters() { return !empty($this->parameters); } public function getParameters() { return $this->parameters; } public function getFullName() { return $this->getClassName() . '::' . $this->getName(); } public function getCommentText() { return implode(PHP_EOL, $this->comment); } public function getComment($indent = '') { $comment = $indent . '/**'; foreach ($this->comment as $line) { $comment .= PHP_EOL . rtrim($indent . ' * ' . $line); } $comment .= PHP_EOL . $indent . ' */'; return $comment; } } functions = ''; } public function addCall(FactoryCall $call) { $this->functions .= PHP_EOL . $this->generateFactoryCall($call); } public function build() { $this->addFileHeader(); $this->addPart('functions_imports'); $this->addPart('functions_header'); $this->addCode($this->functions); $this->addPart('functions_footer'); } public function generateFactoryCall(FactoryCall $call) { $code = "if (!function_exists('{$call->getName()}')) {"; $code.= parent::generateFactoryCall($call); $code.= "}\n"; return $code; } } path = $path; $this->factoryFiles = array(); } public function addFactoryFile(FactoryFile $factoryFile) { $this->factoryFiles[] = $factoryFile; } public function generate() { $classes = $this->getClassesWithFactoryMethods(); foreach ($classes as $class) { foreach ($class->getMethods() as $method) { foreach ($method->getCalls() as $call) { foreach ($this->factoryFiles as $file) { $file->addCall($call); } } } } } public function write() { foreach ($this->factoryFiles as $file) { $file->build(); $file->write(); } } public function getClassesWithFactoryMethods() { $classes = array(); $files = $this->getSortedFiles(); foreach ($files as $file) { $class = $this->getFactoryClass($file); if ($class !== null) { $classes[] = $class; } } return $classes; } public function getSortedFiles() { $iter = \File_Iterator_Factory::getFileIterator($this->path, '.php'); $files = array(); foreach ($iter as $file) { $files[] = $file; } sort($files, SORT_STRING); return $files; } public function getFactoryClass($file) { $name = $this->getFactoryClassName($file); if ($name !== null) { require_once $file; if (class_exists($name)) { $class = new FactoryClass(substr($file, strpos($file, 'Hamcrest/')), new ReflectionClass($name)); if ($class->isFactory()) { return $class; } } } return null; } public function getFactoryClassName($file) { $content = file_get_contents($file); if (preg_match('/namespace\s+(.+);/', $content, $namespace) && preg_match('/\n\s*class\s+(\w+)\s+extends\b/', $content, $className) && preg_match('/@factory\b/', $content) ) { return $namespace[1] . '\\' . $className[1]; } return null; } } file = $file; $this->reflector = $class; $this->extractFactoryMethods(); } public function extractFactoryMethods() { $this->methods = array(); foreach ($this->getPublicStaticMethods() as $method) { if ($method->isFactory()) { // echo $this->getName() . '::' . $method->getName() . ' : ' . count($method->getCalls()) . PHP_EOL; $this->methods[] = $method; } } } public function getPublicStaticMethods() { $methods = array(); foreach ($this->reflector->getMethods(ReflectionMethod::IS_STATIC) as $method) { if ($method->isPublic() && $method->getDeclaringClass() == $this->reflector) { $methods[] = new FactoryMethod($this, $method); } } return $methods; } public function getFile() { return $this->file; } public function getName() { return $this->reflector->name; } public function isFactory() { return !empty($this->methods); } public function getMethods() { return $this->methods; } } addFactoryFile(new StaticMethodFile(STATIC_MATCHERS_FILE)); $generator->addFactoryFile(new GlobalFunctionFile(GLOBAL_FUNCTIONS_FILE)); $generator->generate(); $generator->write(); method = $method; $this->reflector = $reflector; } public function getDeclaration() { if ($this->reflector->isArray()) { $code = 'array '; } else { $class = $this->reflector->getClass(); if ($class !== null) { $code = '\\' . $class->name . ' '; } else { $code = ''; } } $code .= '$' . $this->reflector->name; if ($this->reflector->isOptional()) { $default = $this->reflector->getDefaultValue(); if (is_null($default)) { $default = 'null'; } elseif (is_bool($default)) { $default = $default ? 'true' : 'false'; } elseif (is_string($default)) { $default = "'" . $default . "'"; } elseif (is_numeric($default)) { $default = strval($default); } elseif (is_array($default)) { $default = 'array()'; } else { echo 'Warning: unknown default type for ' . $this->getMethod()->getFullName() . PHP_EOL; var_dump($default); $default = 'null'; } $code .= ' = ' . $default; } return $code; } public function getInvocation() { return '$' . $this->reflector->name; } public function getMethod() { return $this->method; } } file = $file; $this->indent = $indent; } abstract public function addCall(FactoryCall $call); abstract public function build(); public function addFileHeader() { $this->code = ''; $this->addPart('file_header'); } public function addPart($name) { $this->addCode($this->readPart($name)); } public function addCode($code) { $this->code .= $code; } public function readPart($name) { return file_get_contents(__DIR__ . "/parts/$name.txt"); } public function generateFactoryCall(FactoryCall $call) { $method = $call->getMethod(); $code = $method->getComment($this->indent) . PHP_EOL; $code .= $this->generateDeclaration($call->getName(), $method); // $code .= $this->generateImport($method); $code .= $this->generateCall($method); $code .= $this->generateClosing(); return $code; } public function generateDeclaration($name, FactoryMethod $method) { $code = $this->indent . $this->getDeclarationModifiers() . 'function ' . $name . '(' . $this->generateDeclarationArguments($method) . ')' . PHP_EOL . $this->indent . '{' . PHP_EOL; return $code; } public function getDeclarationModifiers() { return ''; } public function generateDeclarationArguments(FactoryMethod $method) { if ($method->acceptsVariableArguments()) { return '/* args... */'; } else { return $method->getParameterDeclarations(); } } public function generateImport(FactoryMethod $method) { return $this->indent . self::INDENT . "require_once '" . $method->getClass()->getFile() . "';" . PHP_EOL; } public function generateCall(FactoryMethod $method) { $code = ''; if ($method->acceptsVariableArguments()) { $code .= $this->indent . self::INDENT . '$args = func_get_args();' . PHP_EOL; } $code .= $this->indent . self::INDENT . 'return '; if ($method->acceptsVariableArguments()) { $code .= 'call_user_func_array(array(\'' . '\\' . $method->getClassName() . '\', \'' . $method->getName() . '\'), $args);' . PHP_EOL; } else { $code .= '\\' . $method->getClassName() . '::' . $method->getName() . '(' . $method->getParameterInvocations() . ');' . PHP_EOL; } return $code; } public function generateClosing() { return $this->indent . '}' . PHP_EOL; } public function write() { file_put_contents($this->file, $this->code); } } method = $method; $this->name = $name; } public function getMethod() { return $this->method; } public function getName() { return $this->name; } } */ class Manager { /** * The update manifest. * * @var Manifest */ private $manifest; /** * The running file (the Phar that will be updated). * * @var string */ private $runningFile; /** * Sets the update manifest. * * @param Manifest $manifest The manifest. */ public function __construct(Manifest $manifest) { $this->manifest = $manifest; } /** * Returns the manifest. * * @return Manifest The manifest. */ public function getManifest() { return $this->manifest; } /** * Returns the running file (the Phar that will be updated). * * @return string The file. */ public function getRunningFile() { if (null === $this->runningFile) { $this->runningFile = realpath($_SERVER['argv'][0]); } return $this->runningFile; } /** * Sets the running file (the Phar that will be updated). * * @param string $file The file name or path. * * @throws Exception\Exception * @throws InvalidArgumentException If the file path is invalid. */ public function setRunningFile($file) { if (false === is_file($file)) { throw InvalidArgumentException::create( 'The file "%s" is not a file or it does not exist.', $file ); } $this->runningFile = $file; } /** * Updates the running Phar if any is available. * * @param string|Version $version The current version. * @param boolean $major Lock to current major version? * @param boolean $pre Allow pre-releases? * * @return boolean TRUE if an update was performed, FALSE if none available. */ public function update($version, $major = false, $pre = false) { if (false === ($version instanceof Version)) { $version = Version::create($version); } if (null !== ($update = $this->manifest->findRecent( $version, $major, $pre ))) { $update->getFile(); $update->copyTo($this->getRunningFile()); return true; } return false; } } */ class Manifest { /** * The list of updates in the manifest. * * @var Update[] */ private $updates; /** * Sets the list of updates from the manifest. * * @param Update[] $updates The updates. */ public function __construct(array $updates = array()) { $this->updates = $updates; } /** * Finds the most recent update and returns it. * * @param Version $version The current version. * @param boolean $major Lock to major version? * @param boolean $pre Allow pre-releases? * * @return Update The update. */ public function findRecent(Version $version, $major = false, $pre = false) { /** @var $current Update */ $current = null; $major = $major ? $version->getMajor() : null; foreach ($this->updates as $update) { if ($major && ($major !== $update->getVersion()->getMajor())) { continue; } if ((false === $pre) && (null !== $update->getVersion()->getPreRelease())) { continue; } $test = $current ? $current->getVersion() : $version; if (false === $update->isNewer($test)) { continue; } $current = $update; } return $current; } /** * Returns the list of updates in the manifest. * * @return Update[] The updates. */ public function getUpdates() { return $this->updates; } /** * Loads the manifest from a JSON encoded string. * * @param string $json The JSON encoded string. * * @return Manifest The manifest. */ public static function load($json) { $j = new Json(); return self::create($j->decode($json), $j); } /** * Loads the manifest from a JSON encoded file. * * @param string $file The JSON encoded file. * * @return Manifest The manifest. */ public static function loadFile($file) { $json = new Json(); return self::create($json->decodeFile($file), $json); } /** * Validates the data, processes it, and returns a new instance of Manifest. * * @param array $decoded The decoded JSON data. * @param Json $json The Json instance used to decode the data. * * @return Manifest The new instance. */ private static function create($decoded, Json $json) { $json->validate( $json->decodeFile(PHAR_UPDATE_MANIFEST_SCHEMA), $decoded ); $updates = array(); foreach ($decoded as $update) { $updates[] = new Update( $update->name, $update->sha1, $update->url, Version::create($update->version), isset($update->publicKey) ? $update->publicKey : null ); } usort($updates, function (Update $a, Update $b) { return $a->getVersion()->compareTo($b->getVersion()); }); return new static($updates); } } */ interface ExceptionInterface { } */ class Exception extends \Exception implements ExceptionInterface { /** * Creates a new exception using a format and values. * * @param string $format The format. * @param mixed $value,... The value(s). * * @return Exception The exception. */ public static function create($format, $value = null) { if (0 < func_num_args()) { $format = vsprintf($format, array_slice(func_get_args(), 1)); } return new static($format); } /** * Creates an exception for the last error message. * * @return Exception The exception. */ public static function lastError() { $error = error_get_last(); return new static($error['message']); } } */ class InvalidArgumentException extends Exception { } */ class LogicException extends Exception { } */ class FileException extends Exception { } */ class Update { /** * The temporary file path. * * @var string */ private $file; /** * The name of the update file. * * @var string */ private $name; /** * The URL where the public key can be downloaded from. * * @var string */ private $publicKey; /** * The SHA1 file checksum. * * @var string */ private $sha1; /** * The URL where the update can be downloaded from. * * @var string */ private $url; /** * The version of the update. * * @var Version */ private $version; /** * Sets the update information. * * @param string $name The name of the update file. * @param string $sha1 The SHA1 file checksum. * @param string $url The URL where the update can be downloaded from. * @param Version $version The version of the update. * @param string $key The URL where the public key can be downloaded * from. */ public function __construct( $name, $sha1, $url, Version $version, $key = null ) { $this->name = $name; $this->publicKey = $key; $this->sha1 = $sha1; $this->url = $url; $this->version = $version; } /** * Copies the update file to the destination. * * @param string $file The target file. * * @throws Exception\Exception * @throws FileException If the file could not be replaced. */ public function copyTo($file) { if (null === $this->file) { throw LogicException::create( 'The update file has not been downloaded.' ); } $mode = 0755; if (file_exists($file)) { $mode = fileperms($file) & 511; } if (false === @copy($this->file, $file)) { throw FileException::lastError(); } if (false === @chmod($file, $mode)) { throw FileException::lastError(); } $key = $file . '.pubkey'; if (file_exists($this->file . '.pubkey')) { if (false === @copy($this->file . '.pubkey', $key)) { throw FileException::lastError(); } } elseif (file_exists($key)) { if (false === @unlink($key)) { throw FileException::lastError(); } } } /** * Cleans up by deleting the temporary update file. * * @throws FileException If the file could not be deleted. */ public function deleteFile() { if ($this->file) { if (file_exists($this->file)) { if (false === @unlink($this->file)) { throw FileException::lastError(); } } if (file_exists($this->file . '.pubkey')) { if (false === @unlink($this->file . '.pubkey')) { throw FileException::lastError(); } } $dir = dirname($this->file); if (file_exists($dir)) { if (false === @rmdir($dir)) { throw FileException::lastError(); } } $this->file = null; } } /** * Downloads the update file to a temporary location. * * @return string The temporary file path. * * @throws Exception\Exception * @throws FileException If the SHA1 checksum differs. * @throws UnexpectedValueException If the Phar is corrupt. */ public function getFile() { if (null === $this->file) { unlink($this->file = tempnam(sys_get_temp_dir(), 'upd')); mkdir($this->file); $this->file .= DIRECTORY_SEPARATOR . $this->name; $in = new SplFileObject($this->url, 'rb', false); $out = new SplFileObject($this->file, 'wb', false); while (false === $in->eof()) { $out->fwrite($in->fgets()); } unset($in, $out); if ($this->publicKey) { $in = new SplFileObject($this->publicKey, 'r', false); $out = new SplFileObject($this->file . '.pubkey', 'w', false); while (false === $in->eof()) { $out->fwrite($in->fgets()); } unset($in, $out); } if ($this->sha1 !== ($sha1 = sha1_file($this->file))) { $this->deleteFile(); throw FileException::create( 'Mismatch of the SHA1 checksum (%s) of the downloaded file (%s).', $this->sha1, $sha1 ); } // double check try { new Phar($this->file); } catch (UnexpectedValueException $exception) { $this->deleteFile(); throw $exception; } } return $this->file; } /** * Returns name of the update file. * * @return string The name. */ public function getName() { return $this->name; } /** * Returns the URL where the public key can be downloaded from. * * @return string The URL. */ public function getPublicKey() { return $this->publicKey; } /** * Returns the SHA1 file checksum. * * @return string The checksum. */ public function getSha1() { return $this->sha1; } /** * Returns the URL where the update can be downloaded from. * * @return string The URL. */ public function getUrl() { return $this->url; } /** * Returns the version of the update. * * @return Version The version. */ public function getVersion() { return $this->version; } /** * Checks if this update is newer than the version given. * * @param Version $version The current version. * * @return boolean TRUE if the update is newer, FALSE if not. */ public function isNewer(Version $version) { return $this->version->isGreaterThan($version); } } =')); } */ class Json { /** * The JSON linter. * * @var JsonParser */ private $linter; /** * The JSON validator. * * @var Validator */ private $validator; /** * Initialize the linter and validator. */ public function __construct() { $this->linter = new JsonParser(); $this->validator = new Validator(); } /** * Decodes the JSON string and performs a lint check if decoding fails. * * @param string $json The JSON data. * @param boolean $assoc Convert objects to associative arrays? * @param integer $depth The maximum recursion depth. * @param integer $options The bitmask JSON decode options (PHP 5.4+). * * @return mixed The decoded data. * * @throws Exception\Exception * @throws JsonException If the JSON string could not be decoded. */ public function decode($json, $assoc = false, $depth = 512, $options = 0) { if (JSON_DECODE_FOURTH_ARG) { $data = json_decode($json, $assoc, $depth, $options); } else { $data = json_decode($json, $assoc, $depth); } if (JSON_ERROR_NONE !== ($error = json_last_error())) { if (JSON_ERROR_UTF8 === $error) { throw JsonException::createUsingCode($error); } $this->lint($json); // @codeCoverageIgnoreStart } // @codeCoverageIgnoreEnd return $data; } /** * Reads the file and decodes the contents using `decode()`. * * @param string $file The file location. * @param boolean $assoc Convert objects to associative arrays? * @param integer $depth The maximum recursion depth. * @param integer $options The bitmask JSON decode options (PHP 5.4+). * * @return mixed The decoded data. * * @throws Exception\Exception * @throws FileException If the file could not be read. */ public function decodeFile( $file, $assoc = false, $depth = 512, $options = 0 ) { if ((false == preg_match('/^\w+:\/\//', $file)) && (false === is_file($file))) { throw FileException::create( 'The path "%s" is not a file or does not exist.', $file ); } if (false === ($json = @file_get_contents($file))) { throw FileException::lastError(); } return $this->decode($json, $assoc, $depth, $options); } /** * Lints the JSON string. * * @param string $json The JSON data. * * @throws ParsingException If the JSON has lint. */ public function lint($json) { if (($result = $this->linter->lint($json)) instanceof ParsingException) { throw $result; } } /** * Validates the decoded JSON data. * * @param object $schema The JSON schema. * @param mixed $json The decoded JSON data. * * @throws Exception\Exception * @throws JsonException If the JSON data failed validation. */ public function validate($schema, $json) { $this->validator->check($json, $schema); if (false === $this->validator->isValid()) { $errors = array(); foreach ($this->validator->getErrors() as $error) { if (false === empty($error['property'])) { $error['message'] = $error['property'] . ': ' . $error['message']; } $errors[] = $error['message']; } throw new JsonException( 'The JSON data did not pass validation.', $errors ); } } } */ interface ExceptionInterface { } */ class Exception extends \Exception implements ExceptionInterface { /** * Creates a new exception using a format and values. * * @param string $format The format. * @param mixed $value,... The value(s). * * @return Exception The exception. */ public static function create($format, $value = null) { if (0 < func_num_args()) { $format = vsprintf($format, array_slice(func_get_args(), 1)); } return new static($format); } /** * Creates an exception for the last error message. * * @return Exception The exception. */ public static function lastError() { $error = error_get_last(); return new static($error['message']); } } */ class FileException extends Exception { } */ class JsonException extends Exception { /** * The recognized JSON error codes. * * @var array */ private static $codes = array( JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded.', JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded.', JSON_ERROR_NONE => 'No error has occurred.', JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON.', JSON_ERROR_SYNTAX => 'Syntax error.', JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded.' ); /** * The individual JSON error messages. * * @var array */ private $errors = array(); /** * Sets the main error message, and the other error messages. * * @param string $message The main error message. * @param array $errors The other error messages. */ public function __construct($message, array $errors = array()) { $this->errors = $errors; parent::__construct($message); } /** * Creates a new exception using the JSON error code. * * @param integer $code The code. * * @return JsonException The exception. */ public static function createUsingCode($code) { $message = 'Unknown error.'; if (isset(self::$codes[$code])) { $message = self::$codes[$code]; } return new static($message); } /** * Returns the other error messages. * * @return array The messages. */ public function getErrors() { return $this->errors; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Seld\JsonLint; /** * Lexer class * * Ported from https://github.com/zaach/jsonlint */ class Lexer { private $EOF = 1; private $rules = array( 0 => '/^\s+/', 1 => '/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/', 2 => '{^"(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x09\x0a-\x1f\\\\"]+)*"}', 3 => '/^\{/', 4 => '/^\}/', 5 => '/^\[/', 6 => '/^\]/', 7 => '/^,/', 8 => '/^:/', 9 => '/^true\b/', 10 => '/^false\b/', 11 => '/^null\b/', 12 => '/^$/', 13 => '/^./', ); private $conditions = array( "INITIAL" => array( "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13), "inclusive" => true, ), ); private $conditionStack; private $input; private $more; private $done; private $matched; public $match; public $yylineno; public $yyleng; public $yytext; public $yylloc; public function lex() { $r = $this->next(); if (!$r instanceof Undefined) { return $r; } return $this->lex(); } public function setInput($input) { $this->input = $input; $this->more = false; $this->done = false; $this->yylineno = $this->yyleng = 0; $this->yytext = $this->matched = $this->match = ''; $this->conditionStack = array('INITIAL'); $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0); return $this; } public function showPosition() { $pre = str_replace("\n", '', $this->getPastInput()); $c = str_repeat('-', max(0, strlen($pre) - 1)); // new Array(pre.length + 1).join("-"); return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^"; } public function getPastInput() { $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match)); return (strlen($past) > 20 ? '...' : '') . substr($past, -20); } public function getUpcomingInput() { $next = $this->match; if (strlen($next) < 20) { $next .= substr($this->input, 0, 20 - strlen($next)); } return substr($next, 0, 20) . (strlen($next) > 20 ? '...' : ''); } protected function parseError($str, $hash) { throw new \Exception($str); } private function next() { if ($this->done) { return $this->EOF; } if (!$this->input) { $this->done = true; } $token = null; $match = null; $col = null; $lines = null; if (!$this->more) { $this->yytext = ''; $this->match = ''; } $rules = $this->getCurrentRules(); $rulesLen = count($rules); for ($i=0; $i < $rulesLen; $i++) { if (preg_match($this->rules[$rules[$i]], $this->input, $match)) { preg_match_all('/\n.*/', $match[0], $lines); $lines = $lines[0]; if ($lines) { $this->yylineno += count($lines); } $this->yylloc = array( 'first_line' => $this->yylloc['last_line'], 'last_line' => $this->yylineno+1, 'first_column' => $this->yylloc['last_column'], 'last_column' => $lines ? strlen($lines[count($lines) - 1]) - 1 : $this->yylloc['last_column'] + strlen($match[0]), ); $this->yytext .= $match[0]; $this->match .= $match[0]; $this->yyleng = strlen($this->yytext); $this->more = false; $this->input = substr($this->input, strlen($match[0])); $this->matched .= $match[0]; $token = $this->performAction($rules[$i], $this->conditionStack[count($this->conditionStack)-1]); if ($token) { return $token; } return new Undefined(); } } if ($this->input === "") { return $this->EOF; } $this->parseError( 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(), array( 'text' => "", 'token' => null, 'line' => $this->yylineno, ) ); } private function getCurrentRules() { return $this->conditions[$this->conditionStack[count($this->conditionStack)-1]]['rules']; } private function performAction($avoiding_name_collisions, $YY_START) { switch ($avoiding_name_collisions) { case 0:/* skip whitespace */ break; case 1: return 6; break; case 2: $this->yytext = substr($this->yytext, 1, $this->yyleng-2); return 4; case 3: return 17; case 4: return 18; case 5: return 23; case 6: return 24; case 7: return 22; case 8: return 21; case 9: return 10; case 10: return 11; case 11: return 8; case 12: return 14; case 13: return 'INVALID'; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Seld\JsonLint; class Undefined { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Seld\JsonLint; class ParsingException extends \Exception { protected $details; public function __construct($message, $details = array()) { $this->details = $details; parent::__construct($message); } public function getDetails() { return $this->details; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Seld\JsonLint; use stdClass; /** * Parser class * * Example: * * $parser = new JsonParser(); * // returns null if it's valid json, or an error object * $parser->lint($json); * // returns parsed json, like json_decode does, but slower, throws exceptions on failure. * $parser->parse($json); * * Ported from https://github.com/zaach/jsonlint */ class JsonParser { const DETECT_KEY_CONFLICTS = 1; const ALLOW_DUPLICATE_KEYS = 2; const PARSE_TO_ASSOC = 4; private $lexer; private $flags; private $stack; private $vstack; // semantic value stack private $lstack; // location stack private $symbols = array( 'error' => 2, 'JSONString' => 3, 'STRING' => 4, 'JSONNumber' => 5, 'NUMBER' => 6, 'JSONNullLiteral' => 7, 'NULL' => 8, 'JSONBooleanLiteral' => 9, 'TRUE' => 10, 'FALSE' => 11, 'JSONText' => 12, 'JSONValue' => 13, 'EOF' => 14, 'JSONObject' => 15, 'JSONArray' => 16, '{' => 17, '}' => 18, 'JSONMemberList' => 19, 'JSONMember' => 20, ':' => 21, ',' => 22, '[' => 23, ']' => 24, 'JSONElementList' => 25, '$accept' => 0, '$end' => 1, ); private $terminals_ = array( 2 => "error", 4 => "STRING", 6 => "NUMBER", 8 => "NULL", 10 => "TRUE", 11 => "FALSE", 14 => "EOF", 17 => "{", 18 => "}", 21 => ":", 22 => ",", 23 => "[", 24 => "]", ); private $productions_ = array( 0, array(3, 1), array(5, 1), array(7, 1), array(9, 1), array(9, 1), array(12, 2), array(13, 1), array(13, 1), array(13, 1), array(13, 1), array(13, 1), array(13, 1), array(15, 2), array(15, 3), array(20, 3), array(19, 1), array(19, 3), array(16, 2), array(16, 3), array(25, 1), array(25, 3) ); private $table = array(array(3 => 5, 4 => array(1,12), 5 => 6, 6 => array(1,13), 7 => 3, 8 => array(1,9), 9 => 4, 10 => array(1,10), 11 => array(1,11), 12 => 1, 13 => 2, 15 => 7, 16 => 8, 17 => array(1,14), 23 => array(1,15)), array( 1 => array(3)), array( 14 => array(1,16)), array( 14 => array(2,7), 18 => array(2,7), 22 => array(2,7), 24 => array(2,7)), array( 14 => array(2,8), 18 => array(2,8), 22 => array(2,8), 24 => array(2,8)), array( 14 => array(2,9), 18 => array(2,9), 22 => array(2,9), 24 => array(2,9)), array( 14 => array(2,10), 18 => array(2,10), 22 => array(2,10), 24 => array(2,10)), array( 14 => array(2,11), 18 => array(2,11), 22 => array(2,11), 24 => array(2,11)), array( 14 => array(2,12), 18 => array(2,12), 22 => array(2,12), 24 => array(2,12)), array( 14 => array(2,3), 18 => array(2,3), 22 => array(2,3), 24 => array(2,3)), array( 14 => array(2,4), 18 => array(2,4), 22 => array(2,4), 24 => array(2,4)), array( 14 => array(2,5), 18 => array(2,5), 22 => array(2,5), 24 => array(2,5)), array( 14 => array(2,1), 18 => array(2,1), 21 => array(2,1), 22 => array(2,1), 24 => array(2,1)), array( 14 => array(2,2), 18 => array(2,2), 22 => array(2,2), 24 => array(2,2)), array( 3 => 20, 4 => array(1,12), 18 => array(1,17), 19 => 18, 20 => 19 ), array( 3 => 5, 4 => array(1,12), 5 => 6, 6 => array(1,13), 7 => 3, 8 => array(1,9), 9 => 4, 10 => array(1,10), 11 => array(1,11), 13 => 23, 15 => 7, 16 => 8, 17 => array(1,14), 23 => array(1,15), 24 => array(1,21), 25 => 22 ), array( 1 => array(2,6)), array( 14 => array(2,13), 18 => array(2,13), 22 => array(2,13), 24 => array(2,13)), array( 18 => array(1,24), 22 => array(1,25)), array( 18 => array(2,16), 22 => array(2,16)), array( 21 => array(1,26)), array( 14 => array(2,18), 18 => array(2,18), 22 => array(2,18), 24 => array(2,18)), array( 22 => array(1,28), 24 => array(1,27)), array( 22 => array(2,20), 24 => array(2,20)), array( 14 => array(2,14), 18 => array(2,14), 22 => array(2,14), 24 => array(2,14)), array( 3 => 20, 4 => array(1,12), 20 => 29 ), array( 3 => 5, 4 => array(1,12), 5 => 6, 6 => array(1,13), 7 => 3, 8 => array(1,9), 9 => 4, 10 => array(1,10), 11 => array(1,11), 13 => 30, 15 => 7, 16 => 8, 17 => array(1,14), 23 => array(1,15)), array( 14 => array(2,19), 18 => array(2,19), 22 => array(2,19), 24 => array(2,19)), array( 3 => 5, 4 => array(1,12), 5 => 6, 6 => array(1,13), 7 => 3, 8 => array(1,9), 9 => 4, 10 => array(1,10), 11 => array(1,11), 13 => 31, 15 => 7, 16 => 8, 17 => array(1,14), 23 => array(1,15)), array( 18 => array(2,17), 22 => array(2,17)), array( 18 => array(2,15), 22 => array(2,15)), array( 22 => array(2,21), 24 => array(2,21)), ); private $defaultActions = array( 16 => array(2, 6) ); /** * @param string $input JSON string * @return null|ParsingException null if no error is found, a ParsingException containing all details otherwise */ public function lint($input) { try { $this->parse($input); } catch (ParsingException $e) { return $e; } } /** * @param string $input JSON string * @return mixed * @throws ParsingException */ public function parse($input, $flags = 0) { $this->failOnBOM($input); $this->flags = $flags; $this->stack = array(0); $this->vstack = array(null); $this->lstack = array(); $yytext = ''; $yylineno = 0; $yyleng = 0; $recovering = 0; $TERROR = 2; $EOF = 1; $this->lexer = new Lexer(); $this->lexer->setInput($input); $yyloc = $this->lexer->yylloc; $this->lstack[] = $yyloc; $symbol = null; $preErrorSymbol = null; $state = null; $action = null; $a = null; $r = null; $yyval = new stdClass; $p = null; $len = null; $newState = null; $expected = null; $errStr = null; while (true) { // retreive state number from top of stack $state = $this->stack[count($this->stack)-1]; // use default actions if available if (isset($this->defaultActions[$state])) { $action = $this->defaultActions[$state]; } else { if ($symbol == null) { $symbol = $this->lex(); } // read action for current state and first input $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false; } // handle parse error if (!$action || !$action[0]) { if (!$recovering) { // Report error $expected = array(); foreach ($this->table[$state] as $p => $ignore) { if (isset($this->terminals_[$p]) && $p > 2) { $expected[] = "'" . $this->terminals_[$p] . "'"; } } $message = null; if (in_array("'STRING'", $expected) && in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) { $message = "Invalid string"; if ("'" === substr($this->lexer->match, 0, 1)) { $message .= ", it appears you used single quotes instead of double quotes"; } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) { $message .= ", it appears you have an unescaped backslash at: ".$match[1]; } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) { $message .= ", it appears you forgot to terminated the string, or attempted to write a multiline string which is invalid"; } } $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n"; $errStr .= $this->lexer->showPosition() . "\n"; if ($message) { $errStr .= $message; } else { $errStr .= (count($expected) > 1) ? "Expected one of: " : "Expected: "; $errStr .= implode(', ', $expected); } if (',' === substr(trim($this->lexer->getPastInput()), -1)) { $errStr .= " - It appears you have an extra trailing comma"; } $this->parseError($errStr, array( 'text' => $this->lexer->match, 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol, 'line' => $this->lexer->yylineno, 'loc' => $yyloc, 'expected' => $expected, )); } // just recovered from another error if ($recovering == 3) { if ($symbol == $EOF) { throw new ParsingException($errStr ?: 'Parsing halted.'); } // discard current lookahead and grab another $yyleng = $this->lexer->yyleng; $yytext = $this->lexer->yytext; $yylineno = $this->lexer->yylineno; $yyloc = $this->lexer->yylloc; $symbol = $this->lex(); } // try to recover from error while (true) { // check for error recovery rule in this state if (array_key_exists($TERROR, $this->table[$state])) { break; } if ($state == 0) { throw new ParsingException($errStr ?: 'Parsing halted.'); } $this->popStack(1); $state = $this->stack[count($this->stack)-1]; } $preErrorSymbol = $symbol; // save the lookahead token $symbol = $TERROR; // insert generic error symbol as new lookahead $state = $this->stack[count($this->stack)-1]; $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false; $recovering = 3; // allow 3 real symbols to be shifted before reporting a new error } // this shouldn't happen, unless resolve defaults are off if (is_array($action[0]) && count($action) > 1) { throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol); } switch ($action[0]) { case 1: // shift $this->stack[] = $symbol; $this->vstack[] = $this->lexer->yytext; $this->lstack[] = $this->lexer->yylloc; $this->stack[] = $action[1]; // push state $symbol = null; if (!$preErrorSymbol) { // normal execution/no error $yyleng = $this->lexer->yyleng; $yytext = $this->lexer->yytext; $yylineno = $this->lexer->yylineno; $yyloc = $this->lexer->yylloc; if ($recovering > 0) { $recovering--; } } else { // error just occurred, resume old lookahead f/ before error $symbol = $preErrorSymbol; $preErrorSymbol = null; } break; case 2: // reduce $len = $this->productions_[$action[1]][1]; // perform semantic action $yyval->token = $this->vstack[count($this->vstack) - $len]; // default to $$ = $1 // default location, uses first token for firsts, last for lasts $yyval->store = array( // _$ = store 'first_line' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_line'], 'last_line' => $this->lstack[count($this->lstack) - 1]['last_line'], 'first_column' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_column'], 'last_column' => $this->lstack[count($this->lstack) - 1]['last_column'], ); $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack); if (!$r instanceof Undefined) { return $r; } if ($len) { $this->popStack($len); } $this->stack[] = $this->productions_[$action[1]][0]; // push nonterminal (reduce) $this->vstack[] = $yyval->token; $this->lstack[] = $yyval->store; $newState = $this->table[$this->stack[count($this->stack)-2]][$this->stack[count($this->stack)-1]]; $this->stack[] = $newState; break; case 3: // accept return true; } } return true; } protected function parseError($str, $hash) { throw new ParsingException($str, $hash); } // $$ = $tokens // needs to be passed by ref? // $ = $token // _$ removed, useless? private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens) { // $0 = $len $len = count($tokens) - 1; switch ($yystate) { case 1: $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext); $yyval->token = $yytext; break; case 2: if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) { $yyval->token = floatval($yytext); } else { $yyval->token = strpos($yytext, '.') === false ? intval($yytext) : floatval($yytext); } break; case 3: $yyval->token = null; break; case 4: $yyval->token = true; break; case 5: $yyval->token = false; break; case 6: return $yyval->token = $tokens[$len-1]; case 13: if ($this->flags & self::PARSE_TO_ASSOC) { $yyval->token = array(); } else { $yyval->token = new stdClass; } break; case 14: $yyval->token = $tokens[$len-1]; break; case 15: $yyval->token = array($tokens[$len-2], $tokens[$len]); break; case 16: $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0]; if ($this->flags & self::PARSE_TO_ASSOC) { $yyval->token = array(); $yyval->token[$property] = $tokens[$len][1]; } else { $yyval->token = new stdClass; $yyval->token->$property = $tokens[$len][1]; } break; case 17: if ($this->flags & self::PARSE_TO_ASSOC) { $yyval->token =& $tokens[$len-2]; $key = $tokens[$len][0]; if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) { $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n"; $errStr .= $this->lexer->showPosition() . "\n"; $errStr .= "Duplicate key: ".$tokens[$len][0]; throw new ParsingException($errStr); } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) { $duplicateCount = 1; do { $duplicateKey = $key . '.' . $duplicateCount++; } while (isset($tokens[$len-2][$duplicateKey])); $key = $duplicateKey; } $tokens[$len-2][$key] = $tokens[$len][1]; } else { $yyval->token = $tokens[$len-2]; $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0]; if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) { $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n"; $errStr .= $this->lexer->showPosition() . "\n"; $errStr .= "Duplicate key: ".$tokens[$len][0]; throw new ParsingException($errStr); } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) { $duplicateCount = 1; do { $duplicateKey = $key . '.' . $duplicateCount++; } while (isset($tokens[$len-2]->$duplicateKey)); $key = $duplicateKey; } $tokens[$len-2]->$key = $tokens[$len][1]; } break; case 18: $yyval->token = array(); break; case 19: $yyval->token = $tokens[$len-1]; break; case 20: $yyval->token = array($tokens[$len]); break; case 21: $tokens[$len-2][] = $tokens[$len]; $yyval->token = $tokens[$len-2]; break; } return new Undefined(); } private function stringInterpolation($match) { switch ($match[0]) { case '\\\\': return '\\'; case '\"': return '"'; case '\b': return chr(8); case '\f': return chr(12); case '\n': return "\n"; case '\r': return "\r"; case '\t': return "\t"; case '\/': return "/"; default: return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', 0, 'UTF-8'); } } private function popStack($n) { $this->stack = array_slice($this->stack, 0, - (2 * $n)); $this->vstack = array_slice($this->vstack, 0, - $n); $this->lstack = array_slice($this->lstack, 0, - $n); } private function lex() { $token = $this->lexer->lex() ?: 1; // $end = 1 // if token isn't its numeric value, convert if (!is_numeric($token)) { $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token; } return $token; } private function failOnBOM($input) { // UTF-8 ByteOrderMark sequence $bom = "\xEF\xBB\xBF"; if (substr($input, 0, 3) === $bom) { $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array()); } } } '{ ... }', * 'http://acme.com/schemas/address#' => '{ ... }', * )) * * $schema = $retriever->retrieve('http://acme.com/schemas/person#'); */ class PredefinedArray extends AbstractRetriever { /** * Contains schemas as URI => JSON * @var array */ private $schemas; /** * Constructor * * @param array $schemas * @param string $contentType */ public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE) { $this->schemas = $schemas; $this->contentType = $contentType; } /** * {@inheritDoc} * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::retrieve() */ public function retrieve($uri) { if (!array_key_exists($uri, $this->schemas)) { throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf( 'The JSON schema "%s" was not found.', $uri )); } return $this->schemas[$uri]; } } */ interface UriRetrieverInterface { /** * Retrieve a schema from the specified URI * @param string $uri URI that resolves to a JSON schema * @throws \JsonSchema\Exception\ResourceNotFoundException * @return mixed string|null */ public function retrieve($uri); /** * Get media content type * @return string */ public function getContentType(); } */ class Curl extends AbstractRetriever { protected $messageBody; public function __construct() { if (!function_exists('curl_init')) { throw new \RuntimeException("cURL not installed"); } } /** * {@inheritDoc} * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::retrieve() */ public function retrieve($uri) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $uri); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE)); $response = curl_exec($ch); if (false === $response) { throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found'); } $this->fetchMessageBody($response); $this->fetchContentType($response); curl_close($ch); return $this->messageBody; } /** * @param string $response cURL HTTP response */ private function fetchMessageBody($response) { preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match); $this->messageBody = $match[1]; } /** * @param string $response cURL HTTP response * @return boolean Whether the Content-Type header was found or not */ protected function fetchContentType($response) { if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) { $this->contentType = trim($match[1]); return true; } return false; } } */ class FileGetContents extends AbstractRetriever { protected $messageBody; /** * {@inheritDoc} * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::retrieve() */ public function retrieve($uri) { $context = stream_context_create(array( 'http' => array( 'method' => 'GET', 'header' => "Accept: " . Validator::SCHEMA_MEDIA_TYPE ))); set_error_handler(function() use ($uri) { throw new ResourceNotFoundException('JSON schema not found at ' . $uri); }); $response = file_get_contents($uri); restore_error_handler(); if (false === $response) { throw new ResourceNotFoundException('JSON schema not found at ' . $uri); } if ($response == '' && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/' ) { throw new ResourceNotFoundException('JSON schema not found at ' . $uri); } $this->messageBody = $response; if (! empty($http_response_header)) { $this->fetchContentType($http_response_header); } else { // Could be a "file://" url or something else - fake up the response $this->contentType = null; } return $this->messageBody; } /** * @param array $headers HTTP Response Headers * @return boolean Whether the Content-Type header was found or not */ private function fetchContentType(array $headers) { foreach ($headers as $header) { if ($this->contentType = self::getContentTypeMatchInHeader($header)) { return true; } } return false; } /** * @param string $header * @return string|null */ protected static function getContentTypeMatchInHeader($header) { if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) { return trim($match[1]); } } } */ abstract class AbstractRetriever implements UriRetrieverInterface { /** * Media content type * @var string */ protected $contentType; /** * {@inheritDoc} * @see \JsonSchema\Uri\Retrievers\UriRetrieverInterface::getContentType() */ public function getContentType() { return $this->contentType; } } */ class UriRetriever { /** * @var null|UriRetrieverInterface */ protected $uriRetriever = null; /** * @var array|object[] * @see loadSchema */ private $schemaCache = array(); /** * Guarantee the correct media type was encountered * * @param UriRetrieverInterface $uriRetriever * @param string $uri * @return bool|void */ public function confirmMediaType($uriRetriever, $uri) { $contentType = $uriRetriever->getContentType(); if (is_null($contentType)) { // Well, we didn't get an invalid one return; } if (Validator::SCHEMA_MEDIA_TYPE === $contentType) { return; } if (substr($uri, 0, 23) == 'http://json-schema.org/') { //HACK; they deliver broken content types return true; } throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE)); } /** * Get a URI Retriever * * If none is specified, sets a default FileGetContents retriever and * returns that object. * * @return UriRetrieverInterface */ public function getUriRetriever() { if (is_null($this->uriRetriever)) { $this->setUriRetriever(new FileGetContents); } return $this->uriRetriever; } /** * Resolve a schema based on pointer * * URIs can have a fragment at the end in the format of * #/path/to/object and we are to look up the 'path' property of * the first object then the 'to' and 'object' properties. * * @param object $jsonSchema JSON Schema contents * @param string $uri JSON Schema URI * @return object JSON Schema after walking down the fragment pieces * * @throws ResourceNotFoundException */ public function resolvePointer($jsonSchema, $uri) { $resolver = new UriResolver(); $parsed = $resolver->parse($uri); if (empty($parsed['fragment'])) { return $jsonSchema; } $path = explode('/', $parsed['fragment']); while ($path) { $pathElement = array_shift($path); if (! empty($pathElement)) { $pathElement = str_replace('~1', '/', $pathElement); $pathElement = str_replace('~0', '~', $pathElement); if (! empty($jsonSchema->$pathElement)) { $jsonSchema = $jsonSchema->$pathElement; } else { throw new ResourceNotFoundException( 'Fragment "' . $parsed['fragment'] . '" not found' . ' in ' . $uri ); } if (! is_object($jsonSchema)) { throw new ResourceNotFoundException( 'Fragment part "' . $pathElement . '" is no object ' . ' in ' . $uri ); } } } return $jsonSchema; } /** * Retrieve a URI * * @param string $uri JSON Schema URI * @param string|null $baseUri * @return object JSON Schema contents */ public function retrieve($uri, $baseUri = null) { $resolver = new UriResolver(); $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri); //fetch URL without #fragment $arParts = $resolver->parse($resolvedUri); if (isset($arParts['fragment'])) { unset($arParts['fragment']); $fetchUri = $resolver->generate($arParts); } $jsonSchema = $this->loadSchema($fetchUri); // Use the JSON pointer if specified $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri); if ($jsonSchema instanceof \stdClass) { $jsonSchema->id = $resolvedUri; } return $jsonSchema; } /** * Fetch a schema from the given URI, json-decode it and return it. * Caches schema objects. * * @param string $fetchUri Absolute URI * * @return object JSON schema object */ protected function loadSchema($fetchUri) { if (isset($this->schemaCache[$fetchUri])) { return $this->schemaCache[$fetchUri]; } $uriRetriever = $this->getUriRetriever(); $contents = $this->uriRetriever->retrieve($fetchUri); $this->confirmMediaType($uriRetriever, $fetchUri); $jsonSchema = json_decode($contents); if (JSON_ERROR_NONE < $error = json_last_error()) { throw new JsonDecodingException($error); } $this->schemaCache[$fetchUri] = $jsonSchema; return $jsonSchema; } /** * Set the URI Retriever * * @param UriRetrieverInterface $uriRetriever * @return $this for chaining */ public function setUriRetriever(UriRetrieverInterface $uriRetriever) { $this->uriRetriever = $uriRetriever; return $this; } /** * Parses a URI into five main components * * @param string $uri * @return array */ public function parse($uri) { preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match); $components = array(); if (5 < count($match)) { $components = array( 'scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5] ); } if (7 < count($match)) { $components['query'] = $match[7]; } if (9 < count($match)) { $components['fragment'] = $match[9]; } return $components; } /** * Builds a URI based on n array with the main components * * @param array $components * @return string */ public function generate(array $components) { $uri = $components['scheme'] . '://' . $components['authority'] . $components['path']; if (array_key_exists('query', $components)) { $uri .= $components['query']; } if (array_key_exists('fragment', $components)) { $uri .= $components['fragment']; } return $uri; } /** * Resolves a URI * * @param string $uri Absolute or relative * @param string $baseUri Optional base URI * @return string */ public function resolve($uri, $baseUri = null) { $components = $this->parse($uri); $path = $components['path']; if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) { return $uri; } $baseComponents = $this->parse($baseUri); $basePath = $baseComponents['path']; $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath); return $this->generate($baseComponents); } /** * @param string $uri * @return boolean */ public function isValid($uri) { $components = $this->parse($uri); return !empty($components); } } */ class UriResolver { /** * Parses a URI into five main components * * @param string $uri * @return array */ public function parse($uri) { preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match); $components = array(); if (5 < count($match)) { $components = array( 'scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5] ); } if (7 < count($match)) { $components['query'] = $match[7]; } if (9 < count($match)) { $components['fragment'] = $match[9]; } return $components; } /** * Builds a URI based on n array with the main components * * @param array $components * @return string */ public function generate(array $components) { $uri = $components['scheme'] . '://' . $components['authority'] . $components['path']; if (array_key_exists('query', $components)) { $uri .= $components['query']; } if (array_key_exists('fragment', $components)) { $uri .= '#' . $components['fragment']; } return $uri; } /** * Resolves a URI * * @param string $uri Absolute or relative * @param string $baseUri Optional base URI * @return string Absolute URI */ public function resolve($uri, $baseUri = null) { if ($uri == '') { return $baseUri; } $components = $this->parse($uri); $path = $components['path']; if (! empty($components['scheme'])) { return $uri; } $baseComponents = $this->parse($baseUri); $basePath = $baseComponents['path']; $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath); if (isset($components['fragment'])) { $baseComponents['fragment'] = $components['fragment']; } return $this->generate($baseComponents); } /** * Tries to glue a relative path onto an absolute one * * @param string $relativePath * @param string $basePath * @return string Merged path * @throws UriResolverException */ public static function combineRelativePathWithBasePath($relativePath, $basePath) { $relativePath = self::normalizePath($relativePath); if ($relativePath == '') { return $basePath; } if ($relativePath{0} == '/') { return $relativePath; } $basePathSegments = explode('/', $basePath); preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match); $numLevelUp = strlen($match[0]) /3 + 1; if ($numLevelUp >= count($basePathSegments)) { throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath)); } $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp); $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath); return implode('/', $basePathSegments) . '/' . $path; } /** * Normalizes a URI path component by removing dot-slash and double slashes * * @param string $path * @return string */ private static function normalizePath($path) { $path = preg_replace('|((?parse($uri); return !empty($components); } } * @see README.md */ class RefResolver { /** * HACK to prevent too many recursive expansions. * Happens e.g. when you want to validate a schema against the schema * definition. * * @var integer */ protected static $depth = 0; /** * maximum references depth * @var integer */ public static $maxDepth = 7; /** * @var UriRetrieverInterface */ protected $uriRetriever = null; /** * @var object */ protected $rootSchema = null; /** * @param UriRetriever $retriever */ public function __construct($retriever = null) { $this->uriRetriever = $retriever; } /** * Retrieves a given schema given a ref and a source URI * * @param string $ref Reference from schema * @param string $sourceUri URI where original schema was located * @return object Schema */ public function fetchRef($ref, $sourceUri) { $retriever = $this->getUriRetriever(); $jsonSchema = $retriever->retrieve($ref, $sourceUri); $this->resolve($jsonSchema); return $jsonSchema; } /** * Return the URI Retriever, defaulting to making a new one if one * was not yet set. * * @return UriRetriever */ public function getUriRetriever() { if (is_null($this->uriRetriever)) { $this->setUriRetriever(new UriRetriever); } return $this->uriRetriever; } /** * Resolves all $ref references for a given schema. Recurses through * the object to resolve references of any child schemas. * * The 'format' property is omitted because it isn't required for * validation. Theoretically, this class could be extended to look * for URIs in formats: "These custom formats MAY be expressed as * an URI, and this URI MAY reference a schema of that format." * * The 'id' property is not filled in, but that could be made to happen. * * @param object $schema JSON Schema to flesh out * @param string $sourceUri URI where this schema was located */ public function resolve($schema, $sourceUri = null) { if (self::$depth > self::$maxDepth) { throw new JsonDecodingException(JSON_ERROR_DEPTH); } ++self::$depth; if (! is_object($schema)) { --self::$depth; return; } if (null === $sourceUri && ! empty($schema->id)) { $sourceUri = $schema->id; } if (null === $this->rootSchema) { $this->rootSchema = $schema; } // Resolve $ref first $this->resolveRef($schema, $sourceUri); // These properties are just schemas // eg. items can be a schema or an array of schemas foreach (array('additionalItems', 'additionalProperties', 'extends', 'items') as $propertyName) { $this->resolveProperty($schema, $propertyName, $sourceUri); } // These are all potentially arrays that contain schema objects // eg. type can be a value or an array of values/schemas // eg. items can be a schema or an array of schemas foreach (array('disallow', 'extends', 'items', 'type', 'allOf', 'anyOf', 'oneOf') as $propertyName) { $this->resolveArrayOfSchemas($schema, $propertyName, $sourceUri); } // These are all objects containing properties whose values are schemas foreach (array('dependencies', 'patternProperties', 'properties') as $propertyName) { $this->resolveObjectOfSchemas($schema, $propertyName, $sourceUri); } --self::$depth; } /** * Given an object and a property name, that property should be an * array whose values can be schemas. * * @param object $schema JSON Schema to flesh out * @param string $propertyName Property to work on * @param string $sourceUri URI where this schema was located */ public function resolveArrayOfSchemas($schema, $propertyName, $sourceUri) { if (! isset($schema->$propertyName) || ! is_array($schema->$propertyName)) { return; } foreach ($schema->$propertyName as $possiblySchema) { $this->resolve($possiblySchema, $sourceUri); } } /** * Given an object and a property name, that property should be an * object whose properties are schema objects. * * @param object $schema JSON Schema to flesh out * @param string $propertyName Property to work on * @param string $sourceUri URI where this schema was located */ public function resolveObjectOfSchemas($schema, $propertyName, $sourceUri) { if (! isset($schema->$propertyName) || ! is_object($schema->$propertyName)) { return; } foreach (get_object_vars($schema->$propertyName) as $possiblySchema) { $this->resolve($possiblySchema, $sourceUri); } } /** * Given an object and a property name, that property should be a * schema object. * * @param object $schema JSON Schema to flesh out * @param string $propertyName Property to work on * @param string $sourceUri URI where this schema was located */ public function resolveProperty($schema, $propertyName, $sourceUri) { if (! isset($schema->$propertyName)) { return; } $this->resolve($schema->$propertyName, $sourceUri); } /** * Look for the $ref property in the object. If found, remove the * reference and augment this object with the contents of another * schema. * * @param object $schema JSON Schema to flesh out * @param string $sourceUri URI where this schema was located */ public function resolveRef($schema, $sourceUri) { $ref = '$ref'; if (empty($schema->$ref)) { return; } $splitRef = explode('#', $schema->$ref, 2); $refDoc = $splitRef[0]; $refPath = null; if (count($splitRef) === 2) { $refPath = explode('/', $splitRef[1]); array_shift($refPath); } if (empty($refDoc) && empty($refPath)) { // TODO: Not yet implemented - root pointer ref, causes recursion issues return; } if (!empty($refDoc)) { $refSchema = $this->fetchRef($refDoc, $sourceUri); } else { $refSchema = $this->rootSchema; } if (null !== $refPath) { $refSchema = $this->resolveRefSegment($refSchema, $refPath); } unset($schema->$ref); // Augment the current $schema object with properties fetched foreach (get_object_vars($refSchema) as $prop => $value) { $schema->$prop = $value; } } /** * Set URI Retriever for use with the Ref Resolver * * @param UriRetriever $retriever * @return $this for chaining */ public function setUriRetriever(UriRetriever $retriever) { $this->uriRetriever = $retriever; return $this; } protected function resolveRefSegment($data, $pathParts) { foreach ($pathParts as $path) { $path = strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%')); if (is_array($data)) { $data = $data[$path]; } else { $data = $data->{$path}; } } return $data; } } * @author Bruno Prieto Reis */ class StringConstraint extends Constraint { /** * {@inheritDoc} */ public function check($element, $schema = null, $path = null, $i = null) { // Verify maxLength if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) { $this->addError($path, "Must be at most " . $schema->maxLength . " characters long"); } //verify minLength if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) { $this->addError($path, "Must be at least " . $schema->minLength . " characters long"); } // Verify a regex pattern if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#', $element)) { $this->addError($path, "Does not match the regex pattern " . $schema->pattern); } $this->checkFormat($element, $schema, $path, $i); } private function strlen($string) { if (extension_loaded('mbstring')) { return mb_strlen($string, mb_detect_encoding($string)); } else { return strlen($string); } } } * @author Bruno Prieto Reis */ class TypeConstraint extends Constraint { /** * @var array|string[] type wordings for validation error messages */ static $wording = array( 'integer' => 'an integer', 'number' => 'a number', 'boolean' => 'a boolean', 'object' => 'an object', 'array' => 'an array', 'string' => 'a string', 'null' => 'a null', 'any' => NULL, // validation of 'any' is always true so is not needed in message wording 0 => NULL, // validation of a false-y value is always true, so not needed as well ); /** * {@inheritDoc} */ public function check($value = null, $schema = null, $path = null, $i = null) { $type = isset($schema->type) ? $schema->type : null; $isValid = true; if (is_array($type)) { // @TODO refactor $validatedOneType = false; $errors = array(); foreach ($type as $tp) { $validator = new TypeConstraint($this->checkMode); $subSchema = new \stdClass(); $subSchema->type = $tp; $validator->check($value, $subSchema, $path, null); $error = $validator->getErrors(); if (!count($error)) { $validatedOneType = true; break; } $errors = $error; } if (!$validatedOneType) { $this->addErrors($errors); return; } } elseif (is_object($type)) { $this->checkUndefined($value, $type, $path); } else { $isValid = $this->validateType($value, $type); } if ($isValid === false) { if (!isset(self::$wording[$type])) { throw new StandardUnexpectedValueException( sprintf( "No wording for %s available, expected wordings are: [%s]", var_export($type, true), implode(', ', array_filter(self::$wording))) ); } $this->addError($path, gettype($value) . " value found, but " . self::$wording[$type] . " is required"); } } /** * Verifies that a given value is of a certain type * * @param mixed $value Value to validate * @param string $type TypeConstraint to check against * * @return boolean * * @throws InvalidArgumentException */ protected function validateType($value, $type) { //mostly the case for inline schema if (!$type) { return true; } if ('integer' === $type) { return is_int($value); } if ('number' === $type) { return is_numeric($value) && !is_string($value); } if ('boolean' === $type) { return is_bool($value); } if ('object' === $type) { return is_object($value); //return ($this::CHECK_MODE_TYPE_CAST == $this->checkMode) ? is_array($value) : is_object($value); } if ('array' === $type) { return is_array($value); } if ('string' === $type) { return is_string($value); } if ('null' === $type) { return is_null($value); } if ('any' === $type) { return true; } throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type); } } * @author Bruno Prieto Reis */ class SchemaConstraint extends Constraint { /** * {@inheritDoc} */ public function check($element, $schema = null, $path = null, $i = null) { if ($schema !== null) { // passed schema $this->checkUndefined($element, $schema, '', ''); } elseif (property_exists($element, $this->inlineSchemaProperty)) { // inline schema $this->checkUndefined($element, $element->{$this->inlineSchemaProperty}, '', ''); } else { throw new InvalidArgumentException('no schema found to verify against'); } } } * @author Bruno Prieto Reis */ class UndefinedConstraint extends Constraint { /** * {@inheritDoc} */ public function check($value, $schema = null, $path = null, $i = null) { if (is_null($schema)) { return; } if (!is_object($schema)) { throw new InvalidArgumentException( 'Given schema must be an object in ' . $path . ' but is a ' . gettype($schema) ); } $i = is_null($i) ? "" : $i; $path = $this->incrementPath($path, $i); // check special properties $this->validateCommonProperties($value, $schema, $path); // check allOf, anyOf, and oneOf properties $this->validateOfProperties($value, $schema, $path); // check known types $this->validateTypes($value, $schema, $path, $i); } /** * Validates the value against the types * * @param mixed $value * @param mixed $schema * @param string $path * @param string $i */ public function validateTypes($value, $schema = null, $path = null, $i = null) { // check array if (is_array($value)) { $this->checkArray($value, $schema, $path, $i); } // check object if (is_object($value) && (isset($schema->properties) || isset($schema->patternProperties))) { $this->checkObject( $value, isset($schema->properties) ? $schema->properties : null, $path, isset($schema->additionalProperties) ? $schema->additionalProperties : null, isset($schema->patternProperties) ? $schema->patternProperties : null ); } // check string if (is_string($value)) { $this->checkString($value, $schema, $path, $i); } // check numeric if (is_numeric($value)) { $this->checkNumber($value, $schema, $path, $i); } // check enum if (isset($schema->enum)) { $this->checkEnum($value, $schema, $path, $i); } } /** * Validates common properties * * @param mixed $value * @param mixed $schema * @param string $path * @param string $i */ protected function validateCommonProperties($value, $schema = null, $path = null, $i = "") { // if it extends another schema, it must pass that schema as well if (isset($schema->extends)) { if (is_string($schema->extends)) { $schema->extends = $this->validateUri($schema, $schema->extends); } if (is_array($schema->extends)) { foreach ($schema->extends as $extends) { $this->checkUndefined($value, $extends, $path, $i); } } else { $this->checkUndefined($value, $schema->extends, $path, $i); } } // Verify required values if (is_object($value)) { if (!($value instanceof UndefinedConstraint) && isset($schema->required) && is_array($schema->required) ) { // Draft 4 - Required is an array of strings - e.g. "required": ["foo", ...] foreach ($schema->required as $required) { if (!property_exists($value, $required)) { $this->addError($required, "The property " . $required . " is required"); } } } else if (isset($schema->required) && !is_array($schema->required)) { // Draft 3 - Required attribute - e.g. "foo": {"type": "string", "required": true} if ( $schema->required && $value instanceof UndefinedConstraint) { $this->addError($path, "Is missing and it is required"); } } } // Verify type if (!($value instanceof UndefinedConstraint)) { $this->checkType($value, $schema, $path); } // Verify disallowed items if (isset($schema->disallow)) { $initErrors = $this->getErrors(); $typeSchema = new \stdClass(); $typeSchema->type = $schema->disallow; $this->checkType($value, $typeSchema, $path); // if no new errors were raised it must be a disallowed value if (count($this->getErrors()) == count($initErrors)) { $this->addError($path, "Disallowed value was matched"); } else { $this->errors = $initErrors; } } if (isset($schema->not)) { $initErrors = $this->getErrors(); $this->checkUndefined($value, $schema->not, $path, $i); // if no new errors were raised then the instance validated against the "not" schema if (count($this->getErrors()) == count($initErrors)) { $this->addError($path, "Matched a schema which it should not"); } else { $this->errors = $initErrors; } } // Verify minimum and maximum number of properties if (is_object($value)) { if (isset($schema->minProperties)) { if (count(get_object_vars($value)) < $schema->minProperties) { $this->addError($path, "Must contain a minimum of " . $schema->minProperties . " properties"); } } if (isset($schema->maxProperties)) { if (count(get_object_vars($value)) > $schema->maxProperties) { $this->addError($path, "Must contain no more than " . $schema->maxProperties . " properties"); } } } // Verify that dependencies are met if (is_object($value) && isset($schema->dependencies)) { $this->validateDependencies($value, $schema->dependencies, $path); } } /** * Validate allOf, anyOf, and oneOf properties * * @param mixed $value * @param mixed $schema * @param string $path * @param string $i */ protected function validateOfProperties($value, $schema, $path, $i = "") { // Verify type if ($value instanceof UndefinedConstraint) { return; } if (isset($schema->allOf)) { $isValid = true; foreach ($schema->allOf as $allOf) { $initErrors = $this->getErrors(); $this->checkUndefined($value, $allOf, $path, $i); $isValid = $isValid && (count($this->getErrors()) == count($initErrors)); } if (!$isValid) { $this->addError($path, "Failed to match all schemas"); } } if (isset($schema->anyOf)) { $isValid = false; $startErrors = $this->getErrors(); foreach ($schema->anyOf as $anyOf) { $initErrors = $this->getErrors(); $this->checkUndefined($value, $anyOf, $path, $i); if ($isValid = (count($this->getErrors()) == count($initErrors))) { break; } } if (!$isValid) { $this->addError($path, "Failed to match at least one schema"); } else { $this->errors = $startErrors; } } if (isset($schema->oneOf)) { $allErrors = array(); $matchedSchemas = 0; $startErrors = $this->getErrors(); foreach ($schema->oneOf as $oneOf) { $this->errors = array(); $this->checkUndefined($value, $oneOf, $path, $i); if (count($this->getErrors()) == 0) { $matchedSchemas++; } $allErrors = array_merge($allErrors, array_values($this->getErrors())); } if ($matchedSchemas !== 1) { $this->addErrors( array_merge( $allErrors, array(array( 'property' => $path, 'message' => "failed to match exactly one schema" ),), $startErrors ) ); } else { $this->errors = $startErrors; } } } /** * Validate dependencies * * @param mixed $value * @param mixed $dependencies * @param string $path * @param string $i */ protected function validateDependencies($value, $dependencies, $path, $i = "") { foreach ($dependencies as $key => $dependency) { if (property_exists($value, $key)) { if (is_string($dependency)) { // Draft 3 string is allowed - e.g. "dependencies": {"bar": "foo"} if (!property_exists($value, $dependency)) { $this->addError($path, "$key depends on $dependency and $dependency is missing"); } } else if (is_array($dependency)) { // Draft 4 must be an array - e.g. "dependencies": {"bar": ["foo"]} foreach ($dependency as $d) { if (!property_exists($value, $d)) { $this->addError($path, "$key depends on $d and $d is missing"); } } } else if (is_object($dependency)) { // Schema - e.g. "dependencies": {"bar": {"properties": {"foo": {...}}}} $this->checkUndefined($value, $dependency, $path, $i); } } } } protected function validateUri($schema, $schemaUri = null) { $resolver = new UriResolver(); $retriever = $this->getUriRetriever(); $jsonSchema = null; if ($resolver->isValid($schemaUri)) { $schemaId = property_exists($schema, 'id') ? $schema->id : null; $jsonSchema = $retriever->retrieve($schemaId, $schemaUri); } return $jsonSchema; } } * @author Bruno Prieto Reis */ class EnumConstraint extends Constraint { /** * {@inheritDoc} */ public function check($element, $schema = null, $path = null, $i = null) { // Only validate enum if the attribute exists if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) { return; } foreach ($schema->enum as $enum) { $type = gettype($element); if ($type === gettype($enum)) { if ($type == "object") { if ($element == $enum) return; } else { if ($element === $enum) return; } } } $this->addError($path, "Does not have a value in the enumeration " . print_r($schema->enum, true)); } } * @author Bruno Prieto Reis */ class ObjectConstraint extends Constraint { /** * {@inheritDoc} */ function check($element, $definition = null, $path = null, $additionalProp = null, $patternProperties = null) { if ($element instanceof UndefinedConstraint) { return; } $matches = array(); if ($patternProperties) { $matches = $this->validatePatternProperties($element, $path, $patternProperties); } if ($definition) { // validate the definition properties $this->validateDefinition($element, $definition, $path); } // additional the element properties $this->validateElement($element, $matches, $definition, $path, $additionalProp); } public function validatePatternProperties($element, $path, $patternProperties) { $matches = array(); foreach ($patternProperties as $pregex => $schema) { // Validate the pattern before using it to test for matches if (@preg_match('/'. $pregex . '/', '') === false) { $this->addError($path, 'The pattern "' . $pregex . '" is invalid'); continue; } foreach ($element as $i => $value) { if (preg_match('/' . $pregex . '/', $i)) { $matches[] = $i; $this->checkUndefined($value, $schema ? : new \stdClass(), $path, $i); } } } return $matches; } /** * Validates the element properties * * @param \stdClass $element Element to validate * @param array $matches Matches from patternProperties (if any) * @param \stdClass $objectDefinition ObjectConstraint definition * @param string $path Path to test? * @param mixed $additionalProp Additional properties */ public function validateElement($element, $matches, $objectDefinition = null, $path = null, $additionalProp = null) { foreach ($element as $i => $value) { $property = $this->getProperty($element, $i, new UndefinedConstraint()); $definition = $this->getProperty($objectDefinition, $i); // no additional properties allowed if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) { $this->addError($path, "The property - " . $i . " - is not defined and the definition does not allow additional properties"); } // additional properties defined if (!in_array($i, $matches) && $additionalProp && !$definition) { if ($additionalProp === true) { $this->checkUndefined($value, null, $path, $i); } else { $this->checkUndefined($value, $additionalProp, $path, $i); } } // property requires presence of another $require = $this->getProperty($definition, 'requires'); if ($require && !$this->getProperty($element, $require)) { $this->addError($path, "The presence of the property " . $i . " requires that " . $require . " also be present"); } if (!$definition) { // normal property verification $this->checkUndefined($value, new \stdClass(), $path, $i); } } } /** * Validates the definition properties * * @param \stdClass $element Element to validate * @param \stdClass $objectDefinition ObjectConstraint definition * @param string $path Path? */ public function validateDefinition($element, $objectDefinition = null, $path = null) { foreach ($objectDefinition as $i => $value) { $property = $this->getProperty($element, $i, new UndefinedConstraint()); $definition = $this->getProperty($objectDefinition, $i); $this->checkUndefined($property, $definition, $path, $i); } } /** * retrieves a property from an object or array * * @param mixed $element Element to validate * @param string $property Property to retrieve * @param mixed $fallback Default value if property is not found * * @return mixed */ protected function getProperty($element, $property, $fallback = null) { if (is_array($element) /*$this->checkMode == self::CHECK_MODE_TYPE_CAST*/) { return array_key_exists($property, $element) ? $element[$property] : $fallback; } elseif (is_object($element)) { return property_exists($element, $property) ? $element->$property : $fallback; } return $fallback; } } * @author Bruno Prieto Reis */ class CollectionConstraint extends Constraint { /** * {@inheritDoc} */ public function check($value, $schema = null, $path = null, $i = null) { // Verify minItems if (isset($schema->minItems) && count($value) < $schema->minItems) { $this->addError($path, "There must be a minimum of " . $schema->minItems . " items in the array"); } // Verify maxItems if (isset($schema->maxItems) && count($value) > $schema->maxItems) { $this->addError($path, "There must be a maximum of " . $schema->maxItems . " items in the array"); } // Verify uniqueItems if (isset($schema->uniqueItems)) { $unique = $value; if (is_array($value) && count($value)) { $unique = array_map(function($e) { return var_export($e, true); }, $value); } if (count(array_unique($unique)) != count($value)) { $this->addError($path, "There are no duplicates allowed in the array"); } } // Verify items if (isset($schema->items)) { $this->validateItems($value, $schema, $path, $i); } } /** * Validates the items * * @param array $value * @param \stdClass $schema * @param string $path * @param string $i */ protected function validateItems($value, $schema = null, $path = null, $i = null) { if (is_object($schema->items)) { // just one type definition for the whole array foreach ($value as $k => $v) { $initErrors = $this->getErrors(); // First check if its defined in "items" $this->checkUndefined($v, $schema->items, $path, $k); // Recheck with "additionalItems" if the first test fails if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) { $secondErrors = $this->getErrors(); $this->checkUndefined($v, $schema->additionalItems, $path, $k); } // Reset errors if needed if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) { $this->errors = $secondErrors; } else if (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) { $this->errors = $initErrors; } } } else { // Defined item type definitions foreach ($value as $k => $v) { if (array_key_exists($k, $schema->items)) { $this->checkUndefined($v, $schema->items[$k], $path, $k); } else { // Additional items if (property_exists($schema, 'additionalItems')) { if ($schema->additionalItems !== false) { $this->checkUndefined($v, $schema->additionalItems, $path, $k); } else { $this->addError( $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items'); } } else { // Should be valid against an empty schema $this->checkUndefined($v, new \stdClass(), $path, $k); } } } // Treat when we have more schema definitions than values, not for empty arrays if(count($value) > 0) { for ($k = count($value); $k < count($schema->items); $k++) { $this->checkUndefined(new UndefinedConstraint(), $schema->items[$k], $path, $k); } } } } } */ interface ConstraintInterface { /** * returns all collected errors * * @return array */ public function getErrors(); /** * adds errors to this validator * * @param array $errors */ public function addErrors(array $errors); /** * adds an error * * @param $path * @param $message */ public function addError($path, $message); /** * checks if the validator has not raised errors * * @return boolean */ public function isValid(); /** * invokes the validation of an element * * @abstract * @param mixed $value * @param mixed $schema * @param mixed $path * @param mixed $i */ public function check($value, $schema = null, $path = null, $i = null); } * @author Bruno Prieto Reis */ class NumberConstraint extends Constraint { /** * {@inheritDoc} */ public function check($element, $schema = null, $path = null, $i = null) { // Verify minimum if (isset($schema->exclusiveMinimum)) { if (isset($schema->minimum)) { if ($schema->exclusiveMinimum && $element === $schema->minimum) { $this->addError($path, "Must have a minimum value greater than boundary value of " . $schema->minimum); } else if ($element < $schema->minimum) { $this->addError($path, "Must have a minimum value of " . $schema->minimum); } } else { $this->addError($path, "Use of exclusiveMinimum requires presence of minimum"); } } else if (isset($schema->minimum) && $element < $schema->minimum) { $this->addError($path, "Must have a minimum value of " . $schema->minimum); } // Verify maximum if (isset($schema->exclusiveMaximum)) { if (isset($schema->maximum)) { if ($schema->exclusiveMaximum && $element === $schema->maximum) { $this->addError($path, "Must have a maximum value less than boundary value of " . $schema->maximum); } else if ($element > $schema->maximum) { $this->addError($path, "Must have a maximum value of " . $schema->maximum); } } else { $this->addError($path, "Use of exclusiveMaximum requires presence of maximum"); } } else if (isset($schema->maximum) && $element > $schema->maximum) { $this->addError($path, "Must have a maximum value of " . $schema->maximum); } // Verify divisibleBy - Draft v3 if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) { $this->addError($path, "Is not divisible by " . $schema->divisibleBy); } // Verify multipleOf - Draft v4 if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) { $this->addError($path, "Must be a multiple of " . $schema->multipleOf); } $this->checkFormat($element, $schema, $path, $i); } private function fmod($number1, $number2) { $modulus = fmod($number1, $number2); $precision = abs(0.0000000001); $diff = (float)($modulus - $number2); if (-$precision < $diff && $diff < $precision) { return 0.0; } $decimals1 = mb_strpos($number1, ".") ? mb_strlen($number1) - mb_strpos($number1, ".") - 1 : 0; $decimals2 = mb_strpos($number2, ".") ? mb_strlen($number2) - mb_strpos($number2, ".") - 1 : 0; return (float)round($modulus, max($decimals1, $decimals2)); } } * @author Bruno Prieto Reis */ abstract class Constraint implements ConstraintInterface { protected $checkMode = self::CHECK_MODE_NORMAL; protected $uriRetriever; protected $errors = array(); protected $inlineSchemaProperty = '$schema'; const CHECK_MODE_NORMAL = 1; const CHECK_MODE_TYPE_CAST = 2; /** * @param int $checkMode * @param UriRetriever $uriRetriever */ public function __construct($checkMode = self::CHECK_MODE_NORMAL, UriRetriever $uriRetriever = null) { $this->checkMode = $checkMode; $this->uriRetriever = $uriRetriever; } /** * @return UriRetriever $uriRetriever */ public function getUriRetriever() { if (is_null($this->uriRetriever)) { $this->setUriRetriever(new UriRetriever); } return $this->uriRetriever; } /** * @param UriRetriever $uriRetriever */ public function setUriRetriever(UriRetriever $uriRetriever) { $this->uriRetriever = $uriRetriever; } /** * {@inheritDoc} */ public function addError($path, $message) { $this->errors[] = array( 'property' => $path, 'message' => $message ); } /** * {@inheritDoc} */ public function addErrors(array $errors) { $this->errors = array_merge($this->errors, $errors); } /** * {@inheritDoc} */ public function getErrors() { return $this->errors; } /** * {@inheritDoc} */ public function isValid() { return !$this->getErrors(); } /** * Clears any reported errors. Should be used between * multiple validation checks. */ public function reset() { $this->errors = array(); } /** * Bubble down the path * * @param string $path Current path * @param mixed $i What to append to the path * * @return string */ protected function incrementPath($path, $i) { if ($path !== '') { if (is_int($i)) { $path .= '[' . $i . ']'; } elseif ($i == '') { $path .= ''; } else { $path .= '.' . $i; } } else { $path = $i; } return $path; } /** * Validates an array * * @param mixed $value * @param mixed $schema * @param mixed $path * @param mixed $i */ protected function checkArray($value, $schema = null, $path = null, $i = null) { $validator = new CollectionConstraint($this->checkMode, $this->uriRetriever); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); } /** * Validates an object * * @param mixed $value * @param mixed $schema * @param mixed $path * @param mixed $i * @param mixed $patternProperties */ protected function checkObject($value, $schema = null, $path = null, $i = null, $patternProperties = null) { $validator = new ObjectConstraint($this->checkMode, $this->uriRetriever); $validator->check($value, $schema, $path, $i, $patternProperties); $this->addErrors($validator->getErrors()); } /** * Validates the type of a property * * @param mixed $value * @param mixed $schema * @param mixed $path * @param mixed $i */ protected function checkType($value, $schema = null, $path = null, $i = null) { $validator = new TypeConstraint($this->checkMode, $this->uriRetriever); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); } /** * Checks a undefined element * * @param mixed $value * @param mixed $schema * @param mixed $path * @param mixed $i */ protected function checkUndefined($value, $schema = null, $path = null, $i = null) { $validator = new UndefinedConstraint($this->checkMode, $this->uriRetriever); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); } /** * Checks a string element * * @param mixed $value * @param mixed $schema * @param mixed $path * @param mixed $i */ protected function checkString($value, $schema = null, $path = null, $i = null) { $validator = new StringConstraint($this->checkMode, $this->uriRetriever); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); } /** * Checks a number element * * @param mixed $value * @param mixed $schema * @param mixed $path * @param mixed $i */ protected function checkNumber($value, $schema = null, $path = null, $i = null) { $validator = new NumberConstraint($this->checkMode, $this->uriRetriever); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); } /** * Checks a enum element * * @param mixed $value * @param mixed $schema * @param mixed $path * @param mixed $i */ protected function checkEnum($value, $schema = null, $path = null, $i = null) { $validator = new EnumConstraint($this->checkMode, $this->uriRetriever); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); } protected function checkFormat($value, $schema = null, $path = null, $i = null) { $validator = new FormatConstraint($this->checkMode, $this->uriRetriever); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); } /** * @param string $uri JSON Schema URI * @return string JSON Schema contents */ protected function retrieveUri($uri) { if (null === $this->uriRetriever) { $this->setUriRetriever(new UriRetriever); } $jsonSchema = $this->uriRetriever->retrieve($uri); // TODO validate using schema return $jsonSchema; } } * @link http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23 */ class FormatConstraint extends Constraint { /** * {@inheritDoc} */ public function check($element, $schema = null, $path = null, $i = null) { if (!isset($schema->format)) { return; } switch ($schema->format) { case 'date': if (!$date = $this->validateDateTime($element, 'Y-m-d')) { $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element))); } break; case 'time': if (!$this->validateDateTime($element, 'H:i:s')) { $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element))); } break; case 'date-time': if (!$this->validateDateTime($element, 'Y-m-d\TH:i:s\Z') && !$this->validateDateTime($element, 'Y-m-d\TH:i:s.u\Z') && !$this->validateDateTime($element, 'Y-m-d\TH:i:sP') && !$this->validateDateTime($element, 'Y-m-d\TH:i:sO') ) { $this->addError($path, sprintf('Invalid date-time %s, expected format YYYY-MM-DDThh:mm:ssZ or YYYY-MM-DDThh:mm:ss+hh:mm', json_encode($element))); } break; case 'utc-millisec': if (!$this->validateDateTime($element, 'U')) { $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element))); } break; case 'regex': if (!$this->validateRegex($element)) { $this->addError($path, 'Invalid regex format ' . $element); } break; case 'color': if (!$this->validateColor($element)) { $this->addError($path, "Invalid color"); } break; case 'style': if (!$this->validateStyle($element)) { $this->addError($path, "Invalid style"); } break; case 'phone': if (!$this->validatePhone($element)) { $this->addError($path, "Invalid phone number"); } break; case 'uri': if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) { $this->addError($path, "Invalid URL format"); } break; case 'email': if (null === filter_var($element, FILTER_VALIDATE_EMAIL, FILTER_NULL_ON_FAILURE)) { $this->addError($path, "Invalid email"); } break; case 'ip-address': case 'ipv4': if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) { $this->addError($path, "Invalid IP address"); } break; case 'ipv6': if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) { $this->addError($path, "Invalid IP address"); } break; case 'host-name': case 'hostname': if (!$this->validateHostname($element)) { $this->addError($path, "Invalid hostname"); } break; default: // Do nothing so that custom formats can be used. break; } } protected function validateDateTime($datetime, $format) { $dt = \DateTime::createFromFormat($format, $datetime); if (!$dt) { return false; } return $datetime === $dt->format($format); } protected function validateRegex($regex) { return false !== @preg_match('/' . $regex . '/', ''); } protected function validateColor($color) { if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia', 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple', 'red', 'silver', 'teal', 'white', 'yellow'))) { return true; } return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color); } protected function validateStyle($style) { $properties = explode(';', rtrim($style, ';')); $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT); return empty($invalidEntries); } protected function validatePhone($phone) { return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone); } protected function validateHostname($host) { return preg_match('/^[_a-z]+\.([_a-z]+\.?)+$/i', $host); } } * @author Bruno Prieto Reis * @see README.md */ class Validator extends Constraint { const SCHEMA_MEDIA_TYPE = 'application/schema+json'; /** * Validates the given data against the schema and returns an object containing the results * Both the php object and the schema are supposed to be a result of a json_decode call. * The validation works as defined by the schema proposal in http://json-schema.org * * {@inheritDoc} */ public function check($value, $schema = null, $path = null, $i = null) { $validator = new SchemaConstraint($this->checkMode, $this->uriRetriever); $validator->check($value, $schema); $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR)); } } */ class Version { /** * The semantic version regular expression. * * @var string */ const REGEX = '/^\d+\.\d+\.\d+(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/'; /** * The build information. * * @var array */ private $build; /** * The major version number. * * @var integer */ private $major = 0; /** * The minor version number. * * @var integer */ private $minor = 0; /** * The patch number. * * @var integer */ private $patch = 0; /** * The pre-release information. * * @var array */ private $pre; /** * Parses the string representation of the version information. * * @param string $string The string representation. */ public function __construct($string = '') { if (false === empty($string)) { $this->parseString($string); } } /** * Generates a string using the current version information. * * @return string The string representation of the information. * * @api */ public function __toString() { $string = sprintf('%d.%d.%d', $this->major, $this->minor, $this->patch); if ($this->pre) { $string .= '-' . join('.', $this->pre); } if ($this->build) { $string .= '+' . join('.', $this->build); } return $string; } /** * Compares one version to another. * * @param Version $version Another version. * * @return -1 If this one is greater, 0 if equal, or 1 if $version is greater. * * @api */ public function compareTo($version) { $major = $version->getMajor(); $minor = $version->getMinor(); $patch = $version->getPatch(); $pre = $version->getPreRelease(); $build = $version->getBuild(); switch (true) { case ($this->major < $major): return 1; case ($this->major > $major): return -1; case ($this->minor > $minor): return -1; case ($this->minor < $minor): return 1; case ($this->patch > $patch): return -1; case ($this->patch < $patch): return 1; // @codeCoverageIgnoreStart } // @codeCoverageIgnoreEnd if ($pre || $this->pre) { if (empty($this->pre) && $pre) { return -1; } if ($this->pre && empty($pre)) { return 1; } if (0 !== ($weight = $this->precedence($this->pre, $pre))) { return $weight; } } if ($build || $this->build) { if ((null === $this->build) && $build) { return 1; } if ($this->build && (null === $build)) { return -1; } return $this->precedence($this->build, $build); } return 0; } /** * Creates a new Version instance. * * @param string $string The string representation. * * @return Version The Version instance. * * @api */ public static function create($string = '') { return new static($string); } /** * Checks if the version is equal to the given one. * * @param Version $version The version to compare against. * * @return boolean TRUE if equal, FALSE if not. * * @api */ public function isEqualTo(Version $version) { return ((string)$this == (string)$version); } /** * Checks if this version is greater than the given one. * * @param Version $version The version to compare against. * * @return boolean TRUE if greater, FALSE if not. */ public function isGreaterThan(Version $version) { return (0 > $this->compareTo($version)); } /** * Checks if this version is less than the given one. * * @param Version $version The version to compare against. * * @return boolean TRUE if less than, FALSE if not. * * @api */ public function isLessThan(Version $version) { return (0 < $this->compareTo($version)); } /** * Checks if the version is for a stable release. * * @return boolean TRUE if stable, FALSE if not. */ public function isStable() { return empty($this->pre); } /** * Checks if the string is a valid string representation of a version. * * @param string $string The string. * * @return boolean TRUE if valid, FALSE if not. * * @api */ public static function isValid($string) { return (bool) preg_match(static::REGEX, $string); } /** * Returns the build version information. * * @return array|null The build version information. * * @api */ public function getBuild() { return $this->build; } /** * Returns the pre-release version information. * * @return array|null The pre-release version information. * * @api */ public function getPreRelease() { return $this->pre; } /** * Returns the major version number. * * @return integer The major version number. * * @api */ public function getMajor() { return $this->major; } /** * Returns the minor version number. * * @return integer The minor version number. * * @api */ public function getMinor() { return $this->minor; } /** * Returns the patch version number. * * @api * @return integer The patch version number. */ public function getPatch() { return $this->patch; } /** * Sets the build version information. * * @param array|integer|string $build The build version information. * * @api */ public function setBuild($build) { $this->build = array_values((array)$build); array_walk( $this->build, function (&$v) { if (preg_match('/^[0-9]+$/', $v)) { $v = (int)$v; } } ); } /** * Sets the pre-release version information. * * @param array|integer|string $pre The pre-release version information. * * @api */ public function setPreRelease($pre) { $this->pre = array_values((array)$pre); array_walk( $this->pre, function (&$v) { if (preg_match('/^[0-9]+$/', $v)) { $v = (int)$v; } } ); } /** * Sets the major version number. * * @param integer|string $major The major version number. * * @api */ public function setMajor($major) { $this->major = (int)$major; } /** * Sets the minor version number. * * @param integer|string $minor The minor version number. * * @api */ public function setMinor($minor) { $this->minor = (int)$minor; } /** * Sets the patch version number. * * @param integer|string $patch The patch version number. * * @api */ public function setPatch($patch) { $this->patch = (int)$patch; } /** * Parses the version string, replacing current any data. * * @param string $string The string representation. * * @throws InvalidArgumentException If the string is invalid. */ protected function parseString($string) { $this->build = null; $this->major = 0; $this->minor = 0; $this->patch = 0; $this->pre = null; if (false === static::isValid($string)) { throw new InvalidArgumentException(sprintf('The version string "%s" is invalid.', $string)); } if (false !== strpos($string, '+')) { list($string, $build) = explode('+', $string); $this->setBuild(explode('.', $build)); } if (false !== strpos($string, '-')) { list($string, $pre) = explode('-', $string); $this->setPreRelease(explode('.', $pre)); } $version = explode('.', $string); $this->major = (int)$version[0]; if (isset($version[1])) { $this->minor = (int)$version[1]; } if (isset($version[2])) { $this->patch = (int)$version[2]; } } /** * Checks the precedence of each data set. * * @param array $a A data set. * @param array $b A data set. * * @return integer -1 if $a > $b, 0 if $a = $b, 1 if $a < $b. */ protected function precedence($a, $b) { if (count($a) > count($b)) { $l = -1; $r = 1; $x = $a; $y = $b; } else { $l = 1; $r = -1; $x = $b; $y = $a; } foreach (array_keys($x) as $i) { if (false === isset($y[$i])) { return $l; } if ($x[$i] === $y[$i]) { continue; } $xi = is_integer($x[$i]); $yi = is_integer($y[$i]); if ($xi && $yi) { return ($x[$i] > $y[$i]) ? $l : $r; } elseif ((false === $xi) && (false === $yi)) { return (max($x[$i], $y[$i]) == $x[$i]) ? $l : $r; } else { return $xi ? $r : $l; } } return 0; } } . */ namespace Doctrine\Common\Annotations; /** * Annotations class. * * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class Annotation { /** * Value property. Common among all derived classes. * * @var string */ public $value; /** * Constructor. * * @param array $data Key-value for properties to be defined in this class. */ public final function __construct(array $data) { foreach ($data as $key => $value) { $this->$key = $value; } } /** * Error handler for unknown property accessor in Annotation class. * * @param string $name Unknown property name. * * @throws \BadMethodCallException */ public function __get($name) { throw new \BadMethodCallException( sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this)) ); } /** * Error handler for unknown property mutator in Annotation class. * * @param string $name Unknown property name. * @param mixed $value Property value. * * @throws \BadMethodCallException */ public function __set($name, $value) { throw new \BadMethodCallException( sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this)) ); } } . */ namespace Doctrine\Common\Annotations; /** * Allows the reader to be used in-place of Doctrine's reader. * * @author Johannes M. Schmitt */ class IndexedReader implements Reader { /** * @var Reader */ private $delegate; /** * Constructor. * * @param Reader $reader */ public function __construct(Reader $reader) { $this->delegate = $reader; } /** * {@inheritDoc} */ public function getClassAnnotations(\ReflectionClass $class) { $annotations = array(); foreach ($this->delegate->getClassAnnotations($class) as $annot) { $annotations[get_class($annot)] = $annot; } return $annotations; } /** * {@inheritDoc} */ public function getClassAnnotation(\ReflectionClass $class, $annotation) { return $this->delegate->getClassAnnotation($class, $annotation); } /** * {@inheritDoc} */ public function getMethodAnnotations(\ReflectionMethod $method) { $annotations = array(); foreach ($this->delegate->getMethodAnnotations($method) as $annot) { $annotations[get_class($annot)] = $annot; } return $annotations; } /** * {@inheritDoc} */ public function getMethodAnnotation(\ReflectionMethod $method, $annotation) { return $this->delegate->getMethodAnnotation($method, $annotation); } /** * {@inheritDoc} */ public function getPropertyAnnotations(\ReflectionProperty $property) { $annotations = array(); foreach ($this->delegate->getPropertyAnnotations($property) as $annot) { $annotations[get_class($annot)] = $annot; } return $annotations; } /** * {@inheritDoc} */ public function getPropertyAnnotation(\ReflectionProperty $property, $annotation) { return $this->delegate->getPropertyAnnotation($property, $annotation); } /** * Proxies all methods to the delegate. * * @param string $method * @param array $args * * @return mixed */ public function __call($method, $args) { return call_user_func_array(array($this->delegate, $method), $args); } } . */ namespace Doctrine\Common\Annotations; use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation; use Doctrine\Common\Annotations\Annotation\Target; use ReflectionClass; use ReflectionMethod; use ReflectionProperty; /** * A reader for docblock annotations. * * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Johannes M. Schmitt */ class AnnotationReader implements Reader { /** * Global map for imports. * * @var array */ private static $globalImports = array( 'ignoreannotation' => 'Doctrine\Common\Annotations\Annotation\IgnoreAnnotation', ); /** * A list with annotations that are not causing exceptions when not resolved to an annotation class. * * The names are case sensitive. * * @var array */ private static $globalIgnoredNames = array( // Annotation tags 'Annotation' => true, 'Attribute' => true, 'Attributes' => true, /* Can we enable this? 'Enum' => true, */ 'Required' => true, 'Target' => true, // Widely used tags (but not existent in phpdoc) 'fix' => true , 'fixme' => true, 'override' => true, // PHPDocumentor 1 tags 'abstract'=> true, 'access'=> true, 'code' => true, 'deprec'=> true, 'endcode' => true, 'exception'=> true, 'final'=> true, 'ingroup' => true, 'inheritdoc'=> true, 'inheritDoc'=> true, 'magic' => true, 'name'=> true, 'toc' => true, 'tutorial'=> true, 'private' => true, 'static'=> true, 'staticvar'=> true, 'staticVar'=> true, 'throw' => true, // PHPDocumentor 2 tags. 'api' => true, 'author'=> true, 'category'=> true, 'copyright'=> true, 'deprecated'=> true, 'example'=> true, 'filesource'=> true, 'global'=> true, 'ignore'=> true, /* Can we enable this? 'index' => true, */ 'internal'=> true, 'license'=> true, 'link'=> true, 'method' => true, 'package'=> true, 'param'=> true, 'property' => true, 'property-read' => true, 'property-write' => true, 'return'=> true, 'see'=> true, 'since'=> true, 'source' => true, 'subpackage'=> true, 'throws'=> true, 'todo'=> true, 'TODO'=> true, 'usedby'=> true, 'uses' => true, 'var'=> true, 'version'=> true, // PHPUnit tags 'codeCoverageIgnore' => true, 'codeCoverageIgnoreStart' => true, 'codeCoverageIgnoreEnd' => true, // PHPCheckStyle 'SuppressWarnings' => true, // PHPStorm 'noinspection' => true, // PEAR 'package_version' => true, // PlantUML 'startuml' => true, 'enduml' => true, ); /** * Add a new annotation to the globally ignored annotation names with regard to exception handling. * * @param string $name */ static public function addGlobalIgnoredName($name) { self::$globalIgnoredNames[$name] = true; } /** * Annotations parser. * * @var \Doctrine\Common\Annotations\DocParser */ private $parser; /** * Annotations parser used to collect parsing metadata. * * @var \Doctrine\Common\Annotations\DocParser */ private $preParser; /** * PHP parser used to collect imports. * * @var \Doctrine\Common\Annotations\PhpParser */ private $phpParser; /** * In-memory cache mechanism to store imported annotations per class. * * @var array */ private $imports = array(); /** * In-memory cache mechanism to store ignored annotations per class. * * @var array */ private $ignoredAnnotationNames = array(); /** * Constructor. * * Initializes a new AnnotationReader. */ public function __construct() { if (extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.save_comments') === "0" || ini_get('opcache.save_comments') === "0")) { throw AnnotationException::optimizerPlusSaveComments(); } if (extension_loaded('Zend OPcache') && ini_get('opcache.save_comments') == 0) { throw AnnotationException::optimizerPlusSaveComments(); } if (PHP_VERSION_ID < 70000) { if (extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.load_comments') === "0" || ini_get('opcache.load_comments') === "0")) { throw AnnotationException::optimizerPlusLoadComments(); } if (extension_loaded('Zend OPcache') && ini_get('opcache.load_comments') == 0) { throw AnnotationException::optimizerPlusLoadComments(); } } AnnotationRegistry::registerFile(__DIR__ . '/Annotation/IgnoreAnnotation.php'); $this->parser = new DocParser; $this->preParser = new DocParser; $this->preParser->setImports(self::$globalImports); $this->preParser->setIgnoreNotImportedAnnotations(true); $this->phpParser = new PhpParser; } /** * {@inheritDoc} */ public function getClassAnnotations(ReflectionClass $class) { $this->parser->setTarget(Target::TARGET_CLASS); $this->parser->setImports($this->getClassImports($class)); $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName()); } /** * {@inheritDoc} */ public function getClassAnnotation(ReflectionClass $class, $annotationName) { $annotations = $this->getClassAnnotations($class); foreach ($annotations as $annotation) { if ($annotation instanceof $annotationName) { return $annotation; } } return null; } /** * {@inheritDoc} */ public function getPropertyAnnotations(ReflectionProperty $property) { $class = $property->getDeclaringClass(); $context = 'property ' . $class->getName() . "::\$" . $property->getName(); $this->parser->setTarget(Target::TARGET_PROPERTY); $this->parser->setImports($this->getPropertyImports($property)); $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); return $this->parser->parse($property->getDocComment(), $context); } /** * {@inheritDoc} */ public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) { $annotations = $this->getPropertyAnnotations($property); foreach ($annotations as $annotation) { if ($annotation instanceof $annotationName) { return $annotation; } } return null; } /** * {@inheritDoc} */ public function getMethodAnnotations(ReflectionMethod $method) { $class = $method->getDeclaringClass(); $context = 'method ' . $class->getName() . '::' . $method->getName() . '()'; $this->parser->setTarget(Target::TARGET_METHOD); $this->parser->setImports($this->getMethodImports($method)); $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); return $this->parser->parse($method->getDocComment(), $context); } /** * {@inheritDoc} */ public function getMethodAnnotation(ReflectionMethod $method, $annotationName) { $annotations = $this->getMethodAnnotations($method); foreach ($annotations as $annotation) { if ($annotation instanceof $annotationName) { return $annotation; } } return null; } /** * Returns the ignored annotations for the given class. * * @param \ReflectionClass $class * * @return array */ private function getIgnoredAnnotationNames(ReflectionClass $class) { if (isset($this->ignoredAnnotationNames[$name = $class->getName()])) { return $this->ignoredAnnotationNames[$name]; } $this->collectParsingMetadata($class); return $this->ignoredAnnotationNames[$name]; } /** * Retrieves imports. * * @param \ReflectionClass $class * * @return array */ private function getClassImports(ReflectionClass $class) { if (isset($this->imports[$name = $class->getName()])) { return $this->imports[$name]; } $this->collectParsingMetadata($class); return $this->imports[$name]; } /** * Retrieves imports for methods. * * @param \ReflectionMethod $method * * @return array */ private function getMethodImports(ReflectionMethod $method) { $class = $method->getDeclaringClass(); $classImports = $this->getClassImports($class); if (!method_exists($class, 'getTraits')) { return $classImports; } $traitImports = array(); foreach ($class->getTraits() as $trait) { if ($trait->hasMethod($method->getName()) && $trait->getFileName() === $method->getFileName() ) { $traitImports = array_merge($traitImports, $this->phpParser->parseClass($trait)); } } return array_merge($classImports, $traitImports); } /** * Retrieves imports for properties. * * @param \ReflectionProperty $property * * @return array */ private function getPropertyImports(ReflectionProperty $property) { $class = $property->getDeclaringClass(); $classImports = $this->getClassImports($class); if (!method_exists($class, 'getTraits')) { return $classImports; } $traitImports = array(); foreach ($class->getTraits() as $trait) { if ($trait->hasProperty($property->getName())) { $traitImports = array_merge($traitImports, $this->phpParser->parseClass($trait)); } } return array_merge($classImports, $traitImports); } /** * Collects parsing metadata for a given class. * * @param \ReflectionClass $class */ private function collectParsingMetadata(ReflectionClass $class) { $ignoredAnnotationNames = self::$globalIgnoredNames; $annotations = $this->preParser->parse($class->getDocComment(), 'class ' . $class->name); foreach ($annotations as $annotation) { if ($annotation instanceof IgnoreAnnotation) { foreach ($annotation->names AS $annot) { $ignoredAnnotationNames[$annot] = true; } } } $name = $class->getName(); $this->imports[$name] = array_merge( self::$globalImports, $this->phpParser->parseClass($class), array('__NAMESPACE__' => $class->getNamespaceName()) ); $this->ignoredAnnotationNames[$name] = $ignoredAnnotationNames; } } . */ namespace Doctrine\Common\Annotations; use Doctrine\Common\Cache\Cache; /** * A cache aware annotation reader. * * @author Johannes M. Schmitt * @author Benjamin Eberlei */ final class CachedReader implements Reader { /** * @var string */ private static $CACHE_SALT = '@[Annot]'; /** * @var Reader */ private $delegate; /** * @var Cache */ private $cache; /** * @var boolean */ private $debug; /** * @var array */ private $loadedAnnotations = array(); /** * Constructor. * * @param Reader $reader * @param Cache $cache * @param bool $debug */ public function __construct(Reader $reader, Cache $cache, $debug = false) { $this->delegate = $reader; $this->cache = $cache; $this->debug = (boolean) $debug; } /** * {@inheritDoc} */ public function getClassAnnotations(\ReflectionClass $class) { $cacheKey = $class->getName(); if (isset($this->loadedAnnotations[$cacheKey])) { return $this->loadedAnnotations[$cacheKey]; } if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { $annots = $this->delegate->getClassAnnotations($class); $this->saveToCache($cacheKey, $annots); } return $this->loadedAnnotations[$cacheKey] = $annots; } /** * {@inheritDoc} */ public function getClassAnnotation(\ReflectionClass $class, $annotationName) { foreach ($this->getClassAnnotations($class) as $annot) { if ($annot instanceof $annotationName) { return $annot; } } return null; } /** * {@inheritDoc} */ public function getPropertyAnnotations(\ReflectionProperty $property) { $class = $property->getDeclaringClass(); $cacheKey = $class->getName().'$'.$property->getName(); if (isset($this->loadedAnnotations[$cacheKey])) { return $this->loadedAnnotations[$cacheKey]; } if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { $annots = $this->delegate->getPropertyAnnotations($property); $this->saveToCache($cacheKey, $annots); } return $this->loadedAnnotations[$cacheKey] = $annots; } /** * {@inheritDoc} */ public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) { foreach ($this->getPropertyAnnotations($property) as $annot) { if ($annot instanceof $annotationName) { return $annot; } } return null; } /** * {@inheritDoc} */ public function getMethodAnnotations(\ReflectionMethod $method) { $class = $method->getDeclaringClass(); $cacheKey = $class->getName().'#'.$method->getName(); if (isset($this->loadedAnnotations[$cacheKey])) { return $this->loadedAnnotations[$cacheKey]; } if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { $annots = $this->delegate->getMethodAnnotations($method); $this->saveToCache($cacheKey, $annots); } return $this->loadedAnnotations[$cacheKey] = $annots; } /** * {@inheritDoc} */ public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) { foreach ($this->getMethodAnnotations($method) as $annot) { if ($annot instanceof $annotationName) { return $annot; } } return null; } /** * Clears loaded annotations. * * @return void */ public function clearLoadedAnnotations() { $this->loadedAnnotations = array(); } /** * Fetches a value from the cache. * * @param string $rawCacheKey The cache key. * @param \ReflectionClass $class The related class. * * @return mixed The cached value or false when the value is not in cache. */ private function fetchFromCache($rawCacheKey, \ReflectionClass $class) { $cacheKey = $rawCacheKey . self::$CACHE_SALT; if (($data = $this->cache->fetch($cacheKey)) !== false) { if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) { return $data; } } return false; } /** * Saves a value to the cache. * * @param string $rawCacheKey The cache key. * @param mixed $value The value. * * @return void */ private function saveToCache($rawCacheKey, $value) { $cacheKey = $rawCacheKey . self::$CACHE_SALT; $this->cache->save($cacheKey, $value); if ($this->debug) { $this->cache->save('[C]'.$cacheKey, time()); } } /** * Checks if the cache is fresh. * * @param string $cacheKey * @param \ReflectionClass $class * * @return boolean */ private function isCacheFresh($cacheKey, \ReflectionClass $class) { if (false === $filename = $class->getFilename()) { return true; } return $this->cache->fetch('[C]'.$cacheKey) >= filemtime($filename); } } . */ namespace Doctrine\Common\Annotations\Annotation; /** * Annotation that can be used to signal to the parser * to check if that attribute is required during the parsing process. * * @author Fabio B. Silva * * @Annotation */ final class Required { } . */ namespace Doctrine\Common\Annotations\Annotation; /** * Annotation that can be used to signal to the parser * to check the types of all declared attributes during the parsing process. * * @author Fabio B. Silva * * @Annotation */ final class Attributes { /** * @var array */ public $value; } . */ namespace Doctrine\Common\Annotations\Annotation; /** * Annotation that can be used to signal to the parser * to check the annotation target during the parsing process. * * @author Fabio B. Silva * * @Annotation */ final class Target { const TARGET_CLASS = 1; const TARGET_METHOD = 2; const TARGET_PROPERTY = 4; const TARGET_ANNOTATION = 8; const TARGET_ALL = 15; /** * @var array */ private static $map = array( 'ALL' => self::TARGET_ALL, 'CLASS' => self::TARGET_CLASS, 'METHOD' => self::TARGET_METHOD, 'PROPERTY' => self::TARGET_PROPERTY, 'ANNOTATION' => self::TARGET_ANNOTATION, ); /** * @var array */ public $value; /** * Targets as bitmask. * * @var integer */ public $targets; /** * Literal target declaration. * * @var integer */ public $literal; /** * Annotation constructor. * * @param array $values * * @throws \InvalidArgumentException */ public function __construct(array $values) { if (!isset($values['value'])){ $values['value'] = null; } if (is_string($values['value'])){ $values['value'] = array($values['value']); } if (!is_array($values['value'])){ throw new \InvalidArgumentException( sprintf('@Target expects either a string value, or an array of strings, "%s" given.', is_object($values['value']) ? get_class($values['value']) : gettype($values['value']) ) ); } $bitmask = 0; foreach ($values['value'] as $literal) { if(!isset(self::$map[$literal])){ throw new \InvalidArgumentException( sprintf('Invalid Target "%s". Available targets: [%s]', $literal, implode(', ', array_keys(self::$map))) ); } $bitmask |= self::$map[$literal]; } $this->targets = $bitmask; $this->value = $values['value']; $this->literal = implode(', ', $this->value); } } . */ namespace Doctrine\Common\Annotations\Annotation; /** * Annotation that can be used to signal to the parser to ignore specific * annotations during the parsing process. * * @Annotation * @author Johannes M. Schmitt */ final class IgnoreAnnotation { /** * @var array */ public $names; /** * Constructor. * * @param array $values * * @throws \RuntimeException */ public function __construct(array $values) { if (is_string($values['value'])) { $values['value'] = array($values['value']); } if (!is_array($values['value'])) { throw new \RuntimeException(sprintf('@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', json_encode($values['value']))); } $this->names = $values['value']; } } . */ namespace Doctrine\Common\Annotations\Annotation; /** * Annotation that can be used to signal to the parser * to check the attribute type during the parsing process. * * @author Fabio B. Silva * * @Annotation */ final class Attribute { /** * @var string */ public $name; /** * @var string */ public $type; /** * @var boolean */ public $required = false; } . */ namespace Doctrine\Common\Annotations\Annotation; /** * Annotation that can be used to signal to the parser * to check the available values during the parsing process. * * @since 2.4 * @author Fabio B. Silva * * @Annotation * @Attributes({ * @Attribute("value", required = true, type = "array"), * @Attribute("literal", required = false, type = "array") * }) */ final class Enum { /** * @var array */ public $value; /** * Literal target declaration. * * @var array */ public $literal; /** * Annotation constructor. * * @param array $values * * @throws \InvalidArgumentException */ public function __construct(array $values) { if ( ! isset($values['literal'])) { $values['literal'] = array(); } foreach ($values['value'] as $var) { if( ! is_scalar($var)) { throw new \InvalidArgumentException(sprintf( '@Enum supports only scalar values "%s" given.', is_object($var) ? get_class($var) : gettype($var) )); } } foreach ($values['literal'] as $key => $var) { if( ! in_array($key, $values['value'])) { throw new \InvalidArgumentException(sprintf( 'Undefined enumerator value "%s" for literal "%s".', $key , $var )); } } $this->value = $values['value']; $this->literal = $values['literal']; } } . */ namespace Doctrine\Common\Annotations; use Doctrine\Common\Annotations\Annotation\Attribute; use ReflectionClass; use Doctrine\Common\Annotations\Annotation\Enum; use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Attributes; /** * A parser for docblock annotations. * * It is strongly discouraged to change the default annotation parsing process. * * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Johannes M. Schmitt * @author Fabio B. Silva */ final class DocParser { /** * An array of all valid tokens for a class name. * * @var array */ private static $classIdentifiers = array( DocLexer::T_IDENTIFIER, DocLexer::T_TRUE, DocLexer::T_FALSE, DocLexer::T_NULL ); /** * The lexer. * * @var \Doctrine\Common\Annotations\DocLexer */ private $lexer; /** * Current target context. * * @var string */ private $target; /** * Doc parser used to collect annotation target. * * @var \Doctrine\Common\Annotations\DocParser */ private static $metadataParser; /** * Flag to control if the current annotation is nested or not. * * @var boolean */ private $isNestedAnnotation = false; /** * Hashmap containing all use-statements that are to be used when parsing * the given doc block. * * @var array */ private $imports = array(); /** * This hashmap is used internally to cache results of class_exists() * look-ups. * * @var array */ private $classExists = array(); /** * Whether annotations that have not been imported should be ignored. * * @var boolean */ private $ignoreNotImportedAnnotations = false; /** * An array of default namespaces if operating in simple mode. * * @var array */ private $namespaces = array(); /** * A list with annotations that are not causing exceptions when not resolved to an annotation class. * * The names must be the raw names as used in the class, not the fully qualified * class names. * * @var array */ private $ignoredAnnotationNames = array(); /** * @var string */ private $context = ''; /** * Hash-map for caching annotation metadata. * * @var array */ private static $annotationMetadata = array( 'Doctrine\Common\Annotations\Annotation\Target' => array( 'is_annotation' => true, 'has_constructor' => true, 'properties' => array(), 'targets_literal' => 'ANNOTATION_CLASS', 'targets' => Target::TARGET_CLASS, 'default_property' => 'value', 'attribute_types' => array( 'value' => array( 'required' => false, 'type' =>'array', 'array_type'=>'string', 'value' =>'array' ) ), ), 'Doctrine\Common\Annotations\Annotation\Attribute' => array( 'is_annotation' => true, 'has_constructor' => false, 'targets_literal' => 'ANNOTATION_ANNOTATION', 'targets' => Target::TARGET_ANNOTATION, 'default_property' => 'name', 'properties' => array( 'name' => 'name', 'type' => 'type', 'required' => 'required' ), 'attribute_types' => array( 'value' => array( 'required' => true, 'type' =>'string', 'value' =>'string' ), 'type' => array( 'required' =>true, 'type' =>'string', 'value' =>'string' ), 'required' => array( 'required' =>false, 'type' =>'boolean', 'value' =>'boolean' ) ), ), 'Doctrine\Common\Annotations\Annotation\Attributes' => array( 'is_annotation' => true, 'has_constructor' => false, 'targets_literal' => 'ANNOTATION_CLASS', 'targets' => Target::TARGET_CLASS, 'default_property' => 'value', 'properties' => array( 'value' => 'value' ), 'attribute_types' => array( 'value' => array( 'type' =>'array', 'required' =>true, 'array_type'=>'Doctrine\Common\Annotations\Annotation\Attribute', 'value' =>'array' ) ), ), 'Doctrine\Common\Annotations\Annotation\Enum' => array( 'is_annotation' => true, 'has_constructor' => true, 'targets_literal' => 'ANNOTATION_PROPERTY', 'targets' => Target::TARGET_PROPERTY, 'default_property' => 'value', 'properties' => array( 'value' => 'value' ), 'attribute_types' => array( 'value' => array( 'type' => 'array', 'required' => true, ), 'literal' => array( 'type' => 'array', 'required' => false, ), ), ), ); /** * Hash-map for handle types declaration. * * @var array */ private static $typeMap = array( 'float' => 'double', 'bool' => 'boolean', // allow uppercase Boolean in honor of George Boole 'Boolean' => 'boolean', 'int' => 'integer', ); /** * Constructs a new DocParser. */ public function __construct() { $this->lexer = new DocLexer; } /** * Sets the annotation names that are ignored during the parsing process. * * The names are supposed to be the raw names as used in the class, not the * fully qualified class names. * * @param array $names * * @return void */ public function setIgnoredAnnotationNames(array $names) { $this->ignoredAnnotationNames = $names; } /** * Sets ignore on not-imported annotations. * * @param boolean $bool * * @return void */ public function setIgnoreNotImportedAnnotations($bool) { $this->ignoreNotImportedAnnotations = (boolean) $bool; } /** * Sets the default namespaces. * * @param array $namespace * * @return void * * @throws \RuntimeException */ public function addNamespace($namespace) { if ($this->imports) { throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); } $this->namespaces[] = $namespace; } /** * Sets the imports. * * @param array $imports * * @return void * * @throws \RuntimeException */ public function setImports(array $imports) { if ($this->namespaces) { throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); } $this->imports = $imports; } /** * Sets current target context as bitmask. * * @param integer $target * * @return void */ public function setTarget($target) { $this->target = $target; } /** * Parses the given docblock string for annotations. * * @param string $input The docblock string to parse. * @param string $context The parsing context. * * @return array Array of annotations. If no annotations are found, an empty array is returned. */ public function parse($input, $context = '') { $pos = $this->findInitialTokenPosition($input); if ($pos === null) { return array(); } $this->context = $context; $this->lexer->setInput(trim(substr($input, $pos), '* /')); $this->lexer->moveNext(); return $this->Annotations(); } /** * Finds the first valid annotation * * @param string $input The docblock string to parse * * @return int|null */ private function findInitialTokenPosition($input) { $pos = 0; // search for first valid annotation while (($pos = strpos($input, '@', $pos)) !== false) { // if the @ is preceded by a space or * it is valid if ($pos === 0 || $input[$pos - 1] === ' ' || $input[$pos - 1] === '*') { return $pos; } $pos++; } return null; } /** * Attempts to match the given token with the current lookahead token. * If they match, updates the lookahead token; otherwise raises a syntax error. * * @param integer $token Type of token. * * @return boolean True if tokens match; false otherwise. */ private function match($token) { if ( ! $this->lexer->isNextToken($token) ) { $this->syntaxError($this->lexer->getLiteral($token)); } return $this->lexer->moveNext(); } /** * Attempts to match the current lookahead token with any of the given tokens. * * If any of them matches, this method updates the lookahead token; otherwise * a syntax error is raised. * * @param array $tokens * * @return boolean */ private function matchAny(array $tokens) { if ( ! $this->lexer->isNextTokenAny($tokens)) { $this->syntaxError(implode(' or ', array_map(array($this->lexer, 'getLiteral'), $tokens))); } return $this->lexer->moveNext(); } /** * Generates a new syntax error. * * @param string $expected Expected string. * @param array|null $token Optional token. * * @return void * * @throws AnnotationException */ private function syntaxError($expected, $token = null) { if ($token === null) { $token = $this->lexer->lookahead; } $message = sprintf('Expected %s, got ', $expected); $message .= ($this->lexer->lookahead === null) ? 'end of string' : sprintf("'%s' at position %s", $token['value'], $token['position']); if (strlen($this->context)) { $message .= ' in ' . $this->context; } $message .= '.'; throw AnnotationException::syntaxError($message); } /** * Attempts to check if a class exists or not. This never goes through the PHP autoloading mechanism * but uses the {@link AnnotationRegistry} to load classes. * * @param string $fqcn * * @return boolean */ private function classExists($fqcn) { if (isset($this->classExists[$fqcn])) { return $this->classExists[$fqcn]; } // first check if the class already exists, maybe loaded through another AnnotationReader if (class_exists($fqcn, false)) { return $this->classExists[$fqcn] = true; } // final check, does this class exist? return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn); } /** * Collects parsing metadata for a given annotation class * * @param string $name The annotation name * * @return void */ private function collectAnnotationMetadata($name) { if (self::$metadataParser === null) { self::$metadataParser = new self(); self::$metadataParser->setIgnoreNotImportedAnnotations(true); self::$metadataParser->setIgnoredAnnotationNames($this->ignoredAnnotationNames); self::$metadataParser->setImports(array( 'enum' => 'Doctrine\Common\Annotations\Annotation\Enum', 'target' => 'Doctrine\Common\Annotations\Annotation\Target', 'attribute' => 'Doctrine\Common\Annotations\Annotation\Attribute', 'attributes' => 'Doctrine\Common\Annotations\Annotation\Attributes' )); AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Enum.php'); AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Target.php'); AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attribute.php'); AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attributes.php'); } $class = new \ReflectionClass($name); $docComment = $class->getDocComment(); // Sets default values for annotation metadata $metadata = array( 'default_property' => null, 'has_constructor' => (null !== $constructor = $class->getConstructor()) && $constructor->getNumberOfParameters() > 0, 'properties' => array(), 'property_types' => array(), 'attribute_types' => array(), 'targets_literal' => null, 'targets' => Target::TARGET_ALL, 'is_annotation' => false !== strpos($docComment, '@Annotation'), ); // verify that the class is really meant to be an annotation if ($metadata['is_annotation']) { self::$metadataParser->setTarget(Target::TARGET_CLASS); foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) { if ($annotation instanceof Target) { $metadata['targets'] = $annotation->targets; $metadata['targets_literal'] = $annotation->literal; continue; } if ($annotation instanceof Attributes) { foreach ($annotation->value as $attribute) { $this->collectAttributeTypeMetadata($metadata, $attribute); } } } // if not has a constructor will inject values into public properties if (false === $metadata['has_constructor']) { // collect all public properties foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { $metadata['properties'][$property->name] = $property->name; if (false === ($propertyComment = $property->getDocComment())) { continue; } $attribute = new Attribute(); $attribute->required = (false !== strpos($propertyComment, '@Required')); $attribute->name = $property->name; $attribute->type = (false !== strpos($propertyComment, '@var') && preg_match('/@var\s+([^\s]+)/',$propertyComment, $matches)) ? $matches[1] : 'mixed'; $this->collectAttributeTypeMetadata($metadata, $attribute); // checks if the property has @Enum if (false !== strpos($propertyComment, '@Enum')) { $context = 'property ' . $class->name . "::\$" . $property->name; self::$metadataParser->setTarget(Target::TARGET_PROPERTY); foreach (self::$metadataParser->parse($propertyComment, $context) as $annotation) { if ( ! $annotation instanceof Enum) { continue; } $metadata['enum'][$property->name]['value'] = $annotation->value; $metadata['enum'][$property->name]['literal'] = ( ! empty($annotation->literal)) ? $annotation->literal : $annotation->value; } } } // choose the first property as default property $metadata['default_property'] = reset($metadata['properties']); } } self::$annotationMetadata[$name] = $metadata; } /** * Collects parsing metadata for a given attribute. * * @param array $metadata * @param Attribute $attribute * * @return void */ private function collectAttributeTypeMetadata(&$metadata, Attribute $attribute) { // handle internal type declaration $type = isset(self::$typeMap[$attribute->type]) ? self::$typeMap[$attribute->type] : $attribute->type; // handle the case if the property type is mixed if ('mixed' === $type) { return; } // Evaluate type switch (true) { // Checks if the property has array case (false !== $pos = strpos($type, '<')): $arrayType = substr($type, $pos + 1, -1); $type = 'array'; if (isset(self::$typeMap[$arrayType])) { $arrayType = self::$typeMap[$arrayType]; } $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; break; // Checks if the property has type[] case (false !== $pos = strrpos($type, '[')): $arrayType = substr($type, 0, $pos); $type = 'array'; if (isset(self::$typeMap[$arrayType])) { $arrayType = self::$typeMap[$arrayType]; } $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; break; } $metadata['attribute_types'][$attribute->name]['type'] = $type; $metadata['attribute_types'][$attribute->name]['value'] = $attribute->type; $metadata['attribute_types'][$attribute->name]['required'] = $attribute->required; } /** * Annotations ::= Annotation {[ "*" ]* [Annotation]}* * * @return array */ private function Annotations() { $annotations = array(); while (null !== $this->lexer->lookahead) { if (DocLexer::T_AT !== $this->lexer->lookahead['type']) { $this->lexer->moveNext(); continue; } // make sure the @ is preceded by non-catchable pattern if (null !== $this->lexer->token && $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value'])) { $this->lexer->moveNext(); continue; } // make sure the @ is followed by either a namespace separator, or // an identifier token if ((null === $peek = $this->lexer->glimpse()) || (DocLexer::T_NAMESPACE_SEPARATOR !== $peek['type'] && !in_array($peek['type'], self::$classIdentifiers, true)) || $peek['position'] !== $this->lexer->lookahead['position'] + 1) { $this->lexer->moveNext(); continue; } $this->isNestedAnnotation = false; if (false !== $annot = $this->Annotation()) { $annotations[] = $annot; } } return $annotations; } /** * Annotation ::= "@" AnnotationName MethodCall * AnnotationName ::= QualifiedName | SimpleName * QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName * NameSpacePart ::= identifier | null | false | true * SimpleName ::= identifier | null | false | true * * @return mixed False if it is not a valid annotation. * * @throws AnnotationException */ private function Annotation() { $this->match(DocLexer::T_AT); // check if we have an annotation $name = $this->Identifier(); // only process names which are not fully qualified, yet // fully qualified names must start with a \ $originalName = $name; if ('\\' !== $name[0]) { $alias = (false === $pos = strpos($name, '\\'))? $name : substr($name, 0, $pos); $found = false; if ($this->namespaces) { foreach ($this->namespaces as $namespace) { if ($this->classExists($namespace.'\\'.$name)) { $name = $namespace.'\\'.$name; $found = true; break; } } } elseif (isset($this->imports[$loweredAlias = strtolower($alias)])) { $found = true; $name = (false !== $pos) ? $this->imports[$loweredAlias] . substr($name, $pos) : $this->imports[$loweredAlias]; } elseif ( ! isset($this->ignoredAnnotationNames[$name]) && isset($this->imports['__NAMESPACE__']) && $this->classExists($this->imports['__NAMESPACE__'] . '\\' . $name) ) { $name = $this->imports['__NAMESPACE__'].'\\'.$name; $found = true; } elseif (! isset($this->ignoredAnnotationNames[$name]) && $this->classExists($name)) { $found = true; } if ( ! $found) { if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) { return false; } throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?', $name, $this->context)); } } if ( ! $this->classExists($name)) { throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s does not exist, or could not be auto-loaded.', $name, $this->context)); } // at this point, $name contains the fully qualified class name of the // annotation, and it is also guaranteed that this class exists, and // that it is loaded // collects the metadata annotation only if there is not yet if ( ! isset(self::$annotationMetadata[$name])) { $this->collectAnnotationMetadata($name); } // verify that the class is really meant to be an annotation and not just any ordinary class if (self::$annotationMetadata[$name]['is_annotation'] === false) { if (isset($this->ignoredAnnotationNames[$originalName])) { return false; } throw AnnotationException::semanticalError(sprintf('The class "%s" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "%s". If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s.', $name, $name, $originalName, $this->context)); } //if target is nested annotation $target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target; // Next will be nested $this->isNestedAnnotation = true; //if annotation does not support current target if (0 === (self::$annotationMetadata[$name]['targets'] & $target) && $target) { throw AnnotationException::semanticalError( sprintf('Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s.', $originalName, $this->context, self::$annotationMetadata[$name]['targets_literal']) ); } $values = $this->MethodCall(); if (isset(self::$annotationMetadata[$name]['enum'])) { // checks all declared attributes foreach (self::$annotationMetadata[$name]['enum'] as $property => $enum) { // checks if the attribute is a valid enumerator if (isset($values[$property]) && ! in_array($values[$property], $enum['value'])) { throw AnnotationException::enumeratorError($property, $name, $this->context, $enum['literal'], $values[$property]); } } } // checks all declared attributes foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) { if ($property === self::$annotationMetadata[$name]['default_property'] && !isset($values[$property]) && isset($values['value'])) { $property = 'value'; } // handle a not given attribute or null value if (!isset($values[$property])) { if ($type['required']) { throw AnnotationException::requiredError($property, $originalName, $this->context, 'a(n) '.$type['value']); } continue; } if ($type['type'] === 'array') { // handle the case of a single value if ( ! is_array($values[$property])) { $values[$property] = array($values[$property]); } // checks if the attribute has array type declaration, such as "array" if (isset($type['array_type'])) { foreach ($values[$property] as $item) { if (gettype($item) !== $type['array_type'] && !$item instanceof $type['array_type']) { throw AnnotationException::attributeTypeError($property, $originalName, $this->context, 'either a(n) '.$type['array_type'].', or an array of '.$type['array_type'].'s', $item); } } } } elseif (gettype($values[$property]) !== $type['type'] && !$values[$property] instanceof $type['type']) { throw AnnotationException::attributeTypeError($property, $originalName, $this->context, 'a(n) '.$type['value'], $values[$property]); } } // check if the annotation expects values via the constructor, // or directly injected into public properties if (self::$annotationMetadata[$name]['has_constructor'] === true) { return new $name($values); } $instance = new $name(); foreach ($values as $property => $value) { if (!isset(self::$annotationMetadata[$name]['properties'][$property])) { if ('value' !== $property) { throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not have a property named "%s". Available properties: %s', $originalName, $this->context, $property, implode(', ', self::$annotationMetadata[$name]['properties']))); } // handle the case if the property has no annotations if ( ! $property = self::$annotationMetadata[$name]['default_property']) { throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not accept any values, but got %s.', $originalName, $this->context, json_encode($values))); } } $instance->{$property} = $value; } return $instance; } /** * MethodCall ::= ["(" [Values] ")"] * * @return array */ private function MethodCall() { $values = array(); if ( ! $this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) { return $values; } $this->match(DocLexer::T_OPEN_PARENTHESIS); if ( ! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { $values = $this->Values(); } $this->match(DocLexer::T_CLOSE_PARENTHESIS); return $values; } /** * Values ::= Array | Value {"," Value}* [","] * * @return array */ private function Values() { $values = array($this->Value()); while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { $this->match(DocLexer::T_COMMA); if ($this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { break; } $token = $this->lexer->lookahead; $value = $this->Value(); if ( ! is_object($value) && ! is_array($value)) { $this->syntaxError('Value', $token); } $values[] = $value; } foreach ($values as $k => $value) { if (is_object($value) && $value instanceof \stdClass) { $values[$value->name] = $value->value; } else if ( ! isset($values['value'])){ $values['value'] = $value; } else { if ( ! is_array($values['value'])) { $values['value'] = array($values['value']); } $values['value'][] = $value; } unset($values[$k]); } return $values; } /** * Constant ::= integer | string | float | boolean * * @return mixed * * @throws AnnotationException */ private function Constant() { $identifier = $this->Identifier(); if ( ! defined($identifier) && false !== strpos($identifier, '::') && '\\' !== $identifier[0]) { list($className, $const) = explode('::', $identifier); $alias = (false === $pos = strpos($className, '\\')) ? $className : substr($className, 0, $pos); $found = false; switch (true) { case !empty ($this->namespaces): foreach ($this->namespaces as $ns) { if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) { $className = $ns.'\\'.$className; $found = true; break; } } break; case isset($this->imports[$loweredAlias = strtolower($alias)]): $found = true; $className = (false !== $pos) ? $this->imports[$loweredAlias] . substr($className, $pos) : $this->imports[$loweredAlias]; break; default: if(isset($this->imports['__NAMESPACE__'])) { $ns = $this->imports['__NAMESPACE__']; if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) { $className = $ns.'\\'.$className; $found = true; } } break; } if ($found) { $identifier = $className . '::' . $const; } } // checks if identifier ends with ::class, \strlen('::class') === 7 $classPos = stripos($identifier, '::class'); if ($classPos === strlen($identifier) - 7) { return substr($identifier, 0, $classPos); } if (!defined($identifier)) { throw AnnotationException::semanticalErrorConstants($identifier, $this->context); } return constant($identifier); } /** * Identifier ::= string * * @return string */ private function Identifier() { // check if we have an annotation if ( ! $this->lexer->isNextTokenAny(self::$classIdentifiers)) { $this->syntaxError('namespace separator or identifier'); } $this->lexer->moveNext(); $className = $this->lexer->token['value']; while ($this->lexer->lookahead['position'] === ($this->lexer->token['position'] + strlen($this->lexer->token['value'])) && $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR)) { $this->match(DocLexer::T_NAMESPACE_SEPARATOR); $this->matchAny(self::$classIdentifiers); $className .= '\\' . $this->lexer->token['value']; } return $className; } /** * Value ::= PlainValue | FieldAssignment * * @return mixed */ private function Value() { $peek = $this->lexer->glimpse(); if (DocLexer::T_EQUALS === $peek['type']) { return $this->FieldAssignment(); } return $this->PlainValue(); } /** * PlainValue ::= integer | string | float | boolean | Array | Annotation * * @return mixed */ private function PlainValue() { if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) { return $this->Arrayx(); } if ($this->lexer->isNextToken(DocLexer::T_AT)) { return $this->Annotation(); } if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { return $this->Constant(); } switch ($this->lexer->lookahead['type']) { case DocLexer::T_STRING: $this->match(DocLexer::T_STRING); return $this->lexer->token['value']; case DocLexer::T_INTEGER: $this->match(DocLexer::T_INTEGER); return (int)$this->lexer->token['value']; case DocLexer::T_FLOAT: $this->match(DocLexer::T_FLOAT); return (float)$this->lexer->token['value']; case DocLexer::T_TRUE: $this->match(DocLexer::T_TRUE); return true; case DocLexer::T_FALSE: $this->match(DocLexer::T_FALSE); return false; case DocLexer::T_NULL: $this->match(DocLexer::T_NULL); return null; default: $this->syntaxError('PlainValue'); } } /** * FieldAssignment ::= FieldName "=" PlainValue * FieldName ::= identifier * * @return array */ private function FieldAssignment() { $this->match(DocLexer::T_IDENTIFIER); $fieldName = $this->lexer->token['value']; $this->match(DocLexer::T_EQUALS); $item = new \stdClass(); $item->name = $fieldName; $item->value = $this->PlainValue(); return $item; } /** * Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}" * * @return array */ private function Arrayx() { $array = $values = array(); $this->match(DocLexer::T_OPEN_CURLY_BRACES); // If the array is empty, stop parsing and return. if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { $this->match(DocLexer::T_CLOSE_CURLY_BRACES); return $array; } $values[] = $this->ArrayEntry(); while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { $this->match(DocLexer::T_COMMA); // optional trailing comma if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { break; } $values[] = $this->ArrayEntry(); } $this->match(DocLexer::T_CLOSE_CURLY_BRACES); foreach ($values as $value) { list ($key, $val) = $value; if ($key !== null) { $array[$key] = $val; } else { $array[] = $val; } } return $array; } /** * ArrayEntry ::= Value | KeyValuePair * KeyValuePair ::= Key ("=" | ":") PlainValue | Constant * Key ::= string | integer | Constant * * @return array */ private function ArrayEntry() { $peek = $this->lexer->glimpse(); if (DocLexer::T_EQUALS === $peek['type'] || DocLexer::T_COLON === $peek['type']) { if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { $key = $this->Constant(); } else { $this->matchAny(array(DocLexer::T_INTEGER, DocLexer::T_STRING)); $key = $this->lexer->token['value']; } $this->matchAny(array(DocLexer::T_EQUALS, DocLexer::T_COLON)); return array($key, $this->PlainValue()); } return array(null, $this->Value()); } } . */ namespace Doctrine\Common\Annotations; /** * Interface for annotation readers. * * @author Johannes M. Schmitt */ interface Reader { /** * Gets the annotations applied to a class. * * @param \ReflectionClass $class The ReflectionClass of the class from which * the class annotations should be read. * * @return array An array of Annotations. */ function getClassAnnotations(\ReflectionClass $class); /** * Gets a class annotation. * * @param \ReflectionClass $class The ReflectionClass of the class from which * the class annotations should be read. * @param string $annotationName The name of the annotation. * * @return object|null The Annotation or NULL, if the requested annotation does not exist. */ function getClassAnnotation(\ReflectionClass $class, $annotationName); /** * Gets the annotations applied to a method. * * @param \ReflectionMethod $method The ReflectionMethod of the method from which * the annotations should be read. * * @return array An array of Annotations. */ function getMethodAnnotations(\ReflectionMethod $method); /** * Gets a method annotation. * * @param \ReflectionMethod $method The ReflectionMethod to read the annotations from. * @param string $annotationName The name of the annotation. * * @return object|null The Annotation or NULL, if the requested annotation does not exist. */ function getMethodAnnotation(\ReflectionMethod $method, $annotationName); /** * Gets the annotations applied to a property. * * @param \ReflectionProperty $property The ReflectionProperty of the property * from which the annotations should be read. * * @return array An array of Annotations. */ function getPropertyAnnotations(\ReflectionProperty $property); /** * Gets a property annotation. * * @param \ReflectionProperty $property The ReflectionProperty to read the annotations from. * @param string $annotationName The name of the annotation. * * @return object|null The Annotation or NULL, if the requested annotation does not exist. */ function getPropertyAnnotation(\ReflectionProperty $property, $annotationName); } . */ namespace Doctrine\Common\Annotations; /** * Simple Annotation Reader. * * This annotation reader is intended to be used in projects where you have * full-control over all annotations that are available. * * @since 2.2 * @author Johannes M. Schmitt * @author Fabio B. Silva */ class SimpleAnnotationReader implements Reader { /** * @var DocParser */ private $parser; /** * Constructor. * * Initializes a new SimpleAnnotationReader. */ public function __construct() { $this->parser = new DocParser(); $this->parser->setIgnoreNotImportedAnnotations(true); } /** * Adds a namespace in which we will look for annotations. * * @param string $namespace * * @return void */ public function addNamespace($namespace) { $this->parser->addNamespace($namespace); } /** * {@inheritDoc} */ public function getClassAnnotations(\ReflectionClass $class) { return $this->parser->parse($class->getDocComment(), 'class '.$class->getName()); } /** * {@inheritDoc} */ public function getMethodAnnotations(\ReflectionMethod $method) { return $this->parser->parse($method->getDocComment(), 'method '.$method->getDeclaringClass()->name.'::'.$method->getName().'()'); } /** * {@inheritDoc} */ public function getPropertyAnnotations(\ReflectionProperty $property) { return $this->parser->parse($property->getDocComment(), 'property '.$property->getDeclaringClass()->name.'::$'.$property->getName()); } /** * {@inheritDoc} */ public function getClassAnnotation(\ReflectionClass $class, $annotationName) { foreach ($this->getClassAnnotations($class) as $annot) { if ($annot instanceof $annotationName) { return $annot; } } return null; } /** * {@inheritDoc} */ public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) { foreach ($this->getMethodAnnotations($method) as $annot) { if ($annot instanceof $annotationName) { return $annot; } } return null; } /** * {@inheritDoc} */ public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) { foreach ($this->getPropertyAnnotations($property) as $annot) { if ($annot instanceof $annotationName) { return $annot; } } return null; } } . */ namespace Doctrine\Common\Annotations; use Doctrine\Common\Lexer\AbstractLexer; /** * Simple lexer for docblock annotations. * * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Johannes M. Schmitt */ final class DocLexer extends AbstractLexer { const T_NONE = 1; const T_INTEGER = 2; const T_STRING = 3; const T_FLOAT = 4; // All tokens that are also identifiers should be >= 100 const T_IDENTIFIER = 100; const T_AT = 101; const T_CLOSE_CURLY_BRACES = 102; const T_CLOSE_PARENTHESIS = 103; const T_COMMA = 104; const T_EQUALS = 105; const T_FALSE = 106; const T_NAMESPACE_SEPARATOR = 107; const T_OPEN_CURLY_BRACES = 108; const T_OPEN_PARENTHESIS = 109; const T_TRUE = 110; const T_NULL = 111; const T_COLON = 112; /** * @var array */ protected $noCase = array( '@' => self::T_AT, ',' => self::T_COMMA, '(' => self::T_OPEN_PARENTHESIS, ')' => self::T_CLOSE_PARENTHESIS, '{' => self::T_OPEN_CURLY_BRACES, '}' => self::T_CLOSE_CURLY_BRACES, '=' => self::T_EQUALS, ':' => self::T_COLON, '\\' => self::T_NAMESPACE_SEPARATOR ); /** * @var array */ protected $withCase = array( 'true' => self::T_TRUE, 'false' => self::T_FALSE, 'null' => self::T_NULL ); /** * {@inheritdoc} */ protected function getCatchablePatterns() { return array( '[a-z_\\\][a-z0-9_\:\\\]*[a-z_][a-z0-9_]*', '(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?', '"(?:""|[^"])*+"', ); } /** * {@inheritdoc} */ protected function getNonCatchablePatterns() { return array('\s+', '\*+', '(.)'); } /** * {@inheritdoc} */ protected function getType(&$value) { $type = self::T_NONE; if ($value[0] === '"') { $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2)); return self::T_STRING; } if (isset($this->noCase[$value])) { return $this->noCase[$value]; } if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) { return self::T_IDENTIFIER; } $lowerValue = strtolower($value); if (isset($this->withCase[$lowerValue])) { return $this->withCase[$lowerValue]; } // Checking numeric value if (is_numeric($value)) { return (strpos($value, '.') !== false || stripos($value, 'e') !== false) ? self::T_FLOAT : self::T_INTEGER; } return $type; } } . */ namespace Doctrine\Common\Annotations; /** * Description of AnnotationException * * @since 2.0 * @author Benjamin Eberlei * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ class AnnotationException extends \Exception { /** * Creates a new AnnotationException describing a Syntax error. * * @param string $message Exception message * * @return AnnotationException */ public static function syntaxError($message) { return new self('[Syntax Error] ' . $message); } /** * Creates a new AnnotationException describing a Semantical error. * * @param string $message Exception message * * @return AnnotationException */ public static function semanticalError($message) { return new self('[Semantical Error] ' . $message); } /** * Creates a new AnnotationException describing an error which occurred during * the creation of the annotation. * * @since 2.2 * * @param string $message * * @return AnnotationException */ public static function creationError($message) { return new self('[Creation Error] ' . $message); } /** * Creates a new AnnotationException describing a type error. * * @since 1.1 * * @param string $message * * @return AnnotationException */ public static function typeError($message) { return new self('[Type Error] ' . $message); } /** * Creates a new AnnotationException describing a constant semantical error. * * @since 2.3 * * @param string $identifier * @param string $context * * @return AnnotationException */ public static function semanticalErrorConstants($identifier, $context = null) { return self::semanticalError(sprintf( "Couldn't find constant %s%s.", $identifier, $context ? ', ' . $context : '' )); } /** * Creates a new AnnotationException describing an type error of an attribute. * * @since 2.2 * * @param string $attributeName * @param string $annotationName * @param string $context * @param string $expected * @param mixed $actual * * @return AnnotationException */ public static function attributeTypeError($attributeName, $annotationName, $context, $expected, $actual) { return self::typeError(sprintf( 'Attribute "%s" of @%s declared on %s expects %s, but got %s.', $attributeName, $annotationName, $context, $expected, is_object($actual) ? 'an instance of ' . get_class($actual) : gettype($actual) )); } /** * Creates a new AnnotationException describing an required error of an attribute. * * @since 2.2 * * @param string $attributeName * @param string $annotationName * @param string $context * @param string $expected * * @return AnnotationException */ public static function requiredError($attributeName, $annotationName, $context, $expected) { return self::typeError(sprintf( 'Attribute "%s" of @%s declared on %s expects %s. This value should not be null.', $attributeName, $annotationName, $context, $expected )); } /** * Creates a new AnnotationException describing a invalid enummerator. * * @since 2.4 * * @param string $attributeName * @param string $annotationName * @param string $context * @param array $available * @param mixed $given * * @return AnnotationException */ public static function enumeratorError($attributeName, $annotationName, $context, $available, $given) { return new self(sprintf( '[Enum Error] Attribute "%s" of @%s declared on %s accept only [%s], but got %s.', $attributeName, $annotationName, $context, implode(', ', $available), is_object($given) ? get_class($given) : $given )); } /** * @return AnnotationException */ public static function optimizerPlusSaveComments() { return new self( "You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1." ); } /** * @return AnnotationException */ public static function optimizerPlusLoadComments() { return new self( "You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1." ); } } . */ namespace Doctrine\Common\Annotations; use SplFileObject; /** * Parses a file for namespaces/use/class declarations. * * @author Fabien Potencier * @author Christian Kaps */ final class PhpParser { /** * Parses a class. * * @param \ReflectionClass $class A ReflectionClass object. * * @return array A list with use statements in the form (Alias => FQN). */ public function parseClass(\ReflectionClass $class) { if (method_exists($class, 'getUseStatements')) { return $class->getUseStatements(); } if (false === $filename = $class->getFilename()) { return array(); } $content = $this->getFileContent($filename, $class->getStartLine()); if (null === $content) { return array(); } $namespace = preg_quote($class->getNamespaceName()); $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content); $tokenizer = new TokenParser('parseUseStatements($class->getNamespaceName()); return $statements; } /** * Gets the content of the file right up to the given line number. * * @param string $filename The name of the file to load. * @param integer $lineNumber The number of lines to read from file. * * @return string The content of the file. */ private function getFileContent($filename, $lineNumber) { if ( ! is_file($filename)) { return null; } $content = ''; $lineCnt = 0; $file = new SplFileObject($filename); while (!$file->eof()) { if ($lineCnt++ == $lineNumber) { break; } $content .= $file->fgets(); } return $content; } } . */ namespace Doctrine\Common\Annotations; /** * Parses a file for namespaces/use/class declarations. * * @author Fabien Potencier * @author Christian Kaps */ class TokenParser { /** * The token list. * * @var array */ private $tokens; /** * The number of tokens. * * @var int */ private $numTokens; /** * The current array pointer. * * @var int */ private $pointer = 0; /** * @param string $contents */ public function __construct($contents) { $this->tokens = token_get_all($contents); // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a // docblock. If the first thing in the file is a class without a doc block this would cause calls to // getDocBlock() on said class to return our long lost doc_comment. Argh. // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least // it's harmless to us. token_get_all("numTokens = count($this->tokens); } /** * Gets the next non whitespace and non comment token. * * @param boolean $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped. * If FALSE then only whitespace and normal comments are skipped. * * @return array|null The token if exists, null otherwise. */ public function next($docCommentIsComment = TRUE) { for ($i = $this->pointer; $i < $this->numTokens; $i++) { $this->pointer++; if ($this->tokens[$i][0] === T_WHITESPACE || $this->tokens[$i][0] === T_COMMENT || ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)) { continue; } return $this->tokens[$i]; } return null; } /** * Parses a single use statement. * * @return array A list with all found class names for a use statement. */ public function parseUseStatement() { $class = ''; $alias = ''; $statements = array(); $explicitAlias = false; while (($token = $this->next())) { $isNameToken = $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR; if (!$explicitAlias && $isNameToken) { $class .= $token[1]; $alias = $token[1]; } else if ($explicitAlias && $isNameToken) { $alias .= $token[1]; } else if ($token[0] === T_AS) { $explicitAlias = true; $alias = ''; } else if ($token === ',') { $statements[strtolower($alias)] = $class; $class = ''; $alias = ''; $explicitAlias = false; } else if ($token === ';') { $statements[strtolower($alias)] = $class; break; } else { break; } } return $statements; } /** * Gets all use statements. * * @param string $namespaceName The namespace name of the reflected class. * * @return array A list with all found use statements. */ public function parseUseStatements($namespaceName) { $statements = array(); while (($token = $this->next())) { if ($token[0] === T_USE) { $statements = array_merge($statements, $this->parseUseStatement()); continue; } if ($token[0] !== T_NAMESPACE || $this->parseNamespace() != $namespaceName) { continue; } // Get fresh array for new namespace. This is to prevent the parser to collect the use statements // for a previous namespace with the same name. This is the case if a namespace is defined twice // or if a namespace with the same name is commented out. $statements = array(); } return $statements; } /** * Gets the namespace. * * @return string The found namespace. */ public function parseNamespace() { $name = ''; while (($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) { $name .= $token[1]; } return $name; } /** * Gets the class name. * * @return string The found class name. */ public function parseClass() { // Namespaces and class names are tokenized the same: T_STRINGs // separated by T_NS_SEPARATOR so we can use one function to provide // both. return $this->parseNamespace(); } } . */ namespace Doctrine\Common\Annotations; /** * AnnotationRegistry. */ final class AnnotationRegistry { /** * A map of namespaces to use for autoloading purposes based on a PSR-0 convention. * * Contains the namespace as key and an array of directories as value. If the value is NULL * the include path is used for checking for the corresponding file. * * This autoloading mechanism does not utilize the PHP autoloading but implements autoloading on its own. * * @var array */ static private $autoloadNamespaces = array(); /** * A map of autoloader callables. * * @var array */ static private $loaders = array(); /** * @return void */ static public function reset() { self::$autoloadNamespaces = array(); self::$loaders = array(); } /** * Registers file. * * @param string $file * * @return void */ static public function registerFile($file) { require_once $file; } /** * Adds a namespace with one or many directories to look for files or null for the include path. * * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. * * @param string $namespace * @param string|array|null $dirs * * @return void */ static public function registerAutoloadNamespace($namespace, $dirs = null) { self::$autoloadNamespaces[$namespace] = $dirs; } /** * Registers multiple namespaces. * * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. * * @param array $namespaces * * @return void */ static public function registerAutoloadNamespaces(array $namespaces) { self::$autoloadNamespaces = array_merge(self::$autoloadNamespaces, $namespaces); } /** * Registers an autoloading callable for annotations, much like spl_autoload_register(). * * NOTE: These class loaders HAVE to be silent when a class was not found! * IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class. * * @param callable $callable * * @return void * * @throws \InvalidArgumentException */ static public function registerLoader($callable) { if (!is_callable($callable)) { throw new \InvalidArgumentException("A callable is expected in AnnotationRegistry::registerLoader()."); } self::$loaders[] = $callable; } /** * Autoloads an annotation class silently. * * @param string $class * * @return boolean */ static public function loadAnnotationClass($class) { foreach (self::$autoloadNamespaces AS $namespace => $dirs) { if (strpos($class, $namespace) === 0) { $file = str_replace("\\", DIRECTORY_SEPARATOR, $class) . ".php"; if ($dirs === null) { if ($path = stream_resolve_include_path($file)) { require $path; return true; } } else { foreach((array)$dirs AS $dir) { if (is_file($dir . DIRECTORY_SEPARATOR . $file)) { require $dir . DIRECTORY_SEPARATOR . $file; return true; } } } } } foreach (self::$loaders AS $loader) { if (call_user_func($loader, $class) === true) { return true; } } return false; } } . */ namespace Doctrine\Common\Annotations; /** * File cache reader for annotations. * * @author Johannes M. Schmitt * @author Benjamin Eberlei * * @deprecated the FileCacheReader is deprecated and will be removed * in version 2.0.0 of doctrine/annotations. Please use the * {@see \Doctrine\Common\Annotations\CachedReader} instead. */ class FileCacheReader implements Reader { /** * @var Reader */ private $reader; /** * @var string */ private $dir; /** * @var bool */ private $debug; /** * @var array */ private $loadedAnnotations = array(); /** * @var array */ private $classNameHashes = array(); /** * @var int */ private $umask; /** * Constructor. * * @param Reader $reader * @param string $cacheDir * @param boolean $debug * * @throws \InvalidArgumentException */ public function __construct(Reader $reader, $cacheDir, $debug = false, $umask = 0002) { if ( ! is_int($umask)) { throw new \InvalidArgumentException(sprintf( 'The parameter umask must be an integer, was: %s', gettype($umask) )); } $this->reader = $reader; $this->umask = $umask; if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777 & (~$this->umask), true)) { throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $cacheDir)); } $this->dir = rtrim($cacheDir, '\\/'); $this->debug = $debug; } /** * {@inheritDoc} */ public function getClassAnnotations(\ReflectionClass $class) { if ( ! isset($this->classNameHashes[$class->name])) { $this->classNameHashes[$class->name] = sha1($class->name); } $key = $this->classNameHashes[$class->name]; if (isset($this->loadedAnnotations[$key])) { return $this->loadedAnnotations[$key]; } $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; if (!is_file($path)) { $annot = $this->reader->getClassAnnotations($class); $this->saveCacheFile($path, $annot); return $this->loadedAnnotations[$key] = $annot; } if ($this->debug && (false !== $filename = $class->getFilename()) && filemtime($path) < filemtime($filename)) { @unlink($path); $annot = $this->reader->getClassAnnotations($class); $this->saveCacheFile($path, $annot); return $this->loadedAnnotations[$key] = $annot; } return $this->loadedAnnotations[$key] = include $path; } /** * {@inheritDoc} */ public function getPropertyAnnotations(\ReflectionProperty $property) { $class = $property->getDeclaringClass(); if ( ! isset($this->classNameHashes[$class->name])) { $this->classNameHashes[$class->name] = sha1($class->name); } $key = $this->classNameHashes[$class->name].'$'.$property->getName(); if (isset($this->loadedAnnotations[$key])) { return $this->loadedAnnotations[$key]; } $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; if (!is_file($path)) { $annot = $this->reader->getPropertyAnnotations($property); $this->saveCacheFile($path, $annot); return $this->loadedAnnotations[$key] = $annot; } if ($this->debug && (false !== $filename = $class->getFilename()) && filemtime($path) < filemtime($filename)) { @unlink($path); $annot = $this->reader->getPropertyAnnotations($property); $this->saveCacheFile($path, $annot); return $this->loadedAnnotations[$key] = $annot; } return $this->loadedAnnotations[$key] = include $path; } /** * {@inheritDoc} */ public function getMethodAnnotations(\ReflectionMethod $method) { $class = $method->getDeclaringClass(); if ( ! isset($this->classNameHashes[$class->name])) { $this->classNameHashes[$class->name] = sha1($class->name); } $key = $this->classNameHashes[$class->name].'#'.$method->getName(); if (isset($this->loadedAnnotations[$key])) { return $this->loadedAnnotations[$key]; } $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; if (!is_file($path)) { $annot = $this->reader->getMethodAnnotations($method); $this->saveCacheFile($path, $annot); return $this->loadedAnnotations[$key] = $annot; } if ($this->debug && (false !== $filename = $class->getFilename()) && filemtime($path) < filemtime($filename)) { @unlink($path); $annot = $this->reader->getMethodAnnotations($method); $this->saveCacheFile($path, $annot); return $this->loadedAnnotations[$key] = $annot; } return $this->loadedAnnotations[$key] = include $path; } /** * Saves the cache file. * * @param string $path * @param mixed $data * * @return void */ private function saveCacheFile($path, $data) { if (!is_writable($this->dir)) { throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable. Both, the webserver and the console user need access. You can manage access rights for multiple users with "chmod +a". If your system does not support this, check out the acl package.', $this->dir)); } $tempfile = tempnam($this->dir, uniqid('', true)); if (false === $tempfile) { throw new \RuntimeException(sprintf('Unable to create tempfile in directory: %s', $this->dir)); } $written = file_put_contents($tempfile, 'umask)); if (false === rename($tempfile, $path)) { @unlink($tempfile); throw new \RuntimeException(sprintf('Unable to rename %s to %s', $tempfile, $path)); } } /** * {@inheritDoc} */ public function getClassAnnotation(\ReflectionClass $class, $annotationName) { $annotations = $this->getClassAnnotations($class); foreach ($annotations as $annotation) { if ($annotation instanceof $annotationName) { return $annotation; } } return null; } /** * {@inheritDoc} */ public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) { $annotations = $this->getMethodAnnotations($method); foreach ($annotations as $annotation) { if ($annotation instanceof $annotationName) { return $annotation; } } return null; } /** * {@inheritDoc} */ public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) { $annotations = $this->getPropertyAnnotations($property); foreach ($annotations as $annotation) { if ($annotation instanceof $annotationName) { return $annotation; } } return null; } /** * Clears loaded annotations. * * @return void */ public function clearLoadedAnnotations() { $this->loadedAnnotations = array(); } } . */ namespace Doctrine\Common\Lexer; /** * Base class for writing simple lexers, i.e. for creating small DSLs. * * @since 2.0 * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel */ abstract class AbstractLexer { /** * Lexer original input string. * * @var string */ private $input; /** * Array of scanned tokens. * * Each token is an associative array containing three items: * - 'value' : the string value of the token in the input string * - 'type' : the type of the token (identifier, numeric, string, input * parameter, none) * - 'position' : the position of the token in the input string * * @var array */ private $tokens = array(); /** * Current lexer position in input string. * * @var integer */ private $position = 0; /** * Current peek of current lexer position. * * @var integer */ private $peek = 0; /** * The next token in the input. * * @var array */ public $lookahead; /** * The last matched/seen token. * * @var array */ public $token; /** * Sets the input data to be tokenized. * * The Lexer is immediately reset and the new input tokenized. * Any unprocessed tokens from any previous input are lost. * * @param string $input The input to be tokenized. * * @return void */ public function setInput($input) { $this->input = $input; $this->tokens = array(); $this->reset(); $this->scan($input); } /** * Resets the lexer. * * @return void */ public function reset() { $this->lookahead = null; $this->token = null; $this->peek = 0; $this->position = 0; } /** * Resets the peek pointer to 0. * * @return void */ public function resetPeek() { $this->peek = 0; } /** * Resets the lexer position on the input to the given position. * * @param integer $position Position to place the lexical scanner. * * @return void */ public function resetPosition($position = 0) { $this->position = $position; } /** * Retrieve the original lexer's input until a given position. * * @param integer $position * * @return string */ public function getInputUntilPosition($position) { return substr($this->input, 0, $position); } /** * Checks whether a given token matches the current lookahead. * * @param integer|string $token * * @return boolean */ public function isNextToken($token) { return null !== $this->lookahead && $this->lookahead['type'] === $token; } /** * Checks whether any of the given tokens matches the current lookahead. * * @param array $tokens * * @return boolean */ public function isNextTokenAny(array $tokens) { return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true); } /** * Moves to the next token in the input string. * * @return boolean */ public function moveNext() { $this->peek = 0; $this->token = $this->lookahead; $this->lookahead = (isset($this->tokens[$this->position])) ? $this->tokens[$this->position++] : null; return $this->lookahead !== null; } /** * Tells the lexer to skip input tokens until it sees a token with the given value. * * @param string $type The token type to skip until. * * @return void */ public function skipUntil($type) { while ($this->lookahead !== null && $this->lookahead['type'] !== $type) { $this->moveNext(); } } /** * Checks if given value is identical to the given token. * * @param mixed $value * @param integer $token * * @return boolean */ public function isA($value, $token) { return $this->getType($value) === $token; } /** * Moves the lookahead token forward. * * @return array|null The next token or NULL if there are no more tokens ahead. */ public function peek() { if (isset($this->tokens[$this->position + $this->peek])) { return $this->tokens[$this->position + $this->peek++]; } else { return null; } } /** * Peeks at the next token, returns it and immediately resets the peek. * * @return array|null The next token or NULL if there are no more tokens ahead. */ public function glimpse() { $peek = $this->peek(); $this->peek = 0; return $peek; } /** * Scans the input string for tokens. * * @param string $input A query string. * * @return void */ protected function scan($input) { static $regex; if ( ! isset($regex)) { $regex = sprintf( '/(%s)|%s/%s', implode(')|(', $this->getCatchablePatterns()), implode('|', $this->getNonCatchablePatterns()), $this->getModifiers() ); } $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; $matches = preg_split($regex, $input, -1, $flags); foreach ($matches as $match) { // Must remain before 'value' assignment since it can change content $type = $this->getType($match[0]); $this->tokens[] = array( 'value' => $match[0], 'type' => $type, 'position' => $match[1], ); } } /** * Gets the literal for a given token. * * @param integer $token * * @return string */ public function getLiteral($token) { $className = get_class($this); $reflClass = new \ReflectionClass($className); $constants = $reflClass->getConstants(); foreach ($constants as $name => $value) { if ($value === $token) { return $className . '::' . $name; } } return $token; } /** * Regex modifiers * * @return string */ protected function getModifiers() { return 'i'; } /** * Lexical catchable patterns. * * @return array */ abstract protected function getCatchablePatterns(); /** * Lexical non-catchable patterns. * * @return array */ abstract protected function getNonCatchablePatterns(); /** * Retrieve token type. Also processes the token value if necessary. * * @param string $value * * @return integer */ abstract protected function getType(&$value); } DefinitionData = array(); # standardize line breaks $text = str_replace(array("\r\n", "\r"), "\n", $text); # remove surrounding line breaks $text = trim($text, "\n"); # split text into lines $lines = explode("\n", $text); # iterate through lines to identify blocks $markup = $this->lines($lines); # trim line breaks $markup = trim($markup, "\n"); return $markup; } # # Setters # function setBreaksEnabled($breaksEnabled) { $this->breaksEnabled = $breaksEnabled; return $this; } protected $breaksEnabled; function setMarkupEscaped($markupEscaped) { $this->markupEscaped = $markupEscaped; return $this; } protected $markupEscaped; function setUrlsLinked($urlsLinked) { $this->urlsLinked = $urlsLinked; return $this; } protected $urlsLinked = true; # # Lines # protected $BlockTypes = array( '#' => array('Header'), '*' => array('Rule', 'List'), '+' => array('List'), '-' => array('SetextHeader', 'Table', 'Rule', 'List'), '0' => array('List'), '1' => array('List'), '2' => array('List'), '3' => array('List'), '4' => array('List'), '5' => array('List'), '6' => array('List'), '7' => array('List'), '8' => array('List'), '9' => array('List'), ':' => array('Table'), '<' => array('Comment', 'Markup'), '=' => array('SetextHeader'), '>' => array('Quote'), '[' => array('Reference'), '_' => array('Rule'), '`' => array('FencedCode'), '|' => array('Table'), '~' => array('FencedCode'), ); # ~ protected $unmarkedBlockTypes = array( 'Code', ); # # Blocks # private function lines(array $lines) { $CurrentBlock = null; foreach ($lines as $line) { if (chop($line) === '') { if (isset($CurrentBlock)) { $CurrentBlock['interrupted'] = true; } continue; } if (strpos($line, "\t") !== false) { $parts = explode("\t", $line); $line = $parts[0]; unset($parts[0]); foreach ($parts as $part) { $shortage = 4 - mb_strlen($line, 'utf-8') % 4; $line .= str_repeat(' ', $shortage); $line .= $part; } } $indent = 0; while (isset($line[$indent]) and $line[$indent] === ' ') { $indent ++; } $text = $indent > 0 ? substr($line, $indent) : $line; # ~ $Line = array('body' => $line, 'indent' => $indent, 'text' => $text); # ~ if (isset($CurrentBlock['continuable'])) { $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock); if (isset($Block)) { $CurrentBlock = $Block; continue; } else { if (method_exists($this, 'block'.$CurrentBlock['type'].'Complete')) { $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock); } } } # ~ $marker = $text[0]; # ~ $blockTypes = $this->unmarkedBlockTypes; if (isset($this->BlockTypes[$marker])) { foreach ($this->BlockTypes[$marker] as $blockType) { $blockTypes []= $blockType; } } # # ~ foreach ($blockTypes as $blockType) { $Block = $this->{'block'.$blockType}($Line, $CurrentBlock); if (isset($Block)) { $Block['type'] = $blockType; if ( ! isset($Block['identified'])) { $Blocks []= $CurrentBlock; $Block['identified'] = true; } if (method_exists($this, 'block'.$blockType.'Continue')) { $Block['continuable'] = true; } $CurrentBlock = $Block; continue 2; } } # ~ if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted'])) { $CurrentBlock['element']['text'] .= "\n".$text; } else { $Blocks []= $CurrentBlock; $CurrentBlock = $this->paragraph($Line); $CurrentBlock['identified'] = true; } } # ~ if (isset($CurrentBlock['continuable']) and method_exists($this, 'block'.$CurrentBlock['type'].'Complete')) { $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock); } # ~ $Blocks []= $CurrentBlock; unset($Blocks[0]); # ~ $markup = ''; foreach ($Blocks as $Block) { if (isset($Block['hidden'])) { continue; } $markup .= "\n"; $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']); } $markup .= "\n"; # ~ return $markup; } # # Code protected function blockCode($Line, $Block = null) { if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted'])) { return; } if ($Line['indent'] >= 4) { $text = substr($Line['body'], 4); $Block = array( 'element' => array( 'name' => 'pre', 'handler' => 'element', 'text' => array( 'name' => 'code', 'text' => $text, ), ), ); return $Block; } } protected function blockCodeContinue($Line, $Block) { if ($Line['indent'] >= 4) { if (isset($Block['interrupted'])) { $Block['element']['text']['text'] .= "\n"; unset($Block['interrupted']); } $Block['element']['text']['text'] .= "\n"; $text = substr($Line['body'], 4); $Block['element']['text']['text'] .= $text; return $Block; } } protected function blockCodeComplete($Block) { $text = $Block['element']['text']['text']; $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); $Block['element']['text']['text'] = $text; return $Block; } # # Comment protected function blockComment($Line) { if ($this->markupEscaped) { return; } if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!') { $Block = array( 'markup' => $Line['body'], ); if (preg_match('/-->$/', $Line['text'])) { $Block['closed'] = true; } return $Block; } } protected function blockCommentContinue($Line, array $Block) { if (isset($Block['closed'])) { return; } $Block['markup'] .= "\n" . $Line['body']; if (preg_match('/-->$/', $Line['text'])) { $Block['closed'] = true; } return $Block; } # # Fenced Code protected function blockFencedCode($Line) { if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches)) { $Element = array( 'name' => 'code', 'text' => '', ); if (isset($matches[1])) { $class = 'language-'.$matches[1]; $Element['attributes'] = array( 'class' => $class, ); } $Block = array( 'char' => $Line['text'][0], 'element' => array( 'name' => 'pre', 'handler' => 'element', 'text' => $Element, ), ); return $Block; } } protected function blockFencedCodeContinue($Line, $Block) { if (isset($Block['complete'])) { return; } if (isset($Block['interrupted'])) { $Block['element']['text']['text'] .= "\n"; unset($Block['interrupted']); } if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text'])) { $Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1); $Block['complete'] = true; return $Block; } $Block['element']['text']['text'] .= "\n".$Line['body'];; return $Block; } protected function blockFencedCodeComplete($Block) { $text = $Block['element']['text']['text']; $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); $Block['element']['text']['text'] = $text; return $Block; } # # Header protected function blockHeader($Line) { if (isset($Line['text'][1])) { $level = 1; while (isset($Line['text'][$level]) and $Line['text'][$level] === '#') { $level ++; } if ($level > 6) { return; } $text = trim($Line['text'], '# '); $Block = array( 'element' => array( 'name' => 'h' . min(6, $level), 'text' => $text, 'handler' => 'line', ), ); return $Block; } } # # List protected function blockList($Line) { list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]'); if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches)) { $Block = array( 'indent' => $Line['indent'], 'pattern' => $pattern, 'element' => array( 'name' => $name, 'handler' => 'elements', ), ); $Block['li'] = array( 'name' => 'li', 'handler' => 'li', 'text' => array( $matches[2], ), ); $Block['element']['text'] []= & $Block['li']; return $Block; } } protected function blockListContinue($Line, array $Block) { if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches)) { if (isset($Block['interrupted'])) { $Block['li']['text'] []= ''; unset($Block['interrupted']); } unset($Block['li']); $text = isset($matches[1]) ? $matches[1] : ''; $Block['li'] = array( 'name' => 'li', 'handler' => 'li', 'text' => array( $text, ), ); $Block['element']['text'] []= & $Block['li']; return $Block; } if ($Line['text'][0] === '[' and $this->blockReference($Line)) { return $Block; } if ( ! isset($Block['interrupted'])) { $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']); $Block['li']['text'] []= $text; return $Block; } if ($Line['indent'] > 0) { $Block['li']['text'] []= ''; $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']); $Block['li']['text'] []= $text; unset($Block['interrupted']); return $Block; } } # # Quote protected function blockQuote($Line) { if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) { $Block = array( 'element' => array( 'name' => 'blockquote', 'handler' => 'lines', 'text' => (array) $matches[1], ), ); return $Block; } } protected function blockQuoteContinue($Line, array $Block) { if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) { if (isset($Block['interrupted'])) { $Block['element']['text'] []= ''; unset($Block['interrupted']); } $Block['element']['text'] []= $matches[1]; return $Block; } if ( ! isset($Block['interrupted'])) { $Block['element']['text'] []= $Line['text']; return $Block; } } # # Rule protected function blockRule($Line) { if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text'])) { $Block = array( 'element' => array( 'name' => 'hr' ), ); return $Block; } } # # Setext protected function blockSetextHeader($Line, array $Block = null) { if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) { return; } if (chop($Line['text'], $Line['text'][0]) === '') { $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; return $Block; } } # # Markup protected function blockMarkup($Line) { if ($this->markupEscaped) { return; } if (preg_match('/^<(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches)) { $element = strtolower($matches[1]); if (in_array($element, $this->textLevelElements)) { return; } $Block = array( 'name' => $matches[1], 'depth' => 0, 'markup' => $Line['text'], ); $length = strlen($matches[0]); $remainder = substr($Line['text'], $length); if (trim($remainder) === '') { if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) { $Block['closed'] = true; $Block['void'] = true; } } else { if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) { return; } if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder)) { $Block['closed'] = true; } } return $Block; } } protected function blockMarkupContinue($Line, array $Block) { if (isset($Block['closed'])) { return; } if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open { $Block['depth'] ++; } if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close { if ($Block['depth'] > 0) { $Block['depth'] --; } else { $Block['closed'] = true; } } if (isset($Block['interrupted'])) { $Block['markup'] .= "\n"; unset($Block['interrupted']); } $Block['markup'] .= "\n".$Line['body']; return $Block; } # # Reference protected function blockReference($Line) { if (preg_match('/^\[(.+?)\]:[ ]*?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) { $id = strtolower($matches[1]); $Data = array( 'url' => $matches[2], 'title' => null, ); if (isset($matches[3])) { $Data['title'] = $matches[3]; } $this->DefinitionData['Reference'][$id] = $Data; $Block = array( 'hidden' => true, ); return $Block; } } # # Table protected function blockTable($Line, array $Block = null) { if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) { return; } if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '') { $alignments = array(); $divider = $Line['text']; $divider = trim($divider); $divider = trim($divider, '|'); $dividerCells = explode('|', $divider); foreach ($dividerCells as $dividerCell) { $dividerCell = trim($dividerCell); if ($dividerCell === '') { continue; } $alignment = null; if ($dividerCell[0] === ':') { $alignment = 'left'; } if (substr($dividerCell, - 1) === ':') { $alignment = $alignment === 'left' ? 'center' : 'right'; } $alignments []= $alignment; } # ~ $HeaderElements = array(); $header = $Block['element']['text']; $header = trim($header); $header = trim($header, '|'); $headerCells = explode('|', $header); foreach ($headerCells as $index => $headerCell) { $headerCell = trim($headerCell); $HeaderElement = array( 'name' => 'th', 'text' => $headerCell, 'handler' => 'line', ); if (isset($alignments[$index])) { $alignment = $alignments[$index]; $HeaderElement['attributes'] = array( 'style' => 'text-align: '.$alignment.';', ); } $HeaderElements []= $HeaderElement; } # ~ $Block = array( 'alignments' => $alignments, 'identified' => true, 'element' => array( 'name' => 'table', 'handler' => 'elements', ), ); $Block['element']['text'] []= array( 'name' => 'thead', 'handler' => 'elements', ); $Block['element']['text'] []= array( 'name' => 'tbody', 'handler' => 'elements', 'text' => array(), ); $Block['element']['text'][0]['text'] []= array( 'name' => 'tr', 'handler' => 'elements', 'text' => $HeaderElements, ); return $Block; } } protected function blockTableContinue($Line, array $Block) { if (isset($Block['interrupted'])) { return; } if ($Line['text'][0] === '|' or strpos($Line['text'], '|')) { $Elements = array(); $row = $Line['text']; $row = trim($row); $row = trim($row, '|'); preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches); foreach ($matches[0] as $index => $cell) { $cell = trim($cell); $Element = array( 'name' => 'td', 'handler' => 'line', 'text' => $cell, ); if (isset($Block['alignments'][$index])) { $Element['attributes'] = array( 'style' => 'text-align: '.$Block['alignments'][$index].';', ); } $Elements []= $Element; } $Element = array( 'name' => 'tr', 'handler' => 'elements', 'text' => $Elements, ); $Block['element']['text'][1]['text'] []= $Element; return $Block; } } # # ~ # protected function paragraph($Line) { $Block = array( 'element' => array( 'name' => 'p', 'text' => $Line['text'], 'handler' => 'line', ), ); return $Block; } # # Inline Elements # protected $InlineTypes = array( '"' => array('SpecialCharacter'), '!' => array('Image'), '&' => array('SpecialCharacter'), '*' => array('Emphasis'), ':' => array('Url'), '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'), '>' => array('SpecialCharacter'), '[' => array('Link'), '_' => array('Emphasis'), '`' => array('Code'), '~' => array('Strikethrough'), '\\' => array('EscapeSequence'), ); # ~ protected $inlineMarkerList = '!"*_&[:<>`~\\'; # # ~ # public function line($text) { $markup = ''; # $excerpt is based on the first occurrence of a marker while ($excerpt = strpbrk($text, $this->inlineMarkerList)) { $marker = $excerpt[0]; $markerPosition = strpos($text, $marker); $Excerpt = array('text' => $excerpt, 'context' => $text); foreach ($this->InlineTypes[$marker] as $inlineType) { $Inline = $this->{'inline'.$inlineType}($Excerpt); if ( ! isset($Inline)) { continue; } # makes sure that the inline belongs to "our" marker if (isset($Inline['position']) and $Inline['position'] > $markerPosition) { continue; } # sets a default inline position if ( ! isset($Inline['position'])) { $Inline['position'] = $markerPosition; } # the text that comes before the inline $unmarkedText = substr($text, 0, $Inline['position']); # compile the unmarked text $markup .= $this->unmarkedText($unmarkedText); # compile the inline $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']); # remove the examined text $text = substr($text, $Inline['position'] + $Inline['extent']); continue 2; } # the marker does not belong to an inline $unmarkedText = substr($text, 0, $markerPosition + 1); $markup .= $this->unmarkedText($unmarkedText); $text = substr($text, $markerPosition + 1); } $markup .= $this->unmarkedText($text); return $markup; } # # ~ # protected function inlineCode($Excerpt) { $marker = $Excerpt['text'][0]; if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(? strlen($matches[0]), 'element' => array( 'name' => 'code', 'text' => $text, ), ); } } protected function inlineEmailTag($Excerpt) { if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches)) { $url = $matches[1]; if ( ! isset($matches[2])) { $url = 'mailto:' . $url; } return array( 'extent' => strlen($matches[0]), 'element' => array( 'name' => 'a', 'text' => $matches[1], 'attributes' => array( 'href' => $url, ), ), ); } } protected function inlineEmphasis($Excerpt) { if ( ! isset($Excerpt['text'][1])) { return; } $marker = $Excerpt['text'][0]; if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) { $emphasis = 'strong'; } elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) { $emphasis = 'em'; } else { return; } return array( 'extent' => strlen($matches[0]), 'element' => array( 'name' => $emphasis, 'handler' => 'line', 'text' => $matches[1], ), ); } protected function inlineEscapeSequence($Excerpt) { if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) { return array( 'markup' => $Excerpt['text'][1], 'extent' => 2, ); } } protected function inlineImage($Excerpt) { if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') { return; } $Excerpt['text']= substr($Excerpt['text'], 1); $Link = $this->inlineLink($Excerpt); if ($Link === null) { return; } $Inline = array( 'extent' => $Link['extent'] + 1, 'element' => array( 'name' => 'img', 'attributes' => array( 'src' => $Link['element']['attributes']['href'], 'alt' => $Link['element']['text'], ), ), ); $Inline['element']['attributes'] += $Link['element']['attributes']; unset($Inline['element']['attributes']['href']); return $Inline; } protected function inlineLink($Excerpt) { $Element = array( 'name' => 'a', 'handler' => 'line', 'text' => null, 'attributes' => array( 'href' => null, 'title' => null, ), ); $extent = 0; $remainder = $Excerpt['text']; if (preg_match('/\[((?:[^][]|(?R))*)\]/', $remainder, $matches)) { $Element['text'] = $matches[1]; $extent += strlen($matches[0]); $remainder = substr($remainder, $extent); } else { return; } if (preg_match('/^[(]((?:[^ ()]|[(][^ )]+[)])+)(?:[ ]+("[^"]*"|\'[^\']*\'))?[)]/', $remainder, $matches)) { $Element['attributes']['href'] = $matches[1]; if (isset($matches[2])) { $Element['attributes']['title'] = substr($matches[2], 1, - 1); } $extent += strlen($matches[0]); } else { if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) { $definition = strlen($matches[1]) ? $matches[1] : $Element['text']; $definition = strtolower($definition); $extent += strlen($matches[0]); } else { $definition = strtolower($Element['text']); } if ( ! isset($this->DefinitionData['Reference'][$definition])) { return; } $Definition = $this->DefinitionData['Reference'][$definition]; $Element['attributes']['href'] = $Definition['url']; $Element['attributes']['title'] = $Definition['title']; } $Element['attributes']['href'] = str_replace(array('&', '<'), array('&', '<'), $Element['attributes']['href']); return array( 'extent' => $extent, 'element' => $Element, ); } protected function inlineMarkup($Excerpt) { if ($this->markupEscaped or strpos($Excerpt['text'], '>') === false) { return; } if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w*[ ]*>/s', $Excerpt['text'], $matches)) { return array( 'markup' => $matches[0], 'extent' => strlen($matches[0]), ); } if ($Excerpt['text'][1] === '!' and preg_match('/^/s', $Excerpt['text'], $matches)) { return array( 'markup' => $matches[0], 'extent' => strlen($matches[0]), ); } if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches)) { return array( 'markup' => $matches[0], 'extent' => strlen($matches[0]), ); } } protected function inlineSpecialCharacter($Excerpt) { if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text'])) { return array( 'markup' => '&', 'extent' => 1, ); } $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot'); if (isset($SpecialCharacter[$Excerpt['text'][0]])) { return array( 'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';', 'extent' => 1, ); } } protected function inlineStrikethrough($Excerpt) { if ( ! isset($Excerpt['text'][1])) { return; } if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches)) { return array( 'extent' => strlen($matches[0]), 'element' => array( 'name' => 'del', 'text' => $matches[1], 'handler' => 'line', ), ); } } protected function inlineUrl($Excerpt) { if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/') { return; } if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)) { $Inline = array( 'extent' => strlen($matches[0][0]), 'position' => $matches[0][1], 'element' => array( 'name' => 'a', 'text' => $matches[0][0], 'attributes' => array( 'href' => $matches[0][0], ), ), ); return $Inline; } } protected function inlineUrlTag($Excerpt) { if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches)) { $url = str_replace(array('&', '<'), array('&', '<'), $matches[1]); return array( 'extent' => strlen($matches[0]), 'element' => array( 'name' => 'a', 'text' => $url, 'attributes' => array( 'href' => $url, ), ), ); } } # ~ protected function unmarkedText($text) { if ($this->breaksEnabled) { $text = preg_replace('/[ ]*\n/', "
\n", $text); } else { $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "
\n", $text); $text = str_replace(" \n", "\n", $text); } return $text; } # # Handlers # protected function element(array $Element) { $markup = '<'.$Element['name']; if (isset($Element['attributes'])) { foreach ($Element['attributes'] as $name => $value) { if ($value === null) { continue; } $markup .= ' '.$name.'="'.$value.'"'; } } if (isset($Element['text'])) { $markup .= '>'; if (isset($Element['handler'])) { $markup .= $this->{$Element['handler']}($Element['text']); } else { $markup .= $Element['text']; } $markup .= ''; } else { $markup .= ' />'; } return $markup; } protected function elements(array $Elements) { $markup = ''; foreach ($Elements as $Element) { $markup .= "\n" . $this->element($Element); } $markup .= "\n"; return $markup; } # ~ protected function li($lines) { $markup = $this->lines($lines); $trimmedMarkup = trim($markup); if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '

') { $markup = $trimmedMarkup; $markup = substr($markup, 3); $position = strpos($markup, "

"); $markup = substr_replace($markup, '', $position, 4); } return $markup; } # # Deprecated Methods # function parse($text) { $markup = $this->text($text); return $markup; } # # Static Methods # static function instance($name = 'default') { if (isset(self::$instances[$name])) { return self::$instances[$name]; } $instance = new static(); self::$instances[$name] = $instance; return $instance; } private static $instances = array(); # # Fields # protected $DefinitionData; # # Read-Only protected $specialCharacters = array( '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|', ); protected $StrongRegex = array( '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s', '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us', ); protected $EmRegex = array( '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us', ); protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?'; protected $voidElements = array( 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', ); protected $textLevelElements = array( 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont', 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing', 'i', 'rp', 'del', 'code', 'strike', 'marquee', 'q', 'rt', 'ins', 'font', 'strong', 's', 'tt', 'sub', 'mark', 'u', 'xm', 'sup', 'nobr', 'var', 'ruby', 'wbr', 'span', 'time', ); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata; /** * Base class for method metadata. * * This class is intended to be extended to add your application specific * properties, and flags. * * @author Johannes M. Schmitt */ class MethodMetadata implements \Serializable { public $class; public $name; public $reflection; public function __construct($class, $name) { $this->class = $class; $this->name = $name; $this->reflection = new \ReflectionMethod($class, $name); $this->reflection->setAccessible(true); } /** * @param object $obj * @param array $args * * @return mixed */ public function invoke($obj, array $args = array()) { return $this->reflection->invokeArgs($obj, $args); } public function serialize() { return serialize(array($this->class, $this->name)); } public function unserialize($str) { list($this->class, $this->name) = unserialize($str); $this->reflection = new \ReflectionMethod($this->class, $this->name); $this->reflection->setAccessible(true); } } */ class NullMetadata extends ClassMetadata { } name = $object->name; $this->reflection = $object->reflection; $this->methodMetadata = array_merge($this->methodMetadata, $object->methodMetadata); $this->propertyMetadata = array_merge($this->propertyMetadata, $object->propertyMetadata); $this->fileResources = array_merge($this->fileResources, $object->fileResources); if ($object->createdAt < $this->createdAt) { $this->createdAt = $object->createdAt; } } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata; final class Version { const VERSION = '1.4-DEV'; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata; /** * Represents the metadata for the entire class hierarchy. * * @author Johannes M. Schmitt */ class ClassHierarchyMetadata { public $classMetadata = array(); public function addClassMetadata(ClassMetadata $metadata) { $this->classMetadata[$metadata->name] = $metadata; } public function getRootClassMetadata() { return reset($this->classMetadata); } public function getOutsideClassMetadata() { return end($this->classMetadata); } public function isFresh($timestamp) { foreach ($this->classMetadata as $metadata) { if (!$metadata->isFresh($timestamp)) { return false; } } return true; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata; /** * Base class for class metadata. * * This class is intended to be extended to add your own application specific * properties, and flags. * * @author Johannes M. Schmitt */ class ClassMetadata implements \Serializable { public $name; public $reflection; public $methodMetadata = array(); public $propertyMetadata = array(); public $fileResources = array(); public $createdAt; public function __construct($name) { $this->name = $name; $this->reflection = new \ReflectionClass($name); $this->createdAt = time(); } public function addMethodMetadata(MethodMetadata $metadata) { $this->methodMetadata[$metadata->name] = $metadata; } public function addPropertyMetadata(PropertyMetadata $metadata) { $this->propertyMetadata[$metadata->name] = $metadata; } public function isFresh($timestamp = null) { if (null === $timestamp) { $timestamp = $this->createdAt; } foreach ($this->fileResources as $filepath) { if (!file_exists($filepath)) { return false; } if ($timestamp < filemtime($filepath)) { return false; } } return true; } public function serialize() { return serialize(array( $this->name, $this->methodMetadata, $this->propertyMetadata, $this->fileResources, $this->createdAt, )); } public function unserialize($str) { list( $this->name, $this->methodMetadata, $this->propertyMetadata, $this->fileResources, $this->createdAt ) = unserialize($str); $this->reflection = new \ReflectionClass($this->name); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata; /** * Interface for Metadata Factory implementations. * * @author Johannes M. Schmitt */ interface MetadataFactoryInterface { /** * Returns the gathered metadata for the given class name. * * If the drivers return instances of MergeableClassMetadata, these will be * merged prior to returning. Otherwise, all metadata for the inheritance * hierarchy will be returned as ClassHierarchyMetadata unmerged. * * If no metadata is available, null is returned. * * @param string $className * * @return ClassHierarchyMetadata|MergeableClassMetadata|null */ public function getMetadataForClass($className); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata; use Metadata\Driver\AdvancedDriverInterface; use Metadata\Driver\DriverInterface; use Metadata\Cache\CacheInterface; class MetadataFactory implements AdvancedMetadataFactoryInterface { private $driver; private $cache; private $loadedMetadata = array(); private $loadedClassMetadata = array(); private $hierarchyMetadataClass; private $includeInterfaces = false; private $debug; /** * @param DriverInterface $driver * @param string $hierarchyMetadataClass * @param boolean $debug */ public function __construct(DriverInterface $driver, $hierarchyMetadataClass = 'Metadata\ClassHierarchyMetadata', $debug = false) { $this->driver = $driver; $this->hierarchyMetadataClass = $hierarchyMetadataClass; $this->debug = (Boolean) $debug; } /** * @param boolean $include */ public function setIncludeInterfaces($include) { $this->includeInterfaces = (Boolean) $include; } public function setCache(CacheInterface $cache) { $this->cache = $cache; } /** * @param string $className * * @return ClassHierarchyMetadata|MergeableClassMetadata|null */ public function getMetadataForClass($className) { if (isset($this->loadedMetadata[$className])) { return $this->filterNullMetadata($this->loadedMetadata[$className]); } $metadata = null; foreach ($this->getClassHierarchy($className) as $class) { if (isset($this->loadedClassMetadata[$name = $class->getName()])) { if (null !== $classMetadata = $this->filterNullMetadata($this->loadedClassMetadata[$name])) { $this->addClassMetadata($metadata, $classMetadata); } continue; } // check the cache if (null !== $this->cache) { if (($classMetadata = $this->cache->loadClassMetadataFromCache($class)) instanceof NullMetadata) { $this->loadedClassMetadata[$name] = $classMetadata; continue; } if (null !== $classMetadata) { if ( ! $classMetadata instanceof ClassMetadata) { throw new \LogicException(sprintf('The cache must return instances of ClassMetadata, but got %s.', var_export($classMetadata, true))); } if ($this->debug && !$classMetadata->isFresh()) { $this->cache->evictClassMetadataFromCache($classMetadata->reflection); } else { $this->loadedClassMetadata[$name] = $classMetadata; $this->addClassMetadata($metadata, $classMetadata); continue; } } } // load from source if (null !== $classMetadata = $this->driver->loadMetadataForClass($class)) { $this->loadedClassMetadata[$name] = $classMetadata; $this->addClassMetadata($metadata, $classMetadata); if (null !== $this->cache) { $this->cache->putClassMetadataInCache($classMetadata); } continue; } if (null !== $this->cache && !$this->debug) { $this->cache->putClassMetadataInCache(new NullMetadata($class->getName())); } } if (null === $metadata) { $metadata = new NullMetadata($className); } return $this->filterNullMetadata($this->loadedMetadata[$className] = $metadata); } /** * {@inheritDoc} */ public function getAllClassNames() { if (!$this->driver instanceof AdvancedDriverInterface) { throw new \RuntimeException( sprintf('Driver "%s" must be an instance of "AdvancedDriverInterface".', get_class($this->driver)) ); } return $this->driver->getAllClassNames(); } /** * @param ClassMetadata|null $metadata * @param ClassMetadata $toAdd */ private function addClassMetadata(&$metadata, $toAdd) { if ($toAdd instanceof MergeableInterface) { if (null === $metadata) { $metadata = clone $toAdd; } else { $metadata->merge($toAdd); } } else { if (null === $metadata) { $metadata = new $this->hierarchyMetadataClass; } $metadata->addClassMetadata($toAdd); } } /** * @param string $class */ private function getClassHierarchy($class) { $classes = array(); $refl = new \ReflectionClass($class); do { $classes[] = $refl; $refl = $refl->getParentClass(); } while (false !== $refl); $classes = array_reverse($classes, false); if (!$this->includeInterfaces) { return $classes; } $addedInterfaces = array(); $newHierarchy = array(); foreach ($classes as $class) { foreach ($class->getInterfaces() as $interface) { if (isset($addedInterfaces[$interface->getName()])) { continue; } $addedInterfaces[$interface->getName()] = true; $newHierarchy[] = $interface; } $newHierarchy[] = $class; } return $newHierarchy; } /** * @param NullMetadata|null $metadata * * @return ClassMetadata|null */ private function filterNullMetadata($metadata = null) { return !$metadata instanceof NullMetadata ? $metadata : null; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata; /** * Base class for property metadata. * * This class is intended to be extended to add your application specific * properties, and flags. * * @author Johannes M. Schmitt */ class PropertyMetadata implements \Serializable { public $class; public $name; public $reflection; public function __construct($class, $name) { $this->class = $class; $this->name = $name; $this->reflection = new \ReflectionProperty($class, $name); $this->reflection->setAccessible(true); } /** * @param object $obj * * @return mixed */ public function getValue($obj) { return $this->reflection->getValue($obj); } /** * @param object $obj * @param string $value */ public function setValue($obj, $value) { $this->reflection->setValue($obj, $value); } public function serialize() { return serialize(array( $this->class, $this->name, )); } public function unserialize($str) { list($this->class, $this->name) = unserialize($str); $this->reflection = new \ReflectionProperty($this->class, $this->name); $this->reflection->setAccessible(true); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata; /** * Interface for advanced Metadata Factory implementations. * * @author Johannes M. Schmitt * @author Jordan Stout */ interface AdvancedMetadataFactoryInterface extends MetadataFactoryInterface { /** * Gets all the possible classes. * * @throws \RuntimeException if driver does not an advanced driver. * @return array */ public function getAllClassNames(); } container = $container; $this->realDriverId = $realDriverId; } /** * {@inheritDoc} */ public function loadMetadataForClass(\ReflectionClass $class) { return $this->container->get($this->realDriverId)->loadMetadataForClass($class); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata\Driver; final class DriverChain implements AdvancedDriverInterface { private $drivers; public function __construct(array $drivers = array()) { $this->drivers = $drivers; } public function addDriver(DriverInterface $driver) { $this->drivers[] = $driver; } public function loadMetadataForClass(\ReflectionClass $class) { foreach ($this->drivers as $driver) { if (null !== $metadata = $driver->loadMetadataForClass($class)) { return $metadata; } } return null; } /** * {@inheritDoc} */ public function getAllClassNames() { $classes = array(); foreach ($this->drivers as $driver) { if (!$driver instanceof AdvancedDriverInterface) { throw new \RuntimeException( sprintf( 'Driver "%s" must be an instance of "AdvancedDriverInterface" to use '. '"DriverChain::getAllClassNames()".', get_class($driver) ) ); } $driverClasses = $driver->getAllClassNames(); if (!empty($driverClasses)) { $classes = array_merge($classes, $driverClasses); } } return $classes; } } dirs = $dirs; } public function getDirs() { return $this->dirs; } /** * @param \ReflectionClass $class * @param string $extension * * @return string|null */ public function findFileForClass(\ReflectionClass $class, $extension) { foreach ($this->dirs as $prefix => $dir) { if ('' !== $prefix && 0 !== strpos($class->getNamespaceName(), $prefix)) { continue; } $len = '' === $prefix ? 0 : strlen($prefix) + 1; $path = $dir.'/'.str_replace('\\', '.', substr($class->name, $len)).'.'.$extension; if (file_exists($path)) { return $path; } } return null; } /** * {@inheritDoc} */ public function findAllClasses($extension) { $classes = array(); foreach ($this->dirs as $prefix => $dir) { /** @var $iterator \RecursiveIteratorIterator|\SplFileInfo[] */ $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY ); $nsPrefix = $prefix !== '' ? $prefix.'\\' : ''; foreach ($iterator as $file) { if (($fileName = $file->getBasename('.'.$extension)) == $file->getBasename()) { continue; } $classes[] = $nsPrefix.str_replace('.', '\\', $fileName); } } return $classes; } } */ abstract class AbstractFileDriver implements AdvancedDriverInterface { /** * @var FileLocatorInterface|FileLocator */ private $locator; public function __construct(FileLocatorInterface $locator) { $this->locator = $locator; } public function loadMetadataForClass(\ReflectionClass $class) { if (null === $path = $this->locator->findFileForClass($class, $this->getExtension())) { return null; } return $this->loadMetadataFromFile($class, $path); } /** * {@inheritDoc} */ public function getAllClassNames() { if (!$this->locator instanceof AdvancedFileLocatorInterface) { throw new \RuntimeException('Locator "%s" must be an instance of "AdvancedFileLocatorInterface".'); } return $this->locator->findAllClasses($this->getExtension()); } /** * Parses the content of the file, and converts it to the desired metadata. * * @param \ReflectionClass $class * @param string $file * * @return \Metadata\ClassMetadata|null */ abstract protected function loadMetadataFromFile(\ReflectionClass $class, $file); /** * Returns the extension of the file. * * @return string */ abstract protected function getExtension(); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata\Driver; /** * Forces advanced logic on a file locator. * * @author Jordan Stout */ interface AdvancedFileLocatorInterface extends FileLocatorInterface { /** * Finds all possible metadata files. * * @param string $extension * * @return array */ public function findAllClasses($extension); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata\Driver; /** * Forces advanced logic to drivers. * * @author Jordan Stout */ interface AdvancedDriverInterface extends DriverInterface { /** * Gets all the metadata class names known to this driver. * * @return array */ public function getAllClassNames(); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Metadata\Driver; interface DriverInterface { /** * @param \ReflectionClass $class * * @return \Metadata\ClassMetadata */ public function loadMetadataForClass(\ReflectionClass $class); } dir = rtrim($dir, '\\/'); } /** * {@inheritDoc} */ public function loadClassMetadataFromCache(\ReflectionClass $class) { $path = $this->dir.'/'.strtr($class->name, '\\', '-').'.cache.php'; if (!file_exists($path)) { return null; } return include $path; } /** * {@inheritDoc} */ public function putClassMetadataInCache(ClassMetadata $metadata) { $path = $this->dir.'/'.strtr($metadata->name, '\\', '-').'.cache.php'; $tmpFile = tempnam($this->dir, 'metadata-cache'); file_put_contents($tmpFile, 'renameFile($tmpFile, $path); } /** * Renames a file with fallback for windows * * @param string $source * @param string $target */ private function renameFile($source, $target) { if (false === @rename($source, $target)) { if (defined('PHP_WINDOWS_VERSION_BUILD')) { if (false === copy($source, $target)) { throw new \RuntimeException(sprintf('(WIN) Could not write new cache file to %s.', $target)); } if (false === unlink($source)) { throw new \RuntimeException(sprintf('(WIN) Could not delete temp cache file to %s.', $source)); } } else { throw new \RuntimeException(sprintf('Could not write new cache file to %s.', $target)); } } } /** * {@inheritDoc} */ public function evictClassMetadataFromCache(\ReflectionClass $class) { $path = $this->dir.'/'.strtr($class->name, '\\', '-').'.cache.php'; if (file_exists($path)) { unlink($path); } } } */ class DoctrineCacheAdapter implements CacheInterface { /** * @param string $prefix */ private $prefix; /** * @var Cache $cache */ private $cache; /** * @param string $prefix * @param Cache $cache */ public function __construct($prefix, Cache $cache) { $this->prefix = $prefix; $this->cache = $cache; } /** * {@inheritDoc} */ public function loadClassMetadataFromCache(\ReflectionClass $class) { $cache = $this->cache->fetch($this->prefix . $class->name); return false === $cache ? null : $cache; } /** * {@inheritDoc} */ public function putClassMetadataInCache(ClassMetadata $metadata) { $this->cache->save($this->prefix . $metadata->name, $metadata); } /** * {@inheritDoc} */ public function evictClassMetadataFromCache(\ReflectionClass $class) { $this->cache->delete($this->prefix . $class->name); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Parser; /** * The simple lexer is a fully usable lexer that does not require sub-classing. * * @author Johannes M. Schmitt */ class SimpleLexer extends AbstractLexer { private $regex; private $callable; private $tokenNames; public function __construct($regex, array $tokenNames, $typeCallable) { $this->regex = $regex; $this->callable = $typeCallable; $this->tokenNames = $tokenNames; } public function getName($type) { if ( ! isset($this->tokenNames[$type])) { throw new \InvalidArgumentException(sprintf('There is no token with type %s.', json_encode($type))); } return $this->tokenNames[$type]; } protected function getRegex() { return $this->regex; } protected function determineTypeAndValue($value) { return call_user_func($this->callable, $value); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Parser; class SyntaxErrorException extends \RuntimeException { private $actualToken; private $context; public function setActualToken(array $actualToken) { $this->actualToken = $actualToken; } public function setContext($context) { $this->context = $context; } public function getActualToken() { return $this->actualToken; } public function getContext() { return $this->context; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Parser; /** * Abstract Lexer. * * @author Johannes M. Schmitt */ abstract class AbstractLexer { public $token; public $next; private $i; private $peek; private $tokens; /** * Returns the name of the given token. * * @param integer $type * * @return string */ public function getName($type) { $ref = new \ReflectionClass($this); foreach ($ref->getConstants() as $name => $value) { if ($value === $type) { return $name; } } throw new \InvalidArgumentException(sprintf('There is no token with value %s.', json_encode($type))); } public function setInput($str) { $tokens = preg_split($this->getRegex(), $str, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE); $this->tokens = array(); foreach ($tokens as $token) { list($token[2], $token[0]) = $this->determineTypeAndValue($token[0]); $this->tokens[] = $token; } $this->reset(); } public function reset() { $this->i = -1; $this->peek = 0; $this->token = $this->next = null; $this->moveNext(); } /** * Moves the pointer one token forward. * * @return boolean if we have not yet reached the end of the input */ public function moveNext() { $this->peek = 0; $this->token = $this->next; $this->next = isset($this->tokens[++$this->i]) ? $this->tokens[$this->i] : null; return null !== $this->next; } /** * Skips the token stream until a token of the given type. * * @param integer $type * * @return boolean true if a token of the passed type was found, false otherwise. */ public function skipUntil($type) { while ( ! $this->isNext($type) && $this->moveNext()); if ( ! $this->isNext($type)) { throw new \RuntimeException(sprintf('Could not find the token %s.', $this->getName($type))); } } /** * @param integer $type * * @return boolean */ public function isNext($type) { return null !== $this->next && $type === $this->next[2]; } /** * @param array $types * * @return boolean */ public function isNextAny(array $types) { if (null === $this->next) { return false; } foreach ($types as $type) { if ($type === $this->next[2]) { return true; } } return false; } /** * @return \PhpOption\Option<[string,integer,integer]> */ public function peek() { if ( ! isset($this->tokens[$this->i + (++$this->peek)])) { return \PhpOption\None::create(); } return new \PhpOption\Some($this->tokens[$this->i + $this->peek]); } /** * @return string */ abstract protected function getRegex(); /** * Determines the type of the given value. * * This method may also modify the passed value for example to cast them to * a different PHP type where necessary. * * @param string $value * * @return array a tupel of type and normalized value */ abstract protected function determineTypeAndValue($value); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Parser; /** * Base Parser which provides some useful parsing methods intended for sub-classing. * * @author Johannes M. Schmitt */ abstract class AbstractParser { protected $lexer; protected $context; public function __construct(AbstractLexer $lexer) { $this->lexer = $lexer; } /** * Parses the given input. * * @param string $str * @param string $context parsing context (allows to produce better error messages) * * @return mixed */ public function parse($str, $context = null) { $this->lexer->setInput($str); $this->context = $context; $rs = $this->parseInternal(); if (null !== $this->lexer->next) { $this->syntaxError('end of input'); } return $rs; } /** * @return mixed */ abstract protected function parseInternal(); /** * Matches a token, and returns its value. * * @param integer $type * * @return mixed the value of the matched token */ protected function match($type) { if ( ! $this->lexer->isNext($type)) { $this->syntaxError($this->lexer->getName($type)); } $this->lexer->moveNext(); return $this->lexer->token[0]; } /** * Matches any of the passed tokens, and returns the matched token's value. * * @param array $types * * @return mixed */ protected function matchAny(array $types) { if ( ! $this->lexer->isNextAny($types)) { $this->syntaxError('any of '.implode(' or ', array_map(array($this->lexer, 'getName'), $types))); } $this->lexer->moveNext(); return $this->lexer->token[0]; } /** * Raises a syntax error exception. * * @param string $expectedDesc A human understandable explanation what was expected * @param array $actualToken The token that was found. If not given, next token will be assumed. */ protected function syntaxError($expectedDesc, $actualToken = null) { if (null === $actualToken) { $actualToken = $this->lexer->next; } if (null === $actualToken) { $actualDesc = 'end of input'; } else if ($actualToken[1] === 0) { $actualDesc = sprintf('"%s" of type %s at beginning of input', $actualToken[0], $this->lexer->getName($actualToken[2])); } else { $actualDesc = sprintf('"%s" of type %s at position %d (0-based)', $actualToken[0], $this->lexer->getName($actualToken[2]), $actualToken[1]); } $ex = new SyntaxErrorException(sprintf('Expected %s, but got %s%s.', $expectedDesc, $actualDesc, $this->context ? ' '.$this->context : '')); if (null !== $actualToken) { $ex->setActualToken($actualToken); } if (null !== $this->context) { $ex->setContext($this->context); } throw $ex; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Metadata; class VirtualPropertyMetadata extends PropertyMetadata { public function __construct($class, $methodName) { if (0 === strpos($methodName, 'get')) { $fieldName = lcfirst(substr($methodName, 3)); } else { $fieldName = $methodName; } $this->class = $class; $this->name = $fieldName; $this->getter = $methodName; $this->readOnly = true; } public function setValue($obj, $value) { throw new \LogicException('VirtualPropertyMetadata is immutable.'); } public function setAccessor($type, $getter = null, $setter = null) { } public function serialize() { return serialize(array( $this->sinceVersion, $this->untilVersion, $this->groups, $this->serializedName, $this->type, $this->xmlCollection, $this->xmlCollectionInline, $this->xmlEntryName, $this->xmlKeyAttribute, $this->xmlAttribute, $this->xmlValue, $this->xmlKeyValuePairs, $this->getter, $this->setter, $this->inline, $this->readOnly, $this->class, $this->name )); } public function unserialize($str) { list( $this->sinceVersion, $this->untilVersion, $this->groups, $this->serializedName, $this->type, $this->xmlCollection, $this->xmlCollectionInline, $this->xmlEntryName, $this->xmlKeyAttribute, $this->xmlAttribute, $this->xmlValue, $this->xmlKeyValuePairs, $this->getter, $this->setter, $this->inline, $this->readOnly, $this->class, $this->name ) = unserialize($str); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Metadata; use JMS\Serializer\Exception\InvalidArgumentException; use Metadata\MergeableInterface; use Metadata\MethodMetadata; use Metadata\MergeableClassMetadata; use Metadata\PropertyMetadata as BasePropertyMetadata; /** * Class Metadata used to customize the serialization process. * * @author Johannes M. Schmitt */ class ClassMetadata extends MergeableClassMetadata { const ACCESSOR_ORDER_UNDEFINED = 'undefined'; const ACCESSOR_ORDER_ALPHABETICAL = 'alphabetical'; const ACCESSOR_ORDER_CUSTOM = 'custom'; /** @var \ReflectionMethod[] */ public $preSerializeMethods = array(); /** @var \ReflectionMethod[] */ public $postSerializeMethods = array(); /** @var \ReflectionMethod[] */ public $postDeserializeMethods = array(); public $xmlRootName; public $accessorOrder; public $customOrder; public $handlerCallbacks = array(); public $discriminatorDisabled = false; public $discriminatorBaseClass; public $discriminatorFieldName; public $discriminatorValue; public $discriminatorMap = array(); public function setDiscriminator($fieldName, array $map) { if (empty($fieldName)) { throw new \InvalidArgumentException('The $fieldName cannot be empty.'); } if (empty($map)) { throw new \InvalidArgumentException('The discriminator map cannot be empty.'); } $this->discriminatorBaseClass = $this->name; $this->discriminatorFieldName = $fieldName; $this->discriminatorMap = $map; } /** * Sets the order of properties in the class. * * @param string $order * @param array $customOrder * * @throws InvalidArgumentException When the accessor order is not valid * @throws InvalidArgumentException When the custom order is not valid */ public function setAccessorOrder($order, array $customOrder = array()) { if (!in_array($order, array(self::ACCESSOR_ORDER_UNDEFINED, self::ACCESSOR_ORDER_ALPHABETICAL, self::ACCESSOR_ORDER_CUSTOM), true)) { throw new InvalidArgumentException(sprintf('The accessor order "%s" is invalid.', $order)); } foreach ($customOrder as $name) { if (!is_string($name)) { throw new InvalidArgumentException(sprintf('$customOrder is expected to be a list of strings, but got element of value %s.', json_encode($name))); } } $this->accessorOrder = $order; $this->customOrder = array_flip($customOrder); $this->sortProperties(); } public function addPropertyMetadata(BasePropertyMetadata $metadata) { parent::addPropertyMetadata($metadata); $this->sortProperties(); } public function addPreSerializeMethod(MethodMetadata $method) { $this->preSerializeMethods[] = $method; } public function addPostSerializeMethod(MethodMetadata $method) { $this->postSerializeMethods[] = $method; } public function addPostDeserializeMethod(MethodMetadata $method) { $this->postDeserializeMethods[] = $method; } /** * @param integer $direction * @param string|integer $format * @param string $methodName */ public function addHandlerCallback($direction, $format, $methodName) { $this->handlerCallbacks[$direction][$format] = $methodName; } public function merge(MergeableInterface $object) { if ( ! $object instanceof ClassMetadata) { throw new InvalidArgumentException('$object must be an instance of ClassMetadata.'); } parent::merge($object); $this->preSerializeMethods = array_merge($this->preSerializeMethods, $object->preSerializeMethods); $this->postSerializeMethods = array_merge($this->postSerializeMethods, $object->postSerializeMethods); $this->postDeserializeMethods = array_merge($this->postDeserializeMethods, $object->postDeserializeMethods); $this->xmlRootName = $object->xmlRootName; // Handler methods are taken from the outer class completely. $this->handlerCallbacks = $object->handlerCallbacks; if ($object->accessorOrder) { $this->accessorOrder = $object->accessorOrder; $this->customOrder = $object->customOrder; } if ($object->discriminatorFieldName && $this->discriminatorFieldName) { throw new \LogicException(sprintf( 'The discriminator of class "%s" would overwrite the discriminator of the parent class "%s". Please define all possible sub-classes in the discriminator of %s.', $object->name, $this->discriminatorBaseClass, $this->discriminatorBaseClass )); } if ($this->discriminatorMap && ! $this->reflection->isAbstract()) { if (false == $typeValue = array_search($this->name, $this->discriminatorMap, true)) { throw new \LogicException(sprintf( 'The sub-class "%s" is not listed in the discriminator of the base class "%s".', $this->name, $this->discriminatorBaseClass )); } $this->discriminatorValue = $typeValue; if (isset($this->propertyMetadata[$this->discriminatorFieldName]) && ! $this->propertyMetadata[$this->discriminatorFieldName] instanceof StaticPropertyMetadata) { throw new \LogicException(sprintf( 'The discriminator field name "%s" of the base-class "%s" conflicts with a regular property of the sub-class "%s".', $this->discriminatorFieldName, $this->discriminatorBaseClass, $this->name )); } $discriminatorProperty = new StaticPropertyMetadata( $this->name, $this->discriminatorFieldName, $typeValue ); $discriminatorProperty->serializedName = $this->discriminatorFieldName; $this->propertyMetadata[$this->discriminatorFieldName] = $discriminatorProperty; } $this->sortProperties(); } public function serialize() { $this->sortProperties(); return serialize(array( $this->preSerializeMethods, $this->postSerializeMethods, $this->postDeserializeMethods, $this->xmlRootName, $this->accessorOrder, $this->customOrder, $this->handlerCallbacks, $this->discriminatorDisabled, $this->discriminatorBaseClass, $this->discriminatorFieldName, $this->discriminatorValue, $this->discriminatorMap, parent::serialize(), )); } public function unserialize($str) { list( $this->preSerializeMethods, $this->postSerializeMethods, $this->postDeserializeMethods, $this->xmlRootName, $this->accessorOrder, $this->customOrder, $this->handlerCallbacks, $this->discriminatorDisabled, $this->discriminatorBaseClass, $this->discriminatorFieldName, $this->discriminatorValue, $this->discriminatorMap, $parentStr ) = unserialize($str); parent::unserialize($parentStr); } private function sortProperties() { switch ($this->accessorOrder) { case self::ACCESSOR_ORDER_ALPHABETICAL: ksort($this->propertyMetadata); break; case self::ACCESSOR_ORDER_CUSTOM: $order = $this->customOrder; uksort($this->propertyMetadata, function($a, $b) use ($order) { $existsA = isset($order[$a]); $existsB = isset($order[$b]); if (!$existsA && !$existsB) { return 0; } if (!$existsA) { return 1; } if (!$existsB) { return -1; } return $order[$a] < $order[$b] ? -1 : 1; }); break; } } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Metadata; use JMS\Serializer\TypeParser; use Metadata\PropertyMetadata as BasePropertyMetadata; use JMS\Serializer\Exception\RuntimeException; class PropertyMetadata extends BasePropertyMetadata { const ACCESS_TYPE_PROPERTY = 'property'; const ACCESS_TYPE_PUBLIC_METHOD = 'public_method'; public $sinceVersion; public $untilVersion; public $groups; public $serializedName; public $type; public $xmlCollection = false; public $xmlCollectionInline = false; public $xmlEntryName; public $xmlKeyAttribute; public $xmlAttribute = false; public $xmlValue = false; public $xmlKeyValuePairs = false; public $getter; public $setter; public $inline = false; public $readOnly = false; public $xmlAttributeMap = false; private static $typeParser; public function setAccessor($type, $getter = null, $setter = null) { if (self::ACCESS_TYPE_PUBLIC_METHOD === $type) { $class = $this->reflection->getDeclaringClass(); if (empty($getter)) { if ($class->hasMethod('get'.$this->name) && $class->getMethod('get'.$this->name)->isPublic()) { $getter = 'get'.$this->name; } elseif ($class->hasMethod('is'.$this->name) && $class->getMethod('is'.$this->name)->isPublic()) { $getter = 'is'.$this->name; } else { throw new RuntimeException(sprintf('There is neither a public %s method, nor a public %s method in class %s. Please specify which public method should be used for retrieving the value of the property %s.', 'get'.ucfirst($this->name), 'is'.ucfirst($this->name), $this->class, $this->name)); } } if (empty($setter) && !$this->readOnly) { if ($class->hasMethod('set'.$this->name) && $class->getMethod('set'.$this->name)->isPublic()) { $setter = 'set'.$this->name; } else { throw new RuntimeException(sprintf('There is no public %s method in class %s. Please specify which public method should be used for setting the value of the property %s.', 'set'.ucfirst($this->name), $this->class, $this->name)); } } } $this->getter = $getter; $this->setter = $setter; } public function getValue($obj) { if (null === $this->getter) { return parent::getValue($obj); } return $obj->{$this->getter}(); } public function setType($type) { if (null === self::$typeParser) { self::$typeParser = new TypeParser(); } $this->type = self::$typeParser->parse($type); } public function serialize() { return serialize(array( $this->sinceVersion, $this->untilVersion, $this->groups, $this->serializedName, $this->type, $this->xmlCollection, $this->xmlCollectionInline, $this->xmlEntryName, $this->xmlKeyAttribute, $this->xmlAttribute, $this->xmlValue, $this->xmlKeyValuePairs, $this->getter, $this->setter, $this->inline, $this->readOnly, $this->xmlAttributeMap, parent::serialize(), )); } public function unserialize($str) { list( $this->sinceVersion, $this->untilVersion, $this->groups, $this->serializedName, $this->type, $this->xmlCollection, $this->xmlCollectionInline, $this->xmlEntryName, $this->xmlKeyAttribute, $this->xmlAttribute, $this->xmlValue, $this->xmlKeyValuePairs, $this->getter, $this->setter, $this->inline, $this->readOnly, $this->xmlAttributeMap, $parentStr ) = unserialize($str); parent::unserialize($parentStr); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Metadata\Driver; use JMS\Serializer\Annotation\Discriminator; use JMS\Serializer\GraphNavigator; use JMS\Serializer\Annotation\HandlerCallback; use JMS\Serializer\Annotation\AccessorOrder; use JMS\Serializer\Annotation\Accessor; use JMS\Serializer\Annotation\AccessType; use JMS\Serializer\Annotation\XmlMap; use JMS\Serializer\Annotation\XmlRoot; use JMS\Serializer\Annotation\XmlAttribute; use JMS\Serializer\Annotation\XmlList; use JMS\Serializer\Annotation\XmlValue; use JMS\Serializer\Annotation\XmlKeyValuePairs; use JMS\Serializer\Annotation\PostSerialize; use JMS\Serializer\Annotation\PostDeserialize; use JMS\Serializer\Annotation\PreSerialize; use JMS\Serializer\Annotation\VirtualProperty; use Metadata\MethodMetadata; use Doctrine\Common\Annotations\Reader; use JMS\Serializer\Annotation\Type; use JMS\Serializer\Annotation\Exclude; use JMS\Serializer\Annotation\Groups; use JMS\Serializer\Annotation\Expose; use JMS\Serializer\Annotation\SerializedName; use JMS\Serializer\Annotation\Until; use JMS\Serializer\Annotation\Since; use JMS\Serializer\Annotation\ExclusionPolicy; use JMS\Serializer\Annotation\Inline; use JMS\Serializer\Annotation\ReadOnly; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Metadata\VirtualPropertyMetadata; use JMS\Serializer\Exception\InvalidArgumentException; use JMS\Serializer\Annotation\XmlAttributeMap; use Metadata\Driver\DriverInterface; class AnnotationDriver implements DriverInterface { private $reader; public function __construct(Reader $reader) { $this->reader = $reader; } public function loadMetadataForClass(\ReflectionClass $class) { $classMetadata = new ClassMetadata($name = $class->name); $classMetadata->fileResources[] = $class->getFilename(); $propertiesMetadata = array(); $propertiesAnnotations = array(); $exclusionPolicy = 'NONE'; $excludeAll = false; $classAccessType = PropertyMetadata::ACCESS_TYPE_PROPERTY; foreach ($this->reader->getClassAnnotations($class) as $annot) { if ($annot instanceof ExclusionPolicy) { $exclusionPolicy = $annot->policy; } elseif ($annot instanceof XmlRoot) { $classMetadata->xmlRootName = $annot->name; } elseif ($annot instanceof Exclude) { $excludeAll = true; } elseif ($annot instanceof AccessType) { $classAccessType = $annot->type; } elseif ($annot instanceof AccessorOrder) { $classMetadata->setAccessorOrder($annot->order, $annot->custom); } elseif ($annot instanceof Discriminator) { if ($annot->disabled) { $classMetadata->discriminatorDisabled = true; } else { $classMetadata->setDiscriminator($annot->field, $annot->map); } } } foreach ($class->getMethods() as $method) { if ($method->class !== $name) { continue; } $methodAnnotations = $this->reader->getMethodAnnotations($method); foreach ($methodAnnotations as $annot) { if ($annot instanceof PreSerialize) { $classMetadata->addPreSerializeMethod(new MethodMetadata($name, $method->name)); continue 2; } elseif ($annot instanceof PostDeserialize) { $classMetadata->addPostDeserializeMethod(new MethodMetadata($name, $method->name)); continue 2; } elseif ($annot instanceof PostSerialize) { $classMetadata->addPostSerializeMethod(new MethodMetadata($name, $method->name)); continue 2; } elseif ($annot instanceof VirtualProperty) { $virtualPropertyMetadata = new VirtualPropertyMetadata($name, $method->name); $propertiesMetadata[] = $virtualPropertyMetadata; $propertiesAnnotations[] = $methodAnnotations; continue 2; } elseif ($annot instanceof HandlerCallback) { $classMetadata->addHandlerCallback(GraphNavigator::parseDirection($annot->direction), $annot->format, $method->name); continue 2; } } } if (!$excludeAll) { foreach ($class->getProperties() as $property) { if ($property->class !== $name) { continue; } $propertiesMetadata[] = new PropertyMetadata($name, $property->getName()); $propertiesAnnotations[] = $this->reader->getPropertyAnnotations($property); } foreach ($propertiesMetadata as $propertyKey => $propertyMetadata) { $isExclude = false; $isExpose = $propertyMetadata instanceof VirtualPropertyMetadata; $accessType = $classAccessType; $accessor = array(null, null); $propertyAnnotations = $propertiesAnnotations[$propertyKey]; foreach ($propertyAnnotations as $annot) { if ($annot instanceof Since) { $propertyMetadata->sinceVersion = $annot->version; } elseif ($annot instanceof Until) { $propertyMetadata->untilVersion = $annot->version; } elseif ($annot instanceof SerializedName) { $propertyMetadata->serializedName = $annot->name; } elseif ($annot instanceof Expose) { $isExpose = true; } elseif ($annot instanceof Exclude) { $isExclude = true; } elseif ($annot instanceof Type) { $propertyMetadata->setType($annot->name); } elseif ($annot instanceof XmlList) { $propertyMetadata->xmlCollection = true; $propertyMetadata->xmlCollectionInline = $annot->inline; $propertyMetadata->xmlEntryName = $annot->entry; } elseif ($annot instanceof XmlMap) { $propertyMetadata->xmlCollection = true; $propertyMetadata->xmlCollectionInline = $annot->inline; $propertyMetadata->xmlEntryName = $annot->entry; $propertyMetadata->xmlKeyAttribute = $annot->keyAttribute; } elseif ($annot instanceof XmlKeyValuePairs) { $propertyMetadata->xmlKeyValuePairs = true; } elseif ($annot instanceof XmlAttribute) { $propertyMetadata->xmlAttribute = true; } elseif ($annot instanceof XmlValue) { $propertyMetadata->xmlValue = true; } elseif ($annot instanceof AccessType) { $accessType = $annot->type; } elseif ($annot instanceof ReadOnly) { $propertyMetadata->readOnly = true; } elseif ($annot instanceof Accessor) { $accessor = array($annot->getter, $annot->setter); } elseif ($annot instanceof Groups) { $propertyMetadata->groups = $annot->groups; foreach ((array) $propertyMetadata->groups as $groupName) { if (false !== strpos($groupName, ',')) { throw new InvalidArgumentException(sprintf( 'Invalid group name "%s" on "%s", did you mean to create multiple groups?', implode(', ', $propertyMetadata->groups), $propertyMetadata->class.'->'.$propertyMetadata->name )); } } } elseif ($annot instanceof Inline) { $propertyMetadata->inline = true; } elseif ($annot instanceof XmlAttributeMap) { $propertyMetadata->xmlAttributeMap = true; } } $propertyMetadata->setAccessor($accessType, $accessor[0], $accessor[1]); if ((ExclusionPolicy::NONE === $exclusionPolicy && !$isExclude) || (ExclusionPolicy::ALL === $exclusionPolicy && $isExpose)) { $classMetadata->addPropertyMetadata($propertyMetadata); } } } return $classMetadata; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Metadata\Driver; use JMS\Serializer\GraphNavigator; use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\Exception\XmlErrorException; use JMS\Serializer\Annotation\ExclusionPolicy; use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Metadata\VirtualPropertyMetadata; use Metadata\MethodMetadata; use JMS\Serializer\Metadata\ClassMetadata; use Metadata\Driver\AbstractFileDriver; class XmlDriver extends AbstractFileDriver { protected function loadMetadataFromFile(\ReflectionClass $class, $path) { $previous = libxml_use_internal_errors(true); $elem = simplexml_load_file($path); libxml_use_internal_errors($previous); if (false === $elem) { throw new XmlErrorException(libxml_get_last_error()); } $metadata = new ClassMetadata($name = $class->name); if (!$elems = $elem->xpath("./class[@name = '".$name."']")) { throw new RuntimeException(sprintf('Could not find class %s inside XML element.', $name)); } $elem = reset($elems); $metadata->fileResources[] = $path; $metadata->fileResources[] = $class->getFileName(); $exclusionPolicy = strtoupper($elem->attributes()->{'exclusion-policy'}) ?: 'NONE'; $excludeAll = null !== ($exclude = $elem->attributes()->exclude) ? 'true' === strtolower($exclude) : false; $classAccessType = (string) ($elem->attributes()->{'access-type'} ?: PropertyMetadata::ACCESS_TYPE_PROPERTY); $propertiesMetadata = array(); $propertiesNodes = array(); if (null !== $accessorOrder = $elem->attributes()->{'accessor-order'}) { $metadata->setAccessorOrder((string) $accessorOrder, preg_split('/\s*,\s*/', (string) $elem->attributes()->{'custom-accessor-order'})); } if (null !== $xmlRootName = $elem->attributes()->{'xml-root-name'}) { $metadata->xmlRootName = (string) $xmlRootName; } $discriminatorFieldName = (string) $elem->attributes()->{'discriminator-field-name'}; $discriminatorMap = array(); foreach ($elem->xpath('./discriminator-class') as $entry) { if ( ! isset($entry->attributes()->value)) { throw new RuntimeException('Each discriminator-class element must have a "value" attribute.'); } $discriminatorMap[(string) $entry->attributes()->value] = (string) $entry; } if ('true' === (string) $elem->attributes()->{'discriminator-disabled'}) { $metadata->discriminatorDisabled = true; } elseif ( ! empty($discriminatorFieldName) || ! empty($discriminatorMap)) { $metadata->setDiscriminator($discriminatorFieldName, $discriminatorMap); } foreach ($elem->xpath('./virtual-property') as $method) { if (!isset($method->attributes()->method)) { throw new RuntimeException('The method attribute must be set for all virtual-property elements.'); } $virtualPropertyMetadata = new VirtualPropertyMetadata( $name, (string) $method->attributes()->method ); $propertiesMetadata[] = $virtualPropertyMetadata; $propertiesNodes[] = $method; } if (!$excludeAll) { foreach ($class->getProperties() as $property) { if ($name !== $property->class) { continue; } $propertiesMetadata[] = new PropertyMetadata($name, $pName = $property->getName()); $pElems = $elem->xpath("./property[@name = '".$pName."']"); $propertiesNodes[] = $pElems ? reset( $pElems ) : null; } foreach ($propertiesMetadata as $propertyKey => $pMetadata) { $isExclude = false; $isExpose = $pMetadata instanceof VirtualPropertyMetadata; $pElem = $propertiesNodes[$propertyKey]; if (!empty( $pElem )) { if (null !== $exclude = $pElem->attributes()->exclude) { $isExclude = 'true' === strtolower($exclude); } if (null !== $expose = $pElem->attributes()->expose) { $isExpose = 'true' === strtolower($expose); } if (null !== $version = $pElem->attributes()->{'since-version'}) { $pMetadata->sinceVersion = (string) $version; } if (null !== $version = $pElem->attributes()->{'until-version'}) { $pMetadata->untilVersion = (string) $version; } if (null !== $serializedName = $pElem->attributes()->{'serialized-name'}) { $pMetadata->serializedName = (string) $serializedName; } if (null !== $type = $pElem->attributes()->type) { $pMetadata->setType((string) $type); } elseif (isset($pElem->type)) { $pMetadata->setType((string) $pElem->type); } if (null !== $groups = $pElem->attributes()->groups) { $pMetadata->groups = preg_split('/\s*,\s*/', (string) $groups); } if (isset($pElem->{'xml-list'})) { $pMetadata->xmlCollection = true; $colConfig = $pElem->{'xml-list'}; if (isset($colConfig->attributes()->inline)) { $pMetadata->xmlCollectionInline = 'true' === (string) $colConfig->attributes()->inline; } if (isset($colConfig->attributes()->{'entry-name'})) { $pMetadata->xmlEntryName = (string) $colConfig->attributes()->{'entry-name'}; } } if (isset($pElem->{'xml-map'})) { $pMetadata->xmlCollection = true; $colConfig = $pElem->{'xml-map'}; if (isset($colConfig->attributes()->inline)) { $pMetadata->xmlCollectionInline = 'true' === (string) $colConfig->attributes()->inline; } if (isset($colConfig->attributes()->{'entry-name'})) { $pMetadata->xmlEntryName = (string) $colConfig->attributes()->{'entry-name'}; } if (isset($colConfig->attributes()->{'key-attribute-name'})) { $pMetadata->xmlKeyAttribute = (string) $colConfig->attributes()->{'key-attribute-name'}; } } if (isset($pElem->attributes()->{'xml-attribute'})) { $pMetadata->xmlAttribute = 'true' === (string) $pElem->attributes()->{'xml-attribute'}; } if (isset($pElem->attributes()->{'xml-attribute-map'})) { $pMetadata->xmlAttribute = 'true' === (string) $pElem->attributes()->{'xml-attribute-map'}; } if (isset($pElem->attributes()->{'xml-value'})) { $pMetadata->xmlValue = 'true' === (string) $pElem->attributes()->{'xml-value'}; } if (isset($pElem->attributes()->{'xml-key-value-pairs'})) { $pMetadata->xmlKeyValuePairs = 'true' === (string) $pElem->attributes()->{'xml-key-value-pairs'}; } //we need read-only before setter and getter set, because that method depends on flag being set if (null !== $readOnly = $pElem->attributes()->{'read-only'}) { $pMetadata->readOnly = 'true' === strtolower($readOnly); } $getter = $pElem->attributes()->{'accessor-getter'}; $setter = $pElem->attributes()->{'accessor-setter'}; $pMetadata->setAccessor( (string) ($pElem->attributes()->{'access-type'} ?: $classAccessType), $getter ? (string) $getter : null, $setter ? (string) $setter : null ); if (null !== $inline = $pElem->attributes()->inline) { $pMetadata->inline = 'true' === strtolower($inline); } } if ((ExclusionPolicy::NONE === (string)$exclusionPolicy && !$isExclude) || (ExclusionPolicy::ALL === (string)$exclusionPolicy && $isExpose)) { $metadata->addPropertyMetadata($pMetadata); } } } foreach ($elem->xpath('./callback-method') as $method) { if (!isset($method->attributes()->type)) { throw new RuntimeException('The type attribute must be set for all callback-method elements.'); } if (!isset($method->attributes()->name)) { throw new RuntimeException('The name attribute must be set for all callback-method elements.'); } switch ((string) $method->attributes()->type) { case 'pre-serialize': $metadata->addPreSerializeMethod(new MethodMetadata($name, (string) $method->attributes()->name)); break; case 'post-serialize': $metadata->addPostSerializeMethod(new MethodMetadata($name, (string) $method->attributes()->name)); break; case 'post-deserialize': $metadata->addPostDeserializeMethod(new MethodMetadata($name, (string) $method->attributes()->name)); break; case 'handler': if ( ! isset($method->attributes()->format)) { throw new RuntimeException('The format attribute must be set for "handler" callback methods.'); } if ( ! isset($method->attributes()->direction)) { throw new RuntimeException('The direction attribute must be set for "handler" callback methods.'); } $direction = GraphNavigator::parseDirection((string) $method->attributes()->direction); $format = (string) $method->attributes()->format; $metadata->addHandlerCallback($direction, $format, (string) $method->attributes()->name); break; default: throw new RuntimeException(sprintf('The type "%s" is not supported.', $method->attributes()->name)); } } return $metadata; } protected function getExtension() { return 'xml'; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Metadata\Driver; use Doctrine\Common\Persistence\ManagerRegistry; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; use Metadata\Driver\DriverInterface; use Doctrine\ORM\Mapping\ClassMetadataInfo; /** * This class decorates any other driver. If the inner driver does not provide a * a property type, the decorator will guess based on Doctrine 2 metadata. */ class DoctrineTypeDriver implements DriverInterface { /** * Map of doctrine 2 field types to JMS\Serializer types * @var array */ protected $fieldMapping = array( 'string' => 'string', 'text' => 'string', 'blob' => 'string', 'integer' => 'integer', 'smallint' => 'integer', 'bigint' => 'integer', 'datetime' => 'DateTime', 'datetimetz' => 'DateTime', 'time' => 'DateTime', 'float' => 'float', 'decimal' => 'float', 'boolean' => 'boolean', 'array' => 'array', 'json_array' => 'array', 'simple_array' => 'array', ); /** * @var DriverInterface */ protected $delegate; /** * @var ManagerRegistry */ protected $registry; public function __construct(DriverInterface $delegate, ManagerRegistry $registry) { $this->delegate = $delegate; $this->registry = $registry; } public function loadMetadataForClass(\ReflectionClass $class) { /** @var $classMetadata ClassMetadata */ $classMetadata = $this->delegate->loadMetadataForClass($class); // Abort if the given class is not a mapped entity if (!$doctrineMetadata = $this->tryLoadingDoctrineMetadata($class->name)) { return $classMetadata; } if ($doctrineMetadata instanceof ClassMetadataInfo) { if (empty($classMetadata->discriminatorMap) && ! $classMetadata->discriminatorDisabled && ! empty($doctrineMetadata->discriminatorMap) && $doctrineMetadata->isRootEntity()) { $classMetadata->setDiscriminator( $doctrineMetadata->discriminatorColumn['name'], $doctrineMetadata->discriminatorMap ); } } // We base our scan on the internal driver's property list so that we // respect any internal white/blacklisting like in the AnnotationDriver foreach ($classMetadata->propertyMetadata as $propertyMetadata) { /** @var $propertyMetadata PropertyMetadata */ // If the inner driver provides a type, don't guess anymore. if ($propertyMetadata->type) { continue; } $propertyName = $propertyMetadata->name; if ($doctrineMetadata->hasField($propertyName) && $fieldType = $this->normalizeFieldType($doctrineMetadata->getTypeOfField($propertyName))) { $propertyMetadata->setType($fieldType); } elseif ($doctrineMetadata->hasAssociation($propertyName)) { $targetEntity = $doctrineMetadata->getAssociationTargetClass($propertyName); if (null === $targetMetadata = $this->tryLoadingDoctrineMetadata($targetEntity)) { continue; } // For inheritance schemes, we cannot add any type as we would only add the super-type of the hierarchy. // On serialization, this would lead to only the supertype being serialized, and properties of subtypes // being ignored. if ($targetMetadata instanceof ClassMetadataInfo && ! $targetMetadata->isInheritanceTypeNone()) { continue; } if ($doctrineMetadata->isSingleValuedAssociation($propertyName)) { $propertyMetadata->setType($targetEntity); } else { $propertyMetadata->setType("ArrayCollection<{$targetEntity}>"); } } } return $classMetadata; } /** * @param string $className * * @return ClassMetadataInfo|null */ private function tryLoadingDoctrineMetadata($className) { if (!$manager = $this->registry->getManagerForClass($className)) { return null; } if ($manager->getMetadataFactory()->isTransient($className)) { return null; } return $manager->getClassMetadata($className); } private function normalizeFieldType($type) { if (!isset($this->fieldMapping[$type])) { return; } return $this->fieldMapping[$type]; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Metadata\Driver; use JMS\Serializer\GraphNavigator; use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\Annotation\ExclusionPolicy; use Metadata\MethodMetadata; use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Metadata\VirtualPropertyMetadata; use JMS\Serializer\Metadata\ClassMetadata; use Symfony\Component\Yaml\Yaml; use Metadata\Driver\AbstractFileDriver; class YamlDriver extends AbstractFileDriver { protected function loadMetadataFromFile(\ReflectionClass $class, $file) { $config = Yaml::parse(file_get_contents($file)); if (!isset($config[$name = $class->name])) { throw new RuntimeException(sprintf('Expected metadata for class %s to be defined in %s.', $class->name, $file)); } $config = $config[$name]; $metadata = new ClassMetadata($name); $metadata->fileResources[] = $file; $metadata->fileResources[] = $class->getFileName(); $exclusionPolicy = isset($config['exclusion_policy']) ? strtoupper($config['exclusion_policy']) : 'NONE'; $excludeAll = isset($config['exclude']) ? (Boolean) $config['exclude'] : false; $classAccessType = isset($config['access_type']) ? $config['access_type'] : PropertyMetadata::ACCESS_TYPE_PROPERTY; $propertiesMetadata = array(); if (isset($config['accessor_order'])) { $metadata->setAccessorOrder($config['accessor_order'], isset($config['custom_accessor_order']) ? $config['custom_accessor_order'] : array()); } if (isset($config['xml_root_name'])) { $metadata->xmlRootName = (string) $config['xml_root_name']; } if (isset($config['discriminator'])) { if (isset($config['discriminator']['disabled']) && true === $config['discriminator']['disabled']) { $metadata->discriminatorDisabled = true; } else { if ( ! isset($config['discriminator']['field_name'])) { throw new RuntimeException('The "field_name" attribute must be set for discriminators.'); } if ( ! isset($config['discriminator']['map']) || ! is_array($config['discriminator']['map'])) { throw new RuntimeException('The "map" attribute must be set, and be an array for discriminators.'); } $metadata->setDiscriminator($config['discriminator']['field_name'], $config['discriminator']['map']); } } if (array_key_exists('virtual_properties', $config) ) { foreach ( $config['virtual_properties'] as $methodName => $propertySettings ) { if ( !$class->hasMethod( $methodName ) ) { throw new RuntimeException('The method '.$methodName.' not found in class ' . $class->name); } $virtualPropertyMetadata = new VirtualPropertyMetadata( $name, $methodName ); $propertiesMetadata[$methodName] = $virtualPropertyMetadata; $config['properties'][$methodName] = $propertySettings; } } if (!$excludeAll) { foreach ($class->getProperties() as $property) { if ($name !== $property->class) { continue; } $pName = $property->getName(); $propertiesMetadata[$pName] = new PropertyMetadata($name, $pName); } foreach ($propertiesMetadata as $pName => $pMetadata) { $isExclude = false; $isExpose = $pMetadata instanceof VirtualPropertyMetadata; if (isset($config['properties'][$pName])) { $pConfig = $config['properties'][$pName]; if (isset($pConfig['exclude'])) { $isExclude = (Boolean) $pConfig['exclude']; } if (isset($pConfig['expose'])) { $isExpose = (Boolean) $pConfig['expose']; } if (isset($pConfig['since_version'])) { $pMetadata->sinceVersion = (string) $pConfig['since_version']; } if (isset($pConfig['until_version'])) { $pMetadata->untilVersion = (string) $pConfig['until_version']; } if (isset($pConfig['serialized_name'])) { $pMetadata->serializedName = (string) $pConfig['serialized_name']; } if (isset($pConfig['type'])) { $pMetadata->setType((string) $pConfig['type']); } if (isset($pConfig['groups'])) { $pMetadata->groups = $pConfig['groups']; } if (isset($pConfig['xml_list'])) { $pMetadata->xmlCollection = true; $colConfig = $pConfig['xml_list']; if (isset($colConfig['inline'])) { $pMetadata->xmlCollectionInline = (Boolean) $colConfig['inline']; } if (isset($colConfig['entry_name'])) { $pMetadata->xmlEntryName = (string) $colConfig['entry_name']; } } if (isset($pConfig['xml_map'])) { $pMetadata->xmlCollection = true; $colConfig = $pConfig['xml_map']; if (isset($colConfig['inline'])) { $pMetadata->xmlCollectionInline = (Boolean) $colConfig['inline']; } if (isset($colConfig['entry_name'])) { $pMetadata->xmlEntryName = (string) $colConfig['entry_name']; } if (isset($colConfig['key_attribute_name'])) { $pMetadata->xmlKeyAttribute = $colConfig['key_attribute_name']; } } if (isset($pConfig['xml_attribute'])) { $pMetadata->xmlAttribute = (Boolean) $pConfig['xml_attribute']; } if (isset($pConfig['xml_attribute_map'])) { $pMetadata->xmlAttribute = (Boolean) $pConfig['xml_attribute_map']; } if (isset($pConfig['xml_value'])) { $pMetadata->xmlValue = (Boolean) $pConfig['xml_value']; } if (isset($pConfig['xml_key_value_pairs'])) { $pMetadata->xmlKeyValuePairs = (Boolean) $pConfig['xml_key_value_pairs']; } //we need read_only before setter and getter set, because that method depends on flag being set if (isset($pConfig['read_only'])) { $pMetadata->readOnly = (Boolean) $pConfig['read_only']; } $pMetadata->setAccessor( isset($pConfig['access_type']) ? $pConfig['access_type'] : $classAccessType, isset($pConfig['accessor']['getter']) ? $pConfig['accessor']['getter'] : null, isset($pConfig['accessor']['setter']) ? $pConfig['accessor']['setter'] : null ); if (isset($pConfig['inline'])) { $pMetadata->inline = (Boolean) $pConfig['inline']; } } if ((ExclusionPolicy::NONE === $exclusionPolicy && !$isExclude) || (ExclusionPolicy::ALL === $exclusionPolicy && $isExpose)) { $metadata->addPropertyMetadata($pMetadata); } } } if (isset($config['handler_callbacks'])) { foreach ($config['handler_callbacks'] as $direction => $formats) { foreach ($formats as $format => $methodName) { $direction = GraphNavigator::parseDirection($direction); $metadata->addHandlerCallback($direction, $format, $methodName); } } } if (isset($config['callback_methods'])) { $cConfig = $config['callback_methods']; if (isset($cConfig['pre_serialize'])) { $metadata->preSerializeMethods = $this->getCallbackMetadata($class, $cConfig['pre_serialize']); } if (isset($cConfig['post_serialize'])) { $metadata->postSerializeMethods = $this->getCallbackMetadata($class, $cConfig['post_serialize']); } if (isset($cConfig['post_deserialize'])) { $metadata->postDeserializeMethods = $this->getCallbackMetadata($class, $cConfig['post_deserialize']); } } return $metadata; } protected function getExtension() { return 'yml'; } private function getCallbackMetadata(\ReflectionClass $class, $config) { if (is_string($config)) { $config = array($config); } elseif (!is_array($config)) { throw new RuntimeException(sprintf('callback methods expects a string, or an array of strings that represent method names, but got %s.', json_encode($config['pre_serialize']))); } $methods = array(); foreach ($config as $name) { if (!$class->hasMethod($name)) { throw new RuntimeException(sprintf('The method %s does not exist in class %s.', $name, $class->name)); } $methods[] = new MethodMetadata($class->name, $name); } return $methods; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Metadata\Driver; use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\Metadata\ClassMetadata; use Metadata\Driver\AbstractFileDriver; class PhpDriver extends AbstractFileDriver { protected function loadMetadataFromFile(\ReflectionClass $class, $file) { $metadata = require $file; if (!$metadata instanceof ClassMetadata) { throw new RuntimeException(sprintf('The file %s was expected to return an instance of ClassMetadata, but returned %s.', $file, json_encode($metadata))); } if ($metadata->name !== $class->name) { throw new RuntimeException(sprintf('The file %s was expected to return metadata for class %s, but instead returned metadata for class %s.', $class->name, $metadata->name)); } return $metadata; } protected function getExtension() { return 'php'; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Metadata; class StaticPropertyMetadata extends PropertyMetadata { private $value; public function __construct($className, $fieldName, $fieldValue) { $this->class = $className; $this->name = $fieldName; $this->value = $fieldValue; $this->readOnly = true; } public function getValue($obj) { return $this->value; } public function setValue($obj, $value) { throw new \LogicException('StaticPropertyMetadata is immutable.'); } public function setAccessor($type, $getter = null, $setter = null) { } public function serialize() { return serialize(array( $this->sinceVersion, $this->untilVersion, $this->groups, $this->serializedName, $this->type, $this->xmlCollection, $this->xmlCollectionInline, $this->xmlEntryName, $this->xmlKeyAttribute, $this->xmlAttribute, $this->xmlValue, $this->xmlKeyValuePairs, $this->getter, $this->setter, $this->inline, $this->readOnly, $this->class, $this->name, $this->value )); } public function unserialize($str) { list( $this->sinceVersion, $this->untilVersion, $this->groups, $this->serializedName, $this->type, $this->xmlCollection, $this->xmlCollectionInline, $this->xmlEntryName, $this->xmlKeyAttribute, $this->xmlAttribute, $this->xmlValue, $this->xmlKeyValuePairs, $this->getter, $this->setter, $this->inline, $this->readOnly, $this->class, $this->name, $this->value ) = unserialize($str); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Metadata\ClassMetadata; class JsonSerializationVisitor extends GenericSerializationVisitor { private $options = 0; public function getResult() { return json_encode($this->getRoot(), $this->options); } public function getOptions() { return $this->options; } public function setOptions($options) { $this->options = (integer) $options; } public function visitArray($data, array $type, Context $context) { $result = parent::visitArray($data, $type, $context); if (null !== $this->getRoot() && isset($type['params'][1]) && 0 === count($result)) { // ArrayObject is specially treated by the json_encode function and // serialized to { } while a mere array would be serialized to []. return new \ArrayObject(); } return $result; } public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) { $rs = parent::endVisitingObject($metadata, $data, $type, $context); // Force JSON output to "{}" instead of "[]" if it contains either no properties or all properties are null. if (empty($rs)) { $rs = new \ArrayObject(); if (array() === $this->getRoot()) { $this->setRoot($rs); } } return $rs; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; class DeserializationContext extends Context { private $depth = 0; public static function create() { return new self(); } public function getDirection() { return GraphNavigator::DIRECTION_DESERIALIZATION; } public function getDepth() { return $this->depth; } public function increaseDepth() { $this->depth += 1; } public function decreaseDepth() { if ($this->depth <= 0) { throw new \LogicException('Depth cannot be smaller than zero.'); } $this->depth -= 1; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Construction\ObjectConstructorInterface; use JMS\Serializer\Handler\HandlerRegistryInterface; use JMS\Serializer\EventDispatcher\EventDispatcherInterface; use JMS\Serializer\Exception\UnsupportedFormatException; use Metadata\MetadataFactoryInterface; use PhpCollection\MapInterface; /** * Serializer Implementation. * * @author Johannes M. Schmitt */ class Serializer implements SerializerInterface { private $factory; private $handlerRegistry; private $objectConstructor; private $dispatcher; private $typeParser; /** @var \PhpCollection\MapInterface */ private $serializationVisitors; /** @var \PhpCollection\MapInterface */ private $deserializationVisitors; private $navigator; /** * Constructor. * * @param \Metadata\MetadataFactoryInterface $factory * @param Handler\HandlerRegistryInterface $handlerRegistry * @param Construction\ObjectConstructorInterface $objectConstructor * @param \PhpCollection\MapInterface $serializationVisitors * @param \PhpCollection\MapInterface $deserializationVisitors * @param EventDispatcher\EventDispatcherInterface $dispatcher * @param TypeParser $typeParser */ public function __construct(MetadataFactoryInterface $factory, HandlerRegistryInterface $handlerRegistry, ObjectConstructorInterface $objectConstructor, MapInterface $serializationVisitors, MapInterface $deserializationVisitors, EventDispatcherInterface $dispatcher = null, TypeParser $typeParser = null) { $this->factory = $factory; $this->handlerRegistry = $handlerRegistry; $this->objectConstructor = $objectConstructor; $this->dispatcher = $dispatcher; $this->typeParser = $typeParser ?: new TypeParser(); $this->serializationVisitors = $serializationVisitors; $this->deserializationVisitors = $deserializationVisitors; $this->navigator = new GraphNavigator($this->factory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher); } public function serialize($data, $format, SerializationContext $context = null) { if ( ! $this->serializationVisitors->containsKey($format)) { throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for serialization.', $format)); } if (null === $context) { $context = new SerializationContext(); } $context->initialize( $format, $visitor = $this->serializationVisitors->get($format)->get(), $this->navigator, $this->factory ); $visitor->setNavigator($this->navigator); $this->navigator->accept($visitor->prepare($data), null, $context); return $visitor->getResult(); } public function deserialize($data, $type, $format, DeserializationContext $context = null) { if ( ! $this->deserializationVisitors->containsKey($format)) { throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for deserialization.', $format)); } if (null === $context) { $context = new DeserializationContext(); } $context->initialize( $format, $visitor = $this->deserializationVisitors->get($format)->get(), $this->navigator, $this->factory ); $visitor->setNavigator($this->navigator); $navigatorResult = $this->navigator->accept($visitor->prepare($data), $this->typeParser->parse($type), $context); // This is a special case if the root is handled by a callback on the object iself. if ((null === $visitorResult = $visitor->getResult()) && null !== $navigatorResult) { return $navigatorResult; } return $visitorResult; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher; interface EventDispatcherInterface { /** * Returns whether there are listeners. * * @param string $eventName * @param string $class * @param string $format * * @return boolean */ public function hasListeners($eventName, $class, $format); /** * Dispatches an event. * * The listeners/subscribers are called in the same order in which they * were added to the dispatcher. * * @param string $eventName * @param string $class * @param string $format * @param Event $event * @return void */ public function dispatch($eventName, $class, $format, Event $event); /** * Adds a listener. * * @param string $eventName * @param callable $callable * @param string|null $class * @param string|null $format * @return void */ public function addListener($eventName, $callable, $class = null, $format = null); /** * Adds a subscribers. * * @param EventSubscriberInterface $subscriber * @return void */ public function addSubscriber(EventSubscriberInterface $subscriber); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher; class PreSerializeEvent extends ObjectEvent { /** * @param string $typeName * @param array $params */ public function setType($typeName, array $params = array()) { $this->type = array('name' => $typeName, 'params' => $params); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher; interface EventSubscriberInterface { /** * Returns the events to which this class has subscribed. * * Return format: * array( * array('event' => 'the-event-name', 'method' => 'onEventName', 'class' => 'some-class', 'format' => 'json'), * array(...), * ) * * The class may be omitted if the class wants to subscribe to events of all classes. * Same goes for the format key. * * @return array */ public static function getSubscribedEvents(); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher\Subscriber; use Doctrine\ORM\PersistentCollection; use Doctrine\Common\Persistence\Proxy; use Doctrine\ORM\Proxy\Proxy as ORMProxy; use JMS\Serializer\EventDispatcher\PreSerializeEvent; use JMS\Serializer\EventDispatcher\EventSubscriberInterface; class DoctrineProxySubscriber implements EventSubscriberInterface { public function onPreSerialize(PreSerializeEvent $event) { $object = $event->getObject(); $type = $event->getType(); // If the set type name is not an actual class, but a faked type for which a custom handler exists, we do not // modify it with this subscriber. Also, we forgo autoloading here as an instance of this type is already created, // so it must be loaded if its a real class. $virtualType = ! class_exists($type['name'], false); if ($object instanceof PersistentCollection) { if ( ! $virtualType) { $event->setType('ArrayCollection'); } return; } if ( ! $object instanceof Proxy && ! $object instanceof ORMProxy) { return; } $object->__load(); if ( ! $virtualType) { $event->setType(get_parent_class($object)); } } public static function getSubscribedEvents() { return array( array('event' => 'serializer.pre_serialize', 'method' => 'onPreSerialize'), ); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher\Subscriber; use JMS\Serializer\EventDispatcher\Event; use JMS\Serializer\EventDispatcher\EventSubscriberInterface; use JMS\Serializer\Exception\ValidationFailedException; use Symfony\Component\Validator\ValidatorInterface; class SymfonyValidatorSubscriber implements EventSubscriberInterface { private $validator; public function __construct(ValidatorInterface $validator) { $this->validator = $validator; } public static function getSubscribedEvents() { return array( array('event' => 'serializer.post_deserialize', 'method' => 'onPostDeserialize'), ); } public function onPostDeserialize(Event $event) { $context = $event->getContext(); if ($context->getDepth() > 0) { return; } $validator = $this->validator; $context->attributes->get('validation_groups')->map( function(array $groups) use ($event, $validator) { $list = $validator->validate($event->getObject(), $groups); if ($list->count() > 0) { throw new ValidationFailedException($list); } } ); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher; use JMS\Serializer\Context; class Event { protected $type; private $context; public function __construct(Context $context, array $type) { $this->context = $context; $this->type = $type; } public function getVisitor() { return $this->context->getVisitor(); } public function getContext() { return $this->context; } public function getType() { return $this->type; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher; abstract class Events { const PRE_SERIALIZE = 'serializer.pre_serialize'; const POST_SERIALIZE = 'serializer.post_serialize'; const POST_DESERIALIZE = 'serializer.post_deserialize'; final private function __construct() { } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher; use JMS\Serializer\DeserializationContext; class PreDeserializeEvent extends Event { private $data; public function __construct(DeserializationContext $context, $data, array $type) { parent::__construct($context, $type); $this->data = $data; } public function setType($name, array $params = array()) { $this->type = array('name' => $name, 'params' => $params); } public function getData() { return $this->data; } public function setData($data) { $this->data = $data; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher; use Symfony\Component\DependencyInjection\ContainerInterface; class LazyEventDispatcher extends EventDispatcher { private $container; public function __construct(ContainerInterface $container) { $this->container = $container; } /** * {@inheritdoc} */ protected function initializeListeners($eventName, $loweredClass, $format) { $listeners = parent::initializeListeners($eventName, $loweredClass, $format); foreach ($listeners as &$listener) { if ( ! is_array($listener) || ! is_string($listener[0])) { continue; } if ( ! $this->container->has($listener[0])) { continue; } $listener[0] = $this->container->get($listener[0]); } return $listeners; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher; use JMS\Serializer\Context; class ObjectEvent extends Event { private $object; public function __construct(Context $context, $object, array $type) { parent::__construct($context, $type); $this->object = $object; } public function getObject() { return $this->object; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\EventDispatcher; use JMS\Serializer\Exception\InvalidArgumentException; /** * Light-weight event dispatcher. * * This implementation focuses primarily on performance, and dispatching * events for certain classes. It is not a general purpose event dispatcher. * * @author Johannes M. Schmitt */ class EventDispatcher implements EventDispatcherInterface { private $listeners = array(); private $classListeners = array(); public static function getDefaultMethodName($eventName) { return 'on'.str_replace(array('_', '.'), '', $eventName); } /** * Sets the listeners. * * @param array $listeners */ public function setListeners(array $listeners) { $this->listeners = $listeners; $this->classListeners = array(); } public function addListener($eventName, $callable, $class = null, $format = null) { $this->listeners[$eventName][] = array($callable, null === $class ? null : strtolower($class), $format); unset($this->classListeners[$eventName]); } public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventData) { if ( ! isset($eventData['event'])) { throw new InvalidArgumentException(sprintf('Each event must have a "event" key.')); } $method = isset($eventData['method']) ? $eventData['method'] : self::getDefaultMethodName($eventData['event']); $class = isset($eventData['class']) ? strtolower($eventData['class']) : null; $format = isset($eventData['format']) ? $eventData['format'] : null; $this->listeners[$eventData['event']][] = array(array($subscriber, $method), $class, $format); unset($this->classListeners[$eventData['event']]); } } public function hasListeners($eventName, $class, $format) { if ( ! isset($this->listeners[$eventName])) { return false; } $loweredClass = strtolower($class); if ( ! isset($this->classListeners[$eventName][$loweredClass][$format])) { $this->classListeners[$eventName][$loweredClass][$format] = $this->initializeListeners($eventName, $loweredClass, $format); } return !!$this->classListeners[$eventName][$loweredClass][$format]; } public function dispatch($eventName, $class, $format, Event $event) { if ( ! isset($this->listeners[$eventName])) { return; } $loweredClass = strtolower($class); if ( ! isset($this->classListeners[$eventName][$loweredClass][$format])) { $this->classListeners[$eventName][$loweredClass][$format] = $this->initializeListeners($eventName, $loweredClass, $format); } foreach ($this->classListeners[$eventName][$loweredClass][$format] as $listener) { call_user_func($listener, $event); } } /** * @param string $eventName * @param string $loweredClass * @param string $format * * @return array An array of listeners */ protected function initializeListeners($eventName, $loweredClass, $format) { $listeners = array(); foreach ($this->listeners[$eventName] as $listener) { if (null !== $listener[1] && $loweredClass !== $listener[1]) { continue; } if (null !== $listener[2] && $format !== $listener[2]) { continue; } $listeners[] = $listener[0]; } return $listeners; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY", "METHOD"}) */ final class Since extends Version { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target("METHOD") * * @author Alexander Klimenkov */ final class VirtualProperty { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target("METHOD") * * @author Johannes M. Schmitt */ final class HandlerCallback { /** * @Required * @var string */ public $format; /** * @Required * @var string */ public $direction; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * This annotation can be declared on methods which should be called * before the Serialization process. * * These methods do not need to be public, and should do any clean-up, or * preparation of the object that is necessary. * * @Annotation * @Target("METHOD") * @author Johannes M. Schmitt */ final class PreSerialize { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY", "METHOD"}) */ final class Until extends Version { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY", "CLASS"}) */ final class Exclude { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY","METHOD"}) */ final class XmlMap extends XmlCollection { /** * @var string */ public $keyAttribute = '_key'; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; abstract class Version { /** * @Required * @var string */ public $version; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * This annotation can be defined on methods which are called after the * deserialization of the object is complete. * * These methods do not necessarily have to be public. * * @Annotation * @Target("METHOD") * @author Johannes M. Schmitt */ final class PostDeserialize { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY","METHOD"}) */ final class XmlKeyValuePairs { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY","METHOD"}) */ final class Groups { /** @var array @Required */ public $groups; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY", "METHOD"}) */ final class Type { /** * @Required * @var string */ public $name; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target("PROPERTY") */ final class Expose { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; abstract class XmlCollection { /** * @var string */ public $entry = 'entry'; /** * @var boolean */ public $inline = false; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY","METHOD"}) */ final class XmlValue { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target("METHOD") */ final class PostSerialize { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"CLASS", "PROPERTY"}) * * @author Johannes M. Schmitt */ final class AccessType { /** * @Required * @var string */ public $type; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY","METHOD"}) */ final class Inline { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY","METHOD"}) */ final class XmlList extends XmlCollection { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target("PROPERTY") * * @author Johannes M. Schmitt */ final class Accessor { /** * @var string */ public $getter; /** * @var string */ public $setter; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target("CLASS") */ class Discriminator { /** @var array */ public $map; /** @var string */ public $field = 'type'; /** @var boolean */ public $disabled = false; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target("CLASS") */ final class XmlRoot { /** * @Required * @var string */ public $name; } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; use JMS\Serializer\Exception\RuntimeException; /** * @Annotation * @Target("CLASS") */ final class ExclusionPolicy { const NONE = 'NONE'; const ALL = 'ALL'; public $policy; public function __construct(array $values) { if (!is_string($values['value'])) { throw new RuntimeException('"value" must be a string.'); } $this->policy = strtoupper($values['value']); if (self::NONE !== $this->policy && self::ALL !== $this->policy) { throw new RuntimeException('Exclusion policy must either be "ALL", or "NONE".'); } } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * Controls the order of properties in a class. * * @Annotation * @Target("CLASS") * @author Johannes M. Schmitt */ final class AccessorOrder { /** * @Required * @var string */ public $order; /** * @var array */ public $custom = array(); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; use JMS\Serializer\Exception\RuntimeException; /** * @Annotation * @Target({"PROPERTY","METHOD"}) */ final class SerializedName { public $name; public function __construct(array $values) { if (!is_string($values['value'])) { throw new RuntimeException(sprintf('"value" must be a string.')); } $this->name = $values['value']; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target("PROPERTY") */ final class ReadOnly { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY", "METHOD"}) */ final class XmlAttributeMap { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Annotation; /** * @Annotation * @Target({"PROPERTY", "METHOD"}) */ final class XmlAttribute { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\Exclusion\DisjunctExclusionStrategy; use JMS\Serializer\Exclusion\ExclusionStrategyInterface; use JMS\Serializer\Exclusion\GroupsExclusionStrategy; use JMS\Serializer\Exclusion\VersionExclusionStrategy; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; use Metadata\MetadataFactory; use Metadata\MetadataFactoryInterface; use PhpCollection\Map; abstract class Context { /** * @var \PhpCollection\Map */ public $attributes; private $format; /** @var VisitorInterface */ private $visitor; /** @var GraphNavigator */ private $navigator; /** @var MetadataFactory */ private $metadataFactory; /** @var ExclusionStrategyInterface */ private $exclusionStrategy; /** @var boolean */ private $serializeNull; private $initialized = false; /** @var \SplStack */ private $metadataStack; public function __construct() { $this->attributes = new Map(); } public function initialize($format, VisitorInterface $visitor, GraphNavigator $navigator, MetadataFactoryInterface $factory) { if ($this->initialized) { throw new \LogicException('This context was already initialized, and cannot be re-used.'); } $this->initialized = true; $this->format = $format; $this->visitor = $visitor; $this->navigator = $navigator; $this->metadataFactory = $factory; $this->metadataStack = new \SplStack(); } public function accept($data, array $type = null) { return $this->navigator->accept($data, $type, $this); } public function getMetadataFactory() { return $this->metadataFactory; } public function getVisitor() { return $this->visitor; } public function getNavigator() { return $this->navigator; } public function getExclusionStrategy() { return $this->exclusionStrategy; } public function setAttribute($key, $value) { $this->assertMutable(); $this->attributes->set($key, $value); return $this; } private function assertMutable() { if ( ! $this->initialized) { return; } throw new \LogicException('This context was already initialized and is immutable; you cannot modify it anymore.'); } public function addExclusionStrategy(ExclusionStrategyInterface $strategy) { $this->assertMutable(); if (null === $this->exclusionStrategy) { $this->exclusionStrategy = $strategy; return $this; } if ($this->exclusionStrategy instanceof DisjunctExclusionStrategy) { $this->exclusionStrategy->addStrategy($strategy); return $this; } $this->exclusionStrategy = new DisjunctExclusionStrategy(array( $this->exclusionStrategy, $strategy, )); return $this; } /** * @param integer $version */ public function setVersion($version) { if (null === $version) { throw new \LogicException('The version must not be null.'); } $this->attributes->set('version', $version); $this->addExclusionStrategy(new VersionExclusionStrategy($version)); return $this; } /** * @param array|string $groups */ public function setGroups($groups) { if (empty($groups)) { throw new \LogicException('The groups must not be empty.'); } $this->attributes->set('groups', (array) $groups); $this->addExclusionStrategy(new GroupsExclusionStrategy((array) $groups)); return $this; } public function setSerializeNull($bool) { $this->serializeNull = (boolean) $bool; return $this; } public function shouldSerializeNull() { return $this->serializeNull; } public function getFormat() { return $this->format; } public function pushClassMetadata(ClassMetadata $metadata) { $this->metadataStack->push($metadata); } public function pushPropertyMetadata(PropertyMetadata $metadata) { $this->metadataStack->push($metadata); } public function popPropertyMetadata() { $metadata = $this->metadataStack->pop(); if (!$metadata instanceof PropertyMetadata) { throw new RuntimeException('Context metadataStack not working well'); } } public function popClassMetadata() { $metadata = $this->metadataStack->pop(); if (!$metadata instanceof ClassMetadata) { throw new RuntimeException('Context metadataStack not working well'); } } public function getMetadataStack() { return $this->metadataStack; } abstract public function getDepth(); abstract public function getDirection(); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Exception\RuntimeException; class JsonDeserializationVisitor extends GenericDeserializationVisitor { protected function decode($str) { $decoded = json_decode($str, true); switch (json_last_error()) { case JSON_ERROR_NONE: return $decoded; case JSON_ERROR_DEPTH: throw new RuntimeException('Could not decode JSON, maximum stack depth exceeded.'); case JSON_ERROR_STATE_MISMATCH: throw new RuntimeException('Could not decode JSON, underflow or the nodes mismatch.'); case JSON_ERROR_CTRL_CHAR: throw new RuntimeException('Could not decode JSON, unexpected control character found.'); case JSON_ERROR_SYNTAX: throw new RuntimeException('Could not decode JSON, syntax error - malformed JSON.'); case JSON_ERROR_UTF8: throw new RuntimeException('Could not decode JSON, malformed UTF-8 characters (incorrectly encoded?)'); default: throw new RuntimeException('Could not decode JSON.'); } } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Util; use JMS\Serializer\Exception\RuntimeException; /** * A writer implementation. * * This may be used to simplify writing well-formatted code. * * @author Johannes M. Schmitt */ class Writer { public $indentationSpaces = 4; public $indentationLevel = 0; public $content = ''; public $changeCount = 0; private $changes = array(); public function indent() { $this->indentationLevel += 1; return $this; } public function outdent() { $this->indentationLevel -= 1; if ($this->indentationLevel < 0) { throw new RuntimeException('The identation level cannot be less than zero.'); } return $this; } /** * @param string $content * * @return Writer */ public function writeln($content) { $this->write($content."\n"); return $this; } public function revert() { $change = array_pop($this->changes); $this->changeCount -=1 ; $this->content = substr($this->content, 0, -1 * strlen($change)); } /** * @param string $content * * @return Writer */ public function write($content) { $addition = ''; $lines = explode("\n", $content); for ($i=0,$c=count($lines); $i<$c; $i++) { if ($this->indentationLevel > 0 && !empty($lines[$i]) && ((empty($addition) && "\n" === substr($this->content, -1)) || "\n" === substr($addition, -1))) { $addition .= str_repeat(' ', $this->indentationLevel * $this->indentationSpaces); } $addition .= $lines[$i]; if ($i+1 < $c) { $addition .= "\n"; } } $this->content .= $addition; $this->changes[] = $addition; $this->changeCount += 1; return $this; } public function rtrim($preserveNewLines = true) { if (!$preserveNewLines) { $this->content = rtrim($this->content); return $this; } $addNl = "\n" === substr($this->content, -1); $this->content = rtrim($this->content); if ($addNl) { $this->content .= "\n"; } return $this; } public function reset() { $this->content = ''; $this->indentationLevel = 0; return $this; } public function getContent() { return $this->content; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Metadata\ClassMetadata; /** * Generic Deserialization Visitor. * * @author Johannes M. Schmitt */ abstract class GenericDeserializationVisitor extends AbstractVisitor { private $navigator; private $result; private $objectStack; private $currentObject; public function setNavigator(GraphNavigator $navigator) { $this->navigator = $navigator; $this->result = null; $this->objectStack = new \SplStack; } public function getNavigator() { return $this->navigator; } public function prepare($data) { return $this->decode($data); } public function visitNull($data, array $type, Context $context) { return null; } public function visitString($data, array $type, Context $context) { $data = (string) $data; if (null === $this->result) { $this->result = $data; } return $data; } public function visitBoolean($data, array $type, Context $context) { $data = (Boolean) $data; if (null === $this->result) { $this->result = $data; } return $data; } public function visitInteger($data, array $type, Context $context) { $data = (integer) $data; if (null === $this->result) { $this->result = $data; } return $data; } public function visitDouble($data, array $type, Context $context) { $data = (double) $data; if (null === $this->result) { $this->result = $data; } return $data; } public function visitArray($data, array $type, Context $context) { if ( ! is_array($data)) { throw new RuntimeException(sprintf('Expected array, but got %s: %s', gettype($data), json_encode($data))); } // If no further parameters were given, keys/values are just passed as is. if ( ! $type['params']) { if (null === $this->result) { $this->result = $data; } return $data; } switch (count($type['params'])) { case 1: // Array is a list. $listType = $type['params'][0]; $result = array(); if (null === $this->result) { $this->result = &$result; } foreach ($data as $v) { $result[] = $this->navigator->accept($v, $listType, $context); } return $result; case 2: // Array is a map. list($keyType, $entryType) = $type['params']; $result = array(); if (null === $this->result) { $this->result = &$result; } foreach ($data as $k => $v) { $result[$this->navigator->accept($k, $keyType, $context)] = $this->navigator->accept($v, $entryType, $context); } return $result; default: throw new RuntimeException(sprintf('Array type cannot have more than 2 parameters, but got %s.', json_encode($type['params']))); } } public function startVisitingObject(ClassMetadata $metadata, $object, array $type, Context $context) { $this->setCurrentObject($object); if (null === $this->result) { $this->result = $this->currentObject; } } public function visitProperty(PropertyMetadata $metadata, $data, Context $context) { $name = $this->namingStrategy->translateName($metadata); if (null === $data || ! array_key_exists($name, $data)) { return; } if ( ! $metadata->type) { throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->class, $metadata->name)); } $v = $data[$name] !== null ? $this->navigator->accept($data[$name], $metadata->type, $context) : null; if (null === $metadata->setter) { $metadata->reflection->setValue($this->currentObject, $v); return; } $this->currentObject->{$metadata->setter}($v); } public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) { $obj = $this->currentObject; $this->revertCurrentObject(); return $obj; } public function getResult() { return $this->result; } public function setCurrentObject($object) { $this->objectStack->push($this->currentObject); $this->currentObject = $object; } public function getCurrentObject() { return $this->currentObject; } public function revertCurrentObject() { return $this->currentObject = $this->objectStack->pop(); } abstract protected function decode($str); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Naming\PropertyNamingStrategyInterface; abstract class AbstractVisitor implements VisitorInterface { protected $namingStrategy; public function __construct(PropertyNamingStrategyInterface $namingStrategy) { $this->namingStrategy = $namingStrategy; } public function getNamingStrategy() { return $this->namingStrategy; } public function prepare($data) { return $data; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Exception\LogicException; use JMS\Serializer\Exception\RuntimeException; use Metadata\MetadataFactoryInterface; class SerializationContext extends Context { /** @var \SplObjectStorage */ private $visitingSet; /** @var \SplStack */ private $visitingStack; public static function create() { return new self(); } public function initialize($format, VisitorInterface $visitor, GraphNavigator $navigator, MetadataFactoryInterface $factory) { parent::initialize($format, $visitor, $navigator, $factory); $this->visitingSet = new \SplObjectStorage(); $this->visitingStack = new \SplStack(); } public function startVisiting($object) { $this->visitingSet->attach($object); $this->visitingStack->push($object); } public function stopVisiting($object) { $this->visitingSet->detach($object); $poppedObject = $this->visitingStack->pop(); if ($object !== $poppedObject) { throw new RuntimeException('Context visitingStack not working well'); } } public function isVisiting($object) { if (! is_object($object)) { throw new LogicException('Expected object but got ' . gettype($object) . '. Do you have the wrong @Type mapping or could this be a Doctrine many-to-many relation?'); } return $this->visitingSet->contains($object); } public function getPath() { $path = array(); foreach ($this->visitingStack as $obj) { $path[] = get_class($obj); } if ( ! $path) { return null; } return implode(' -> ', $path); } public function getDirection() { return GraphNavigator::DIRECTION_SERIALIZATION; } public function getDepth() { return $this->visitingStack->count(); } public function getObject() { return !$this->visitingStack->isEmpty() ? $this->visitingStack->top() : null; } public function getVisitingStack() { return $this->visitingStack; } public function getVisitingSet() { return $this->visitingSet; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; /** * Serializer Interface. * * @author Johannes M. Schmitt */ interface SerializerInterface { /** * Serializes the given data to the specified output format. * * @param object|array|scalar $data * @param string $format * @param Context $context * * @return string */ public function serialize($data, $format, SerializationContext $context = null); /** * Deserializes the given data to the specified type. * * @param string $data * @param string $type * @param string $format * @param Context $context * * @return object|array|scalar */ public function deserialize($data, $type, $format, DeserializationContext $context = null); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Naming; use JMS\Serializer\Metadata\PropertyMetadata; /** * Generic naming strategy which translates a camel-cased property name. * * @author Johannes M. Schmitt */ class CamelCaseNamingStrategy implements PropertyNamingStrategyInterface { private $separator; private $lowerCase; public function __construct($separator = '_', $lowerCase = true) { $this->separator = $separator; $this->lowerCase = $lowerCase; } /** * {@inheritDoc} */ public function translateName(PropertyMetadata $property) { $name = preg_replace('/[A-Z]/', $this->separator.'\\0', $property->name); if ($this->lowerCase) { return strtolower($name); } return ucfirst($name); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Naming; use JMS\Serializer\Metadata\PropertyMetadata; /** * Naming strategy which uses an annotation to translate the property name. * * @author Johannes M. Schmitt */ class SerializedNameAnnotationStrategy implements PropertyNamingStrategyInterface { private $delegate; public function __construct(PropertyNamingStrategyInterface $namingStrategy) { $this->delegate = $namingStrategy; } /** * {@inheritDoc} */ public function translateName(PropertyMetadata $property) { if (null !== $name = $property->serializedName) { return $name; } return $this->delegate->translateName($property); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Naming; use JMS\Serializer\Metadata\PropertyMetadata; class CacheNamingStrategy implements PropertyNamingStrategyInterface { private $delegate; private $cache; public function __construct(PropertyNamingStrategyInterface $delegate) { $this->delegate = $delegate; $this->cache = new \SplObjectStorage(); } public function translateName(PropertyMetadata $property) { if (isset($this->cache[$property])) { return $this->cache[$property]; } return $this->cache[$property] = $this->delegate->translateName($property); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Naming; use JMS\Serializer\Metadata\PropertyMetadata; /** * Interface for property naming strategies. * * Implementations translate the property name to a serialized name that is * displayed. * * @author Johannes M. Schmitt */ interface PropertyNamingStrategyInterface { /** * Translates the name of the property to the serialized version. * * @param PropertyMetadata $property * * @return string */ public function translateName(PropertyMetadata $property); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Naming; use JMS\Serializer\Naming\PropertyNamingStrategyInterface; use JMS\Serializer\Metadata\PropertyMetadata; class IdenticalPropertyNamingStrategy implements PropertyNamingStrategyInterface { public function translateName(PropertyMetadata $property) { return $property->name; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Exception\InvalidArgumentException; use JMS\Serializer\Metadata\PropertyMetadata; abstract class GenericSerializationVisitor extends AbstractVisitor { private $navigator; private $root; private $dataStack; private $data; public function setNavigator(GraphNavigator $navigator) { $this->navigator = $navigator; $this->root = null; $this->dataStack = new \SplStack; } /** * @return GraphNavigator */ public function getNavigator() { return $this->navigator; } public function visitNull($data, array $type, Context $context) { return null; } public function visitString($data, array $type, Context $context) { if (null === $this->root) { $this->root = $data; } return (string) $data; } public function visitBoolean($data, array $type, Context $context) { if (null === $this->root) { $this->root = $data; } return (boolean) $data; } public function visitInteger($data, array $type, Context $context) { if (null === $this->root) { $this->root = $data; } return (int) $data; } public function visitDouble($data, array $type, Context $context) { if (null === $this->root) { $this->root = $data; } return (float) $data; } /** * @param array $data * @param array $type */ public function visitArray($data, array $type, Context $context) { if (null === $this->root) { $this->root = array(); $rs = &$this->root; } else { $rs = array(); } foreach ($data as $k => $v) { $v = $this->navigator->accept($v, isset($type['params'][1]) ? $type['params'][1] : null, $context); if (null === $v && (!is_string($k) || !$context->shouldSerializeNull())) { continue; } $rs[$k] = $v; } return $rs; } public function startVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) { if (null === $this->root) { $this->root = new \stdClass; } $this->dataStack->push($this->data); $this->data = array(); } public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) { $rs = $this->data; $this->data = $this->dataStack->pop(); if ($this->root instanceof \stdClass && 0 === $this->dataStack->count()) { $this->root = $rs; } return $rs; } public function visitProperty(PropertyMetadata $metadata, $data, Context $context) { $v = $metadata->getValue($data); $v = $this->navigator->accept($v, $metadata->type, $context); if (null === $v && !$context->shouldSerializeNull()) { return; } $k = $this->namingStrategy->translateName($metadata); if ($metadata->inline && is_array($v)) { $this->data = array_merge($this->data, $v); } else { $this->data[$k] = $v; } } /** * Allows you to add additional data to the current object/root element. * * @param string $key * @param scalar|array $value This value must either be a regular scalar, or an array. * It must not contain any objects anymore. */ public function addData($key, $value) { if (isset($this->data[$key])) { throw new InvalidArgumentException(sprintf('There is already data for "%s".', $key)); } $this->data[$key] = $value; } public function getRoot() { return $this->root; } /** * @param array|\ArrayObject $data the passed data must be understood by whatever encoding function is applied later. */ public function setRoot($data) { $this->root = $data; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Handler\PhpCollectionHandler; use JMS\Serializer\Exception\RuntimeException; use Metadata\MetadataFactory; use JMS\Serializer\Metadata\Driver\AnnotationDriver; use JMS\Serializer\Handler\HandlerRegistry; use JMS\Serializer\Construction\UnserializeObjectConstructor; use PhpCollection\Map; use JMS\Serializer\EventDispatcher\EventDispatcher; use Metadata\Driver\DriverChain; use JMS\Serializer\Metadata\Driver\YamlDriver; use JMS\Serializer\Metadata\Driver\XmlDriver; use Metadata\Driver\FileLocator; use JMS\Serializer\Handler\DateHandler; use JMS\Serializer\Handler\ArrayCollectionHandler; use JMS\Serializer\Construction\ObjectConstructorInterface; use JMS\Serializer\EventDispatcher\Subscriber\DoctrineProxySubscriber; use JMS\Serializer\Naming\CamelCaseNamingStrategy; use JMS\Serializer\Naming\PropertyNamingStrategyInterface; use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\FileCacheReader; use Metadata\Cache\FileCache; use JMS\Serializer\Naming\SerializedNameAnnotationStrategy; use JMS\Serializer\Exception\InvalidArgumentException; /** * Builder for serializer instances. * * This object makes serializer construction a breeze for projects that do not use * any special dependency injection container. * * @author Johannes M. Schmitt */ class SerializerBuilder { private $metadataDirs = array(); private $handlerRegistry; private $handlersConfigured = false; private $eventDispatcher; private $listenersConfigured = false; private $objectConstructor; private $serializationVisitors; private $deserializationVisitors; private $visitorsAdded = false; private $propertyNamingStrategy; private $debug = false; private $cacheDir; private $annotationReader; private $includeInterfaceMetadata = false; public static function create() { return new static(); } public function __construct() { $this->handlerRegistry = new HandlerRegistry(); $this->eventDispatcher = new EventDispatcher(); $this->serializationVisitors = new Map(); $this->deserializationVisitors = new Map(); } public function setAnnotationReader(AnnotationReader $reader) { $this->annotationReader = $reader; return $this; } public function setDebug($bool) { $this->debug = (boolean) $bool; return $this; } public function setCacheDir($dir) { if ( ! is_dir($dir)) { $this->createDir($dir); } if ( ! is_writable($dir)) { throw new InvalidArgumentException(sprintf('The cache directory "%s" is not writable.', $dir)); } $this->cacheDir = $dir; return $this; } public function addDefaultHandlers() { $this->handlersConfigured = true; $this->handlerRegistry->registerSubscribingHandler(new DateHandler()); $this->handlerRegistry->registerSubscribingHandler(new PhpCollectionHandler()); $this->handlerRegistry->registerSubscribingHandler(new ArrayCollectionHandler()); return $this; } public function configureHandlers(\Closure $closure) { $this->handlersConfigured = true; $closure($this->handlerRegistry); return $this; } public function addDefaultListeners() { $this->listenersConfigured = true; $this->eventDispatcher->addSubscriber(new DoctrineProxySubscriber()); return $this; } public function configureListeners(\Closure $closure) { $this->listenersConfigured = true; $closure($this->eventDispatcher); return $this; } public function setObjectConstructor(ObjectConstructorInterface $constructor) { $this->objectConstructor = $constructor; return $this; } public function setPropertyNamingStrategy(PropertyNamingStrategyInterface $propertyNamingStrategy) { $this->propertyNamingStrategy = $propertyNamingStrategy; return $this; } public function setSerializationVisitor($format, VisitorInterface $visitor) { $this->visitorsAdded = true; $this->serializationVisitors->set($format, $visitor); return $this; } public function setDeserializationVisitor($format, VisitorInterface $visitor) { $this->visitorsAdded = true; $this->deserializationVisitors->set($format, $visitor); return $this; } public function addDefaultSerializationVisitors() { $this->initializePropertyNamingStrategy(); $this->visitorsAdded = true; $this->serializationVisitors->setAll(array( 'xml' => new XmlSerializationVisitor($this->propertyNamingStrategy), 'yml' => new YamlSerializationVisitor($this->propertyNamingStrategy), 'json' => new JsonSerializationVisitor($this->propertyNamingStrategy), )); return $this; } public function addDefaultDeserializationVisitors() { $this->initializePropertyNamingStrategy(); $this->visitorsAdded = true; $this->deserializationVisitors->setAll(array( 'xml' => new XmlDeserializationVisitor($this->propertyNamingStrategy), 'json' => new JsonDeserializationVisitor($this->propertyNamingStrategy), )); return $this; } /** * @param Boolean $include Whether to include the metadata from the interfaces * * @return SerializerBuilder */ public function includeInterfaceMetadata($include) { $this->includeInterfaceMetadata = (Boolean) $include; return $this; } /** * Sets a map of namespace prefixes to directories. * * This method overrides any previously defined directories. * * @param array $namespacePrefixToDirMap * * @return SerializerBuilder * * @throws InvalidArgumentException When a directory does not exist */ public function setMetadataDirs(array $namespacePrefixToDirMap) { foreach ($namespacePrefixToDirMap as $dir) { if ( ! is_dir($dir)) { throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir)); } } $this->metadataDirs = $namespacePrefixToDirMap; return $this; } /** * Adds a directory where the serializer will look for class metadata. * * The namespace prefix will make the names of the actual metadata files a bit shorter. For example, let's assume * that you have a directory where you only store metadata files for the ``MyApplication\Entity`` namespace. * * If you use an empty prefix, your metadata files would need to look like: * * ``my-dir/MyApplication.Entity.SomeObject.yml`` * ``my-dir/MyApplication.Entity.OtherObject.xml`` * * If you use ``MyApplication\Entity`` as prefix, your metadata files would need to look like: * * ``my-dir/SomeObject.yml`` * ``my-dir/OtherObject.yml`` * * Please keep in mind that you currently may only have one directory per namespace prefix. * * @param string $dir The directory where metadata files are located. * @param string $namespacePrefix An optional prefix if you only store metadata for specific namespaces in this directory. * * @return SerializerBuilder * * @throws InvalidArgumentException When a directory does not exist * @throws InvalidArgumentException When a directory has already been registered */ public function addMetadataDir($dir, $namespacePrefix = '') { if ( ! is_dir($dir)) { throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir)); } if (isset($this->metadataDirs[$namespacePrefix])) { throw new InvalidArgumentException(sprintf('There is already a directory configured for the namespace prefix "%s". Please use replaceMetadataDir() to override directories.', $namespacePrefix)); } $this->metadataDirs[$namespacePrefix] = $dir; return $this; } /** * Adds a map of namespace prefixes to directories. * * @param array $namespacePrefixToDirMap * * @return SerializerBuilder */ public function addMetadataDirs(array $namespacePrefixToDirMap) { foreach ($namespacePrefixToDirMap as $prefix => $dir) { $this->addMetadataDir($dir, $prefix); } return $this; } /** * Similar to addMetadataDir(), but overrides an existing entry. * * @param string $dir * @param string $namespacePrefix * * @return SerializerBuilder * * @throws InvalidArgumentException When a directory does not exist * @throws InvalidArgumentException When no directory is configured for the ns prefix */ public function replaceMetadataDir($dir, $namespacePrefix = '') { if ( ! is_dir($dir)) { throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir)); } if ( ! isset($this->metadataDirs[$namespacePrefix])) { throw new InvalidArgumentException(sprintf('There is no directory configured for namespace prefix "%s". Please use addMetadataDir() for adding new directories.', $namespacePrefix)); } $this->metadataDirs[$namespacePrefix] = $dir; return $this; } public function build() { $annotationReader = $this->annotationReader; if (null === $annotationReader) { $annotationReader = new AnnotationReader(); if (null !== $this->cacheDir) { $this->createDir($this->cacheDir.'/annotations'); $annotationReader = new FileCacheReader($annotationReader, $this->cacheDir.'/annotations', $this->debug); } } if ( ! empty($this->metadataDirs)) { $fileLocator = new FileLocator($this->metadataDirs); $metadataDriver = new DriverChain(array( new YamlDriver($fileLocator), new XmlDriver($fileLocator), new AnnotationDriver($annotationReader), )); } else { $metadataDriver = new AnnotationDriver($annotationReader); } $metadataFactory = new MetadataFactory($metadataDriver, null, $this->debug); $metadataFactory->setIncludeInterfaces($this->includeInterfaceMetadata); if (null !== $this->cacheDir) { $this->createDir($this->cacheDir.'/metadata'); $metadataFactory->setCache(new FileCache($this->cacheDir.'/metadata')); } if ( ! $this->handlersConfigured) { $this->addDefaultHandlers(); } if ( ! $this->listenersConfigured) { $this->addDefaultListeners(); } if ( ! $this->visitorsAdded) { $this->addDefaultSerializationVisitors(); $this->addDefaultDeserializationVisitors(); } return new Serializer( $metadataFactory, $this->handlerRegistry, $this->objectConstructor ?: new UnserializeObjectConstructor(), $this->serializationVisitors, $this->deserializationVisitors, $this->eventDispatcher ); } private function initializePropertyNamingStrategy() { if (null !== $this->propertyNamingStrategy) { return; } $this->propertyNamingStrategy = new SerializedNameAnnotationStrategy(new CamelCaseNamingStrategy()); } private function createDir($dir) { if (is_dir($dir)) { return; } if (false === @mkdir($dir, 0777, true)) { throw new RuntimeException(sprintf('Could not create directory "%s".', $dir)); } } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Handler; use JMS\Serializer\GraphNavigator; use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\Exception\LogicException; class HandlerRegistry implements HandlerRegistryInterface { protected $handlers; public static function getDefaultMethod($direction, $type, $format) { if (false !== $pos = strrpos($type, '\\')) { $type = substr($type, $pos + 1); } switch ($direction) { case GraphNavigator::DIRECTION_DESERIALIZATION: return 'deserialize'.$type.'From'.$format; case GraphNavigator::DIRECTION_SERIALIZATION: return 'serialize'.$type.'To'.$format; default: throw new LogicException(sprintf('The direction %s does not exist; see GraphNavigator::DIRECTION_??? constants.', json_encode($direction))); } } public function __construct(array $handlers = array()) { $this->handlers = $handlers; } public function registerSubscribingHandler(SubscribingHandlerInterface $handler) { foreach ($handler->getSubscribingMethods() as $methodData) { if ( ! isset($methodData['type'], $methodData['format'])) { throw new RuntimeException(sprintf('For each subscribing method a "type" and "format" attribute must be given, but only got "%s" for %s.', implode('" and "', array_keys($methodData)), get_class($handler))); } $directions = array(GraphNavigator::DIRECTION_DESERIALIZATION, GraphNavigator::DIRECTION_SERIALIZATION); if (isset($methodData['direction'])) { $directions = array($methodData['direction']); } foreach ($directions as $direction) { $method = isset($methodData['method']) ? $methodData['method'] : self::getDefaultMethod($direction, $methodData['type'], $methodData['format']); $this->registerHandler($direction, $methodData['type'], $methodData['format'], array($handler, $method)); } } } public function registerHandler($direction, $typeName, $format, $handler) { if (is_string($direction)) { $direction = GraphNavigator::parseDirection($direction); } $this->handlers[$direction][$typeName][$format] = $handler; } public function getHandler($direction, $typeName, $format) { if ( ! isset($this->handlers[$direction][$typeName][$format])) { return null; } return $this->handlers[$direction][$typeName][$format]; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Handler; use Doctrine\Common\Collections\ArrayCollection; use JMS\Serializer\Context; use JMS\Serializer\GraphNavigator; use JMS\Serializer\VisitorInterface; use Doctrine\Common\Collections\Collection; use JMS\Serializer\Handler\SubscribingHandlerInterface; class ArrayCollectionHandler implements SubscribingHandlerInterface { public static function getSubscribingMethods() { $methods = array(); $formats = array('json', 'xml', 'yml'); $collectionTypes = array('ArrayCollection', 'Doctrine\Common\Collections\ArrayCollection', 'Doctrine\ORM\PersistentCollection', 'Doctrine\ODM\MongoDB\PersistentCollection'); foreach ($collectionTypes as $type) { foreach ($formats as $format) { $methods[] = array( 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, 'type' => $type, 'format' => $format, 'method' => 'serializeCollection', ); $methods[] = array( 'direction' => GraphNavigator::DIRECTION_DESERIALIZATION, 'type' => $type, 'format' => $format, 'method' => 'deserializeCollection', ); } } return $methods; } public function serializeCollection(VisitorInterface $visitor, Collection $collection, array $type, Context $context) { // We change the base type, and pass through possible parameters. $type['name'] = 'array'; return $visitor->visitArray($collection->toArray(), $type, $context); } public function deserializeCollection(VisitorInterface $visitor, $data, array $type, Context $context) { // See above. $type['name'] = 'array'; return new ArrayCollection($visitor->visitArray($data, $type, $context)); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Handler; use JMS\Serializer\Context; use JMS\Serializer\JsonDeserializationVisitor; use JMS\Serializer\XmlDeserializationVisitor; use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\VisitorInterface; use JMS\Serializer\GraphNavigator; class DateHandler implements SubscribingHandlerInterface { private $defaultFormat; private $defaultTimezone; public static function getSubscribingMethods() { $methods = array(); $types = array('DateTime', 'DateInterval'); foreach (array('json', 'xml', 'yml') as $format) { $methods[] = array( 'type' => 'DateTime', 'direction' => GraphNavigator::DIRECTION_DESERIALIZATION, 'format' => $format, ); foreach ($types as $type) { $methods[] = array( 'type' => $type, 'format' => $format, 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, 'method' => 'serialize'.$type, ); } } return $methods; } public function __construct($defaultFormat = \DateTime::ISO8601, $defaultTimezone = 'UTC') { $this->defaultFormat = $defaultFormat; $this->defaultTimezone = new \DateTimeZone($defaultTimezone); } public function serializeDateTime(VisitorInterface $visitor, \DateTime $date, array $type, Context $context) { return $visitor->visitString($date->format($this->getFormat($type)), $type, $context); } public function serializeDateInterval(VisitorInterface $visitor, \DateInterval $date, array $type, Context $context) { $iso8601DateIntervalString = $this->format($date); return $visitor->visitString($iso8601DateIntervalString, $type, $context); } public function deserializeDateTimeFromXml(XmlDeserializationVisitor $visitor, $data, array $type) { $attributes = $data->attributes(); if ((isset($attributes['nil'][0]) && (string) $attributes['nil'][0] === 'true') || (isset($attributes['xsi:nil'][0]) && (string) $attributes['xsi:nil'][0] === 'true')) { return null; } return $this->parseDateTime($data, $type); } public function deserializeDateTimeFromJson(JsonDeserializationVisitor $visitor, $data, array $type) { if (null === $data) { return null; } return $this->parseDateTime($data, $type); } private function parseDateTime($data, array $type) { $timezone = isset($type['params'][1]) ? new \DateTimeZone($type['params'][1]) : $this->defaultTimezone; $format = $this->getFormat($type); $datetime = \DateTime::createFromFormat($format, (string) $data, $timezone); if (false === $datetime) { throw new RuntimeException(sprintf('Invalid datetime "%s", expected format %s.', $data, $format)); } return $datetime; } /** * @return string * @param array $type */ private function getFormat(array $type) { return isset($type['params'][0]) ? $type['params'][0] : $this->defaultFormat; } /** * @param \DateInterval $dateInterval * @return string */ public function format(\DateInterval $dateInterval) { $format = 'P'; if (0 < $dateInterval->y) { $format .= $dateInterval->y.'Y'; } if (0 < $dateInterval->m) { $format .= $dateInterval->m.'M'; } if (0 < $dateInterval->d) { $format .= $dateInterval->d.'D'; } if (0 < $dateInterval->h || 0 < $dateInterval->i || 0 < $dateInterval->s) { $format .= 'T'; } if (0 < $dateInterval->h) { $format .= $dateInterval->h.'H'; } if (0 < $dateInterval->i) { $format .= $dateInterval->i.'M'; } if (0 < $dateInterval->s) { $format .= $dateInterval->s.'S'; } return $format; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Handler; use JMS\Serializer\YamlSerializationVisitor; use JMS\Serializer\JsonSerializationVisitor; use JMS\Serializer\GraphNavigator; use JMS\Serializer\GenericSerializationVisitor; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormError; use Symfony\Component\Translation\TranslatorInterface; use JMS\Serializer\XmlSerializationVisitor; class FormErrorHandler implements SubscribingHandlerInterface { private $translator; public static function getSubscribingMethods() { $methods = array(); foreach (array('xml', 'json', 'yml') as $format) { $methods[] = array( 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, 'type' => 'Symfony\Component\Form\Form', 'format' => $format, ); $methods[] = array( 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, 'type' => 'Symfony\Component\Form\FormError', 'format' => $format, ); } return $methods; } public function __construct(TranslatorInterface $translator) { $this->translator = $translator; } public function serializeFormToXml(XmlSerializationVisitor $visitor, Form $form, array $type) { if (null === $visitor->document) { $visitor->document = $visitor->createDocument(null, null, false); $visitor->document->appendChild($formNode = $visitor->document->createElement('form')); $visitor->setCurrentNode($formNode); } else { $visitor->getCurrentNode()->appendChild( $formNode = $visitor->document->createElement('form') ); } $formNode->setAttribute('name', $form->getName()); $formNode->appendChild($errorsNode = $visitor->document->createElement('errors')); foreach ($form->getErrors() as $error) { $errorNode = $visitor->document->createElement('entry'); $errorNode->appendChild($this->serializeFormErrorToXml($visitor, $error, array())); $errorsNode->appendChild($errorNode); } foreach ($form->all() as $child) { if (null !== $node = $this->serializeFormToXml($visitor, $child, array())) { $formNode->appendChild($node); } } return $formNode; } public function serializeFormToJson(JsonSerializationVisitor $visitor, Form $form, array $type) { return $this->convertFormToArray($visitor, $form); } public function serializeFormToYml(YamlSerializationVisitor $visitor, Form $form, array $type) { return $this->convertFormToArray($visitor, $form); } public function serializeFormErrorToXml(XmlSerializationVisitor $visitor, FormError $formError, array $type) { if (null === $visitor->document) { $visitor->document = $visitor->createDocument(null, null, true); } return $visitor->document->createCDATASection($this->getErrorMessage($formError)); } public function serializeFormErrorToJson(JsonSerializationVisitor $visitor, FormError $formError, array $type) { return $this->getErrorMessage($formError); } public function serializeFormErrorToYml(YamlSerializationVisitor $visitor, FormError $formError, array $type) { return $this->getErrorMessage($formError); } private function getErrorMessage(FormError $error) { if (null !== $error->getMessagePluralization()) { return $this->translator->transChoice($error->getMessageTemplate(), $error->getMessagePluralization(), $error->getMessageParameters(), 'validators'); } return $this->translator->trans($error->getMessageTemplate(), $error->getMessageParameters(), 'validators'); } private function convertFormToArray(GenericSerializationVisitor $visitor, Form $data) { $isRoot = null === $visitor->getRoot(); $form = $errors = array(); foreach ($data->getErrors() as $error) { $errors[] = $this->getErrorMessage($error); } if ($errors) { $form['errors'] = $errors; } $children = array(); foreach ($data->all() as $child) { $children[$child->getName()] = $this->convertFormToArray($visitor, $child); } if ($children) { $form['children'] = $children; } if ($isRoot) { $visitor->setRoot($form); } return $form; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Handler; use JMS\Serializer\Context; use JMS\Serializer\YamlSerializationVisitor; use JMS\Serializer\JsonSerializationVisitor; use JMS\Serializer\GraphNavigator; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; use JMS\Serializer\XmlSerializationVisitor; class ConstraintViolationHandler implements SubscribingHandlerInterface { public static function getSubscribingMethods() { $methods = array(); $formats = array('xml', 'json', 'yml'); $types = array('Symfony\Component\Validator\ConstraintViolationList' => 'serializeList', 'Symfony\Component\Validator\ConstraintViolation' => 'serializeViolation'); foreach ($types as $type => $method) { foreach ($formats as $format) { $methods[] = array( 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, 'type' => $type, 'format' => $format, 'method' => $method.'To'.$format, ); } } return $methods; } public function serializeListToXml(XmlSerializationVisitor $visitor, ConstraintViolationList $list, array $type) { if (null === $visitor->document) { $visitor->document = $visitor->createDocument(); } foreach ($list as $violation) { $this->serializeViolationToXml($visitor, $violation); } } public function serializeListToJson(JsonSerializationVisitor $visitor, ConstraintViolationList $list, array $type, Context $context) { return $visitor->visitArray(iterator_to_array($list), $type, $context); } public function serializeListToYml(YamlSerializationVisitor $visitor, ConstraintViolationList $list, array $type, Context $context) { return $visitor->visitArray(iterator_to_array($list), $type, $context); } public function serializeViolationToXml(XmlSerializationVisitor $visitor, ConstraintViolation $violation, array $type = null) { if (null === $visitor->document) { $visitor->document = $visitor->createDocument(null, null, false); $visitor->document->appendChild($violationNode = $visitor->document->createElement('violation')); $visitor->setCurrentNode($violationNode); } else { $visitor->getCurrentNode()->appendChild( $violationNode = $visitor->document->createElement('violation') ); } $violationNode->setAttribute('property_path', $violation->getPropertyPath()); $violationNode->appendChild($messageNode = $visitor->document->createElement('message')); $messageNode->appendChild($visitor->document->createCDATASection($violation->getMessage())); } public function serializeViolationToJson(JsonSerializationVisitor $visitor, ConstraintViolation $violation, array $type = null) { $data = array( 'property_path' => $violation->getPropertyPath(), 'message' => $violation->getMessage() ); if (null === $visitor->getRoot()) { $visitor->setRoot($data); } return $data; } public function serializeViolationToYml(YamlSerializationVisitor $visitor, ConstraintViolation $violation, array $type = null) { return array( 'property_path' => $violation->getPropertyPath(), 'message' => $violation->getMessage(), ); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Handler; interface SubscribingHandlerInterface { /** * @return array */ public static function getSubscribingMethods(); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Handler; /** * Handler Registry Interface. * * @author Johannes M. Schmitt */ interface HandlerRegistryInterface { /** * @param SubscribingHandlerInterface $handler * * @return void */ public function registerSubscribingHandler(SubscribingHandlerInterface $handler); /** * Registers a handler in the registry. * * @param integer $direction one of the GraphNavigator::DIRECTION_??? constants * @param string $typeName * @param string $format * @param callable $handler function(VisitorInterface, mixed $data, array $type): mixed * * @return void */ public function registerHandler($direction, $typeName, $format, $handler); /** * @param integer $direction one of the GraphNavigator::DIRECTION_??? constants * @param string $typeName * @param string $format * * @return callable|null */ public function getHandler($direction, $typeName, $format); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Handler; use Symfony\Component\DependencyInjection\ContainerInterface; class LazyHandlerRegistry extends HandlerRegistry { private $container; private $initializedHandlers = array(); public function __construct(ContainerInterface $container, array $handlers = array()) { parent::__construct($handlers); $this->container = $container; } public function registerHandler($direction, $typeName, $format, $handler) { parent::registerHandler($direction, $typeName, $format, $handler); unset($this->initializedHandlers[$direction][$typeName][$format]); } public function getHandler($direction, $typeName, $format) { if (isset($this->initializedHandlers[$direction][$typeName][$format])) { return $this->initializedHandlers[$direction][$typeName][$format]; } if ( ! isset($this->handlers[$direction][$typeName][$format])) { return null; } $handler = $this->handlers[$direction][$typeName][$format]; if (is_array($handler) && is_string($handler[0]) && $this->container->has($handler[0])) { $handler[0] = $this->container->get($handler[0]); } return $this->initializedHandlers[$direction][$typeName][$format] = $handler; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Handler; use JMS\Serializer\Context; use JMS\Serializer\GraphNavigator; use JMS\Serializer\VisitorInterface; use PhpCollection\Map; use PhpCollection\Sequence; class PhpCollectionHandler implements SubscribingHandlerInterface { public static function getSubscribingMethods() { $methods = array(); $formats = array('json', 'xml', 'yml'); $collectionTypes = array( 'PhpCollection\Sequence' => 'Sequence', 'PhpCollection\Map' => 'Map', ); foreach ($collectionTypes as $type => $shortName) { foreach ($formats as $format) { $methods[] = array( 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, 'type' => $type, 'format' => $format, 'method' => 'serialize'.$shortName, ); $methods[] = array( 'direction' => GraphNavigator::DIRECTION_DESERIALIZATION, 'type' => $type, 'format' => $format, 'method' => 'deserialize'.$shortName, ); } } return $methods; } public function serializeMap(VisitorInterface $visitor, Map $map, array $type, Context $context) { $type['name'] = 'array'; return $visitor->visitArray(iterator_to_array($map), $type, $context); } public function deserializeMap(VisitorInterface $visitor, $data, array $type, Context $context) { $type['name'] = 'array'; return new Map($visitor->visitArray($data, $type, $context)); } public function serializeSequence(VisitorInterface $visitor, Sequence $sequence, array $type, Context $context) { // We change the base type, and pass through possible parameters. $type['name'] = 'array'; return $visitor->visitArray($sequence->all(), $type, $context); } public function deserializeSequence(VisitorInterface $visitor, $data, array $type, Context $context) { // See above. $type['name'] = 'array'; return new Sequence($visitor->visitArray($data, $type, $context)); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exclusion; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Context; class GroupsExclusionStrategy implements ExclusionStrategyInterface { const DEFAULT_GROUP = 'Default'; private $groups = array(); public function __construct(array $groups) { if (empty($groups)) { $groups = array(self::DEFAULT_GROUP); } foreach ($groups as $group) { $this->groups[$group] = true; } } /** * {@inheritDoc} */ public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext) { return false; } /** * {@inheritDoc} */ public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext) { if ( ! $property->groups) { return ! isset($this->groups[self::DEFAULT_GROUP]); } foreach ($property->groups as $group) { if (isset($this->groups[$group])) { return false; } } return true; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exclusion; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Context; /** * Interface for exclusion strategies. * * @author Johannes M. Schmitt */ interface ExclusionStrategyInterface { /** * Whether the class should be skipped. * * @param ClassMetadata $metadata * @param Context $navigatorContext * * @return boolean */ public function shouldSkipClass(ClassMetadata $metadata, Context $context); /** * Whether the property should be skipped. * * @param PropertyMetadata $property * @param Context $navigatorContext * * @return boolean */ public function shouldSkipProperty(PropertyMetadata $property, Context $context); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exclusion; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Context; class VersionExclusionStrategy implements ExclusionStrategyInterface { private $version; public function __construct($version) { $this->version = $version; } /** * {@inheritDoc} */ public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext) { return false; } /** * {@inheritDoc} */ public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext) { if ((null !== $version = $property->sinceVersion) && version_compare($this->version, $version, '<')) { return true; } if ((null !== $version = $property->untilVersion) && version_compare($this->version, $version, '>')) { return true; } return false; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exclusion; use JMS\Serializer\Context; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; use PhpCollection\Sequence; use PhpCollection\SequenceInterface; /** * Disjunct Exclusion Strategy. * * This strategy is short-circuiting and will skip a class, or property as soon as one of the delegates skips it. * * @author Johannes M. Schmitt */ class DisjunctExclusionStrategy implements ExclusionStrategyInterface { /** @var \PhpCollection\SequenceInterface */ private $delegates; /** * @param ExclusionStrategyInterface[]|SequenceInterface $delegates */ public function __construct($delegates) { if ( ! $delegates instanceof SequenceInterface) { $delegates = new Sequence($delegates); } $this->delegates = $delegates; } public function addStrategy(ExclusionStrategyInterface $strategy) { $this->delegates->add($strategy); } /** * Whether the class should be skipped. * * @param ClassMetadata $metadata * @param Context $navigatorContext * * @return boolean */ public function shouldSkipClass(ClassMetadata $metadata, Context $context) { foreach ($this->delegates as $delegate) { /** @var $delegate ExclusionStrategyInterface */ if ($delegate->shouldSkipClass($metadata, $context)) { return true; } } return false; } /** * Whether the property should be skipped. * * @param PropertyMetadata $property * @param Context $navigatorContext * * @return boolean */ public function shouldSkipProperty(PropertyMetadata $property, Context $context) { foreach ($this->delegates as $delegate) { /** @var $delegate ExclusionStrategyInterface */ if ($delegate->shouldSkipProperty($property, $context)) { return true; } } return false; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; /** * XmlSerializationVisitor. * * @author Johannes M. Schmitt */ class XmlSerializationVisitor extends AbstractVisitor { public $document; private $navigator; private $defaultRootName = 'result'; private $defaultVersion = '1.0'; private $defaultEncoding = 'UTF-8'; private $stack; private $metadataStack; private $currentNode; private $currentMetadata; private $hasValue; public function setDefaultRootName($name) { $this->defaultRootName = $name; } public function setDefaultVersion($version) { $this->defaultVersion = $version; } public function setDefaultEncoding($encoding) { $this->defaultEncoding = $encoding; } public function setNavigator(GraphNavigator $navigator) { $this->navigator = $navigator; $this->document = null; $this->stack = new \SplStack; $this->metadataStack = new \SplStack; } public function getNavigator() { return $this->navigator; } public function visitNull($data, array $type, Context $context) { if (null === $this->document) { $this->document = $this->createDocument(null, null, true); $node = $this->document->createAttribute('xsi:nil'); $node->value = 'true'; $this->currentNode->appendChild($node); return; } $node = $this->document->createAttribute('xsi:nil'); $node->value = 'true'; return $node; } public function visitString($data, array $type, Context $context) { if (null === $this->document) { $this->document = $this->createDocument(null, null, true); $this->currentNode->appendChild($this->document->createCDATASection($data)); return; } return $this->document->createCDATASection($data); } public function visitBoolean($data, array $type, Context $context) { if (null === $this->document) { $this->document = $this->createDocument(null, null, true); $this->currentNode->appendChild($this->document->createTextNode($data ? 'true' : 'false')); return; } return $this->document->createTextNode($data ? 'true' : 'false'); } public function visitInteger($data, array $type, Context $context) { return $this->visitNumeric($data, $type); } public function visitDouble($data, array $type, Context $context) { return $this->visitNumeric($data, $type); } public function visitArray($data, array $type, Context $context) { if (null === $this->document) { $this->document = $this->createDocument(null, null, true); } $entryName = (null !== $this->currentMetadata && null !== $this->currentMetadata->xmlEntryName) ? $this->currentMetadata->xmlEntryName : 'entry'; $keyAttributeName = (null !== $this->currentMetadata && null !== $this->currentMetadata->xmlKeyAttribute) ? $this->currentMetadata->xmlKeyAttribute : null; foreach ($data as $k => $v) { $tagName = (null !== $this->currentMetadata && $this->currentMetadata->xmlKeyValuePairs && $this->isElementNameValid($k)) ? $k : $entryName; $entryNode = $this->document->createElement($tagName); $this->currentNode->appendChild($entryNode); $this->setCurrentNode($entryNode); if (null !== $keyAttributeName) { $entryNode->setAttribute($keyAttributeName, (string) $k); } if (null !== $node = $this->navigator->accept($v, isset($type['params'][1]) ? $type['params'][1] : null, $context)) { $this->currentNode->appendChild($node); } $this->revertCurrentNode(); } } public function startVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) { if (null === $this->document) { $this->document = $this->createDocument(null, null, false); $this->document->appendChild($this->currentNode = $this->document->createElement($metadata->xmlRootName ?: $this->defaultRootName)); } $this->hasValue = false; } public function visitProperty(PropertyMetadata $metadata, $object, Context $context) { $v = $metadata->getValue($object); if (null === $v && !$context->shouldSerializeNull()) { return; } if ($metadata->xmlAttribute) { $node = $this->navigator->accept($v, $metadata->type, $context); if (!$node instanceof \DOMCharacterData) { throw new RuntimeException(sprintf('Unsupported value for XML attribute. Expected character data, but got %s.', json_encode($v))); } $this->currentNode->setAttribute($this->namingStrategy->translateName($metadata), $node->nodeValue); return; } if (($metadata->xmlValue && $this->currentNode->childNodes->length > 0) || (!$metadata->xmlValue && $this->hasValue)) { throw new RuntimeException(sprintf('If you make use of @XmlValue, all other properties in the class must have the @XmlAttribute annotation. Invalid usage detected in class %s.', $metadata->class)); } if ($metadata->xmlValue) { $this->hasValue = true; $node = $this->navigator->accept($v, $metadata->type, $context); if (!$node instanceof \DOMCharacterData) { throw new RuntimeException(sprintf('Unsupported value for property %s::$%s. Expected character data, but got %s.', $metadata->reflection->class, $metadata->reflection->name, is_object($node) ? get_class($node) : gettype($node))); } $this->currentNode->appendChild($node); return; } if ($metadata->xmlAttributeMap) { if (!is_array($v)) { throw new RuntimeException(sprintf('Unsupported value type for XML attribute map. Expected array but got %s.', gettype($v))); } foreach ($v as $key => $value) { $node = $this->navigator->accept($value, null, $context); if (!$node instanceof \DOMCharacterData) { throw new RuntimeException(sprintf('Unsupported value for a XML attribute map value. Expected character data, but got %s.', json_encode($v))); } $this->currentNode->setAttribute($key, $node->nodeValue); } return; } if ($addEnclosingElement = (!$metadata->xmlCollection || !$metadata->xmlCollectionInline) && !$metadata->inline) { $element = $this->document->createElement($this->namingStrategy->translateName($metadata)); $this->setCurrentNode($element); } $this->setCurrentMetadata($metadata); if (null !== $node = $this->navigator->accept($v, $metadata->type, $context)) { $this->currentNode->appendChild($node); } $this->revertCurrentMetadata(); if ($addEnclosingElement) { $this->revertCurrentNode(); if ($element->hasChildNodes() || $element->hasAttributes() || (isset($metadata->type['name']) && $metadata->type['name'] === 'array' && isset($metadata->type['params'][1]))) { $this->currentNode->appendChild($element); } } $this->hasValue = false; } public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) { } public function getResult() { return $this->document->saveXML(); } public function getCurrentNode() { return $this->currentNode; } public function getCurrentMetadata() { return $this->currentMetadata; } public function getDocument() { return $this->document; } public function setCurrentMetadata(PropertyMetadata $metadata) { $this->metadataStack->push($this->currentMetadata); $this->currentMetadata = $metadata; } public function setCurrentNode(\DOMNode $node) { $this->stack->push($this->currentNode); $this->currentNode = $node; } public function revertCurrentNode() { return $this->currentNode = $this->stack->pop(); } public function revertCurrentMetadata() { return $this->currentMetadata = $this->metadataStack->pop(); } public function createDocument($version = null, $encoding = null, $addRoot = true) { $doc = new \DOMDocument($version ?: $this->defaultVersion, $encoding ?: $this->defaultEncoding); $doc->formatOutput = true; if ($addRoot) { $this->setCurrentNode($rootNode = $doc->createElement($this->defaultRootName)); $doc->appendChild($rootNode); } return $doc; } private function visitNumeric($data, array $type) { if (null === $this->document) { $this->document = $this->createDocument(null, null, true); $this->currentNode->appendChild($textNode = $this->document->createTextNode((string) $data)); return $textNode; } return $this->document->createTextNode((string) $data); } /** * Checks that the name is a valid XML element name. * * @param string $name * * @return boolean */ private function isElementNameValid($name) { return $name && false === strpos($name, ' ') && preg_match('#^[\pL_][\pL0-9._-]*$#ui', $name); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Twig; use JMS\Serializer\SerializerInterface; use JMS\Serializer\SerializationContext; /** * Serializer helper twig extension * * Basically provides access to JMSSerializer from Twig */ class SerializerExtension extends \Twig_Extension { protected $serializer; public function getName() { return 'jms_serializer'; } public function __construct(SerializerInterface $serializer) { $this->serializer = $serializer; } public function getFilters() { return array( 'serialize' => new \Twig_Filter_Method($this, 'serialize'), ); } public function getFunctions() { return array( 'serialization_context' => new \Twig_Function_Method($this, 'createContext'), ); } /** * Creates the serialization context * * @return SerializationContext */ public function createContext() { return SerializationContext::create(); } /** * @param object $object * @param string $type * @param SerializationContext $context */ public function serialize($object, $type = 'json', SerializationContext $context = null) { return $this->serializer->serialize($object, $type, $context); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use Symfony\Component\Yaml\Inline; use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Naming\PropertyNamingStrategyInterface; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Util\Writer; /** * Serialization Visitor for the YAML format. * * @see http://www.yaml.org/spec/ * @author Johannes M. Schmitt */ class YamlSerializationVisitor extends AbstractVisitor { public $writer; private $navigator; private $stack; private $metadataStack; private $currentMetadata; public function __construct(PropertyNamingStrategyInterface $namingStrategy) { parent::__construct($namingStrategy); $this->writer = new Writer(); } public function prepare($data) { return $data; } public function setNavigator(GraphNavigator $navigator) { $this->navigator = $navigator; $this->writer->reset(); $this->stack = new \SplStack; $this->metadataStack = new \SplStack; } public function visitNull($data, array $type, Context $context) { if ('' === $this->writer->content) { $this->writer->writeln('null'); } return 'null'; } public function visitString($data, array $type, Context $context) { $v = Inline::dump($data); if ('' === $this->writer->content) { $this->writer->writeln($v); } return $v; } /** * @param array $data * @param array $type */ public function visitArray($data, array $type, Context $context) { $count = $this->writer->changeCount; $isList = array_keys($data) === range(0, count($data) - 1); foreach ($data as $k => $v) { if (null === $v && (!is_string($k) || ! $context->shouldSerializeNull())) { continue; } if ($isList) { $this->writer->writeln('-'); } else { $this->writer->writeln(Inline::dump($k).':'); } $this->writer->indent(); if (null !== $v = $this->navigator->accept($v, null, $context)) { $this->writer ->rtrim(false) ->writeln(' '.$v) ; } $this->writer->outdent(); } if ($count === $this->writer->changeCount && isset($type['params'][1])) { $this->writer ->rtrim(false) ->writeln(' {}') ; } } public function visitBoolean($data, array $type, Context $context) { $v = $data ? 'true' : 'false'; if ('' === $this->writer->content) { $this->writer->writeln($v); } return $v; } public function visitDouble($data, array $type, Context $context) { $v = (string) $data; if ('' === $this->writer->content) { $this->writer->writeln($v); } return $v; } public function visitInteger($data, array $type, Context $context) { $v = (string) $data; if ('' === $this->writer->content) { $this->writer->writeln($v); } return $v; } public function startVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) { } public function visitProperty(PropertyMetadata $metadata, $data, Context $context) { $v = $metadata->getValue($data); if (null === $v && !$context->shouldSerializeNull()) { return; } $name = $this->namingStrategy->translateName($metadata); if (!$metadata->inline) { $this->writer ->writeln(Inline::dump($name).':') ->indent(); } $this->setCurrentMetadata($metadata); $count = $this->writer->changeCount; if (null !== $v = $this->navigator->accept($v, $metadata->type, $context)) { $this->writer ->rtrim(false) ->writeln(' '.$v) ; } elseif ($count === $this->writer->changeCount) { $this->writer->revert(); } if (!$metadata->inline) { $this->writer->outdent(); } $this->revertCurrentMetadata(); } public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) { } public function setCurrentMetadata(PropertyMetadata $metadata) { $this->metadataStack->push($this->currentMetadata); $this->currentMetadata = $metadata; } public function revertCurrentMetadata() { return $this->currentMetadata = $this->metadataStack->pop(); } public function getNavigator() { return $this->navigator; } public function getResult() { return $this->writer->getContent(); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Exception\XmlErrorException; use JMS\Serializer\Exception\LogicException; use JMS\Serializer\Exception\InvalidArgumentException; use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\Metadata\PropertyMetadata; use JMS\Serializer\Metadata\ClassMetadata; class XmlDeserializationVisitor extends AbstractVisitor { private $objectStack; private $metadataStack; private $currentObject; private $currentMetadata; private $result; private $navigator; private $disableExternalEntities = true; private $doctypeWhitelist = array(); public function enableExternalEntities() { $this->disableExternalEntities = false; } public function setNavigator(GraphNavigator $navigator) { $this->navigator = $navigator; $this->objectStack = new \SplStack; $this->metadataStack = new \SplStack; $this->result = null; } public function getNavigator() { return $this->navigator; } public function prepare($data) { $previous = libxml_use_internal_errors(true); $previousEntityLoaderState = libxml_disable_entity_loader($this->disableExternalEntities); $dom = new \DOMDocument(); $dom->loadXML($data); foreach ($dom->childNodes as $child) { if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { $internalSubset = str_replace(array("\n", "\r"), '', $child->internalSubset); if (!in_array($internalSubset, $this->doctypeWhitelist, true)) { throw new InvalidArgumentException(sprintf( 'The document type "%s" is not allowed. If it is safe, you may add it to the whitelist configuration.', $internalSubset )); } } } $doc = simplexml_load_string($data); libxml_use_internal_errors($previous); libxml_disable_entity_loader($previousEntityLoaderState); if (false === $doc) { throw new XmlErrorException(libxml_get_last_error()); } return $doc; } public function visitNull($data, array $type, Context $context) { return null; } public function visitString($data, array $type, Context $context) { $data = (string) $data; if (null === $this->result) { $this->result = $data; } return $data; } public function visitBoolean($data, array $type, Context $context) { $data = (string) $data; if ('true' === $data) { $data = true; } elseif ('false' === $data) { $data = false; } else { throw new RuntimeException(sprintf('Could not convert data to boolean. Expected "true", or "false", but got %s.', json_encode($data))); } if (null === $this->result) { $this->result = $data; } return $data; } public function visitInteger($data, array $type, Context $context) { $data = (integer) $data; if (null === $this->result) { $this->result = $data; } return $data; } public function visitDouble($data, array $type, Context $context) { $data = (double) $data; if (null === $this->result) { $this->result = $data; } return $data; } public function visitArray($data, array $type, Context $context) { $entryName = null !== $this->currentMetadata && $this->currentMetadata->xmlEntryName ? $this->currentMetadata->xmlEntryName : 'entry'; if ( ! isset($data->$entryName)) { if (null === $this->result) { return $this->result = array(); } return array(); } switch (count($type['params'])) { case 0: throw new RuntimeException(sprintf('The array type must be specified either as "array", or "array".')); case 1: $result = array(); if (null === $this->result) { $this->result = &$result; } foreach ($data->$entryName as $v) { $result[] = $this->navigator->accept($v, $type['params'][0], $context); } return $result; case 2: if (null === $this->currentMetadata) { throw new RuntimeException('Maps are not supported on top-level without metadata.'); } list($keyType, $entryType) = $type['params']; $result = array(); if (null === $this->result) { $this->result = &$result; } foreach ($data->$entryName as $v) { if (!isset($v[$this->currentMetadata->xmlKeyAttribute])) { throw new RuntimeException(sprintf('The key attribute "%s" must be set for each entry of the map.', $this->currentMetadata->xmlKeyAttribute)); } $k = $this->navigator->accept($v[$this->currentMetadata->xmlKeyAttribute], $keyType, $context); $result[$k] = $this->navigator->accept($v, $entryType, $context); } return $result; default: throw new LogicException(sprintf('The array type does not support more than 2 parameters, but got %s.', json_encode($type['params']))); } } public function startVisitingObject(ClassMetadata $metadata, $object, array $type, Context $context) { $this->setCurrentObject($object); if (null === $this->result) { $this->result = $this->currentObject; } } public function visitProperty(PropertyMetadata $metadata, $data, Context $context) { $name = $this->namingStrategy->translateName($metadata); if (!$metadata->type) { throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->class, $metadata->name)); } if ($metadata->xmlAttribute) { if (isset($data[$name])) { $v = $this->navigator->accept($data[$name], $metadata->type, $context); $metadata->reflection->setValue($this->currentObject, $v); } return; } if ($metadata->xmlValue) { $v = $this->navigator->accept($data, $metadata->type, $context); $metadata->reflection->setValue($this->currentObject, $v); return; } if ($metadata->xmlCollection) { $enclosingElem = $data; if (!$metadata->xmlCollectionInline && isset($data->$name)) { $enclosingElem = $data->$name; } $this->setCurrentMetadata($metadata); $v = $this->navigator->accept($enclosingElem, $metadata->type, $context); $this->revertCurrentMetadata(); $metadata->reflection->setValue($this->currentObject, $v); return; } if (!isset($data->$name)) { return; } $v = $this->navigator->accept($data->$name, $metadata->type, $context); if (null === $metadata->setter) { $metadata->reflection->setValue($this->currentObject, $v); return; } $this->currentObject->{$metadata->setter}($v); } public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context) { $rs = $this->currentObject; $this->revertCurrentObject(); return $rs; } public function setCurrentObject($object) { $this->objectStack->push($this->currentObject); $this->currentObject = $object; } public function getCurrentObject() { return $this->currentObject; } public function revertCurrentObject() { return $this->currentObject = $this->objectStack->pop(); } public function setCurrentMetadata(PropertyMetadata $metadata) { $this->metadataStack->push($this->currentMetadata); $this->currentMetadata = $metadata; } public function getCurrentMetadata() { return $this->currentMetadata; } public function revertCurrentMetadata() { return $this->currentMetadata = $this->metadataStack->pop(); } public function getResult() { return $this->result; } /** * @param array $doctypeWhitelist */ public function setDoctypeWhitelist(array $doctypeWhitelist) { $this->doctypeWhitelist = $doctypeWhitelist; } /** * @return array */ public function getDoctypeWhitelist() { return $this->doctypeWhitelist; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\EventDispatcher\ObjectEvent; use JMS\Serializer\EventDispatcher\PreDeserializeEvent; use JMS\Serializer\EventDispatcher\PreSerializeEvent; use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\Construction\ObjectConstructorInterface; use JMS\Serializer\Handler\HandlerRegistryInterface; use JMS\Serializer\EventDispatcher\EventDispatcherInterface; use JMS\Serializer\Metadata\ClassMetadata; use Metadata\MetadataFactoryInterface; use JMS\Serializer\Exception\InvalidArgumentException; /** * Handles traversal along the object graph. * * This class handles traversal along the graph, and calls different methods * on visitors, or custom handlers to process its nodes. * * @author Johannes M. Schmitt */ final class GraphNavigator { const DIRECTION_SERIALIZATION = 1; const DIRECTION_DESERIALIZATION = 2; private $dispatcher; private $metadataFactory; private $handlerRegistry; private $objectConstructor; /** * Parses a direction string to one of the direction constants. * * @param string $dirStr * * @return integer */ public static function parseDirection($dirStr) { switch (strtolower($dirStr)) { case 'serialization': return self::DIRECTION_SERIALIZATION; case 'deserialization': return self::DIRECTION_DESERIALIZATION; default: throw new InvalidArgumentException(sprintf('The direction "%s" does not exist.', $dirStr)); } } public function __construct(MetadataFactoryInterface $metadataFactory, HandlerRegistryInterface $handlerRegistry, ObjectConstructorInterface $objectConstructor, EventDispatcherInterface $dispatcher = null) { $this->dispatcher = $dispatcher; $this->metadataFactory = $metadataFactory; $this->handlerRegistry = $handlerRegistry; $this->objectConstructor = $objectConstructor; } /** * Called for each node of the graph that is being traversed. * * @param mixed $data the data depends on the direction, and type of visitor * @param null|array $type array has the format ["name" => string, "params" => array] * @param VisitorInterface $visitor * * @return mixed the return value depends on the direction, and type of visitor */ public function accept($data, array $type = null, Context $context) { $visitor = $context->getVisitor(); // If the type was not given, we infer the most specific type from the // input data in serialization mode. if (null === $type) { if ($context instanceof DeserializationContext) { throw new RuntimeException('The type must be given for all properties when deserializing.'); } $typeName = gettype($data); if ('object' === $typeName) { $typeName = get_class($data); } $type = array('name' => $typeName, 'params' => array()); } // If the data is null, we have to force the type to null regardless of the input in order to // guarantee correct handling of null values, and not have any internal auto-casting behavior. else if ($context instanceof SerializationContext && null === $data) { $type = array('name' => 'NULL', 'params' => array()); } switch ($type['name']) { case 'NULL': return $visitor->visitNull($data, $type, $context); case 'string': return $visitor->visitString($data, $type, $context); case 'integer': return $visitor->visitInteger($data, $type, $context); case 'boolean': return $visitor->visitBoolean($data, $type, $context); case 'double': case 'float': return $visitor->visitDouble($data, $type, $context); case 'array': return $visitor->visitArray($data, $type, $context); case 'resource': $msg = 'Resources are not supported in serialized data.'; if ($context instanceof SerializationContext && null !== $path = $context->getPath()) { $msg .= ' Path: '.$path; } throw new RuntimeException($msg); default: // TODO: The rest of this method needs some refactoring. if ($context instanceof SerializationContext) { if (null !== $data) { if ($context->isVisiting($data)) { return null; } $context->startVisiting($data); } } elseif ($context instanceof DeserializationContext) { $context->increaseDepth(); } // Trigger pre-serialization callbacks, and listeners if they exist. // Dispatch pre-serialization event before handling data to have ability change type in listener if ($context instanceof SerializationContext) { if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.pre_serialize', $type['name'], $context->getFormat())) { $this->dispatcher->dispatch('serializer.pre_serialize', $type['name'], $context->getFormat(), $event = new PreSerializeEvent($context, $data, $type)); $type = $event->getType(); } } elseif ($context instanceof DeserializationContext) { if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.pre_deserialize', $type['name'], $context->getFormat())) { $this->dispatcher->dispatch('serializer.pre_deserialize', $type['name'], $context->getFormat(), $event = new PreDeserializeEvent($context, $data, $type)); $type = $event->getType(); $data = $event->getData(); } } // First, try whether a custom handler exists for the given type. This is done // before loading metadata because the type name might not be a class, but // could also simply be an artifical type. if (null !== $handler = $this->handlerRegistry->getHandler($context->getDirection(), $type['name'], $context->getFormat())) { $rs = call_user_func($handler, $visitor, $data, $type, $context); $this->leaveScope($context, $data); return $rs; } $exclusionStrategy = $context->getExclusionStrategy(); /** @var $metadata ClassMetadata */ $metadata = $this->metadataFactory->getMetadataForClass($type['name']); if ($context instanceof DeserializationContext && ! empty($metadata->discriminatorMap) && $type['name'] === $metadata->discriminatorBaseClass) { $metadata = $this->resolveMetadata($context, $data, $metadata); } if (null !== $exclusionStrategy && $exclusionStrategy->shouldSkipClass($metadata, $context)) { $this->leaveScope($context, $data); return null; } $context->pushClassMetadata($metadata); if ($context instanceof SerializationContext) { foreach ($metadata->preSerializeMethods as $method) { $method->invoke($data); } } $object = $data; if ($context instanceof DeserializationContext) { $object = $this->objectConstructor->construct($visitor, $metadata, $data, $type); } if (isset($metadata->handlerCallbacks[$context->getDirection()][$context->getFormat()])) { $rs = $object->{$metadata->handlerCallbacks[$context->getDirection()][$context->getFormat()]}( $visitor, $context instanceof SerializationContext ? null : $data, $context ); $this->afterVisitingObject($metadata, $object, $type, $context); return $context instanceof SerializationContext ? $rs : $object; } $visitor->startVisitingObject($metadata, $object, $type, $context); foreach ($metadata->propertyMetadata as $propertyMetadata) { if (null !== $exclusionStrategy && $exclusionStrategy->shouldSkipProperty($propertyMetadata, $context)) { continue; } if ($context instanceof DeserializationContext && $propertyMetadata->readOnly) { continue; } $context->pushPropertyMetadata($propertyMetadata); $visitor->visitProperty($propertyMetadata, $data, $context); $context->popPropertyMetadata(); } if ($context instanceof SerializationContext) { $this->afterVisitingObject($metadata, $data, $type, $context); return $visitor->endVisitingObject($metadata, $data, $type, $context); } $rs = $visitor->endVisitingObject($metadata, $data, $type, $context); $this->afterVisitingObject($metadata, $rs, $type, $context); return $rs; } } private function resolveMetadata(DeserializationContext $context, $data, ClassMetadata $metadata) { switch (true) { case is_array($data) && isset($data[$metadata->discriminatorFieldName]): $typeValue = (string) $data[$metadata->discriminatorFieldName]; break; case is_object($data) && isset($data->{$metadata->discriminatorFieldName}): $typeValue = (string) $data->{$metadata->discriminatorFieldName}; break; default: throw new \LogicException(sprintf( 'The discriminator field name "%s" for base-class "%s" was not found in input data.', $metadata->discriminatorFieldName, $metadata->name )); } if ( ! isset($metadata->discriminatorMap[$typeValue])) { throw new \LogicException(sprintf( 'The type value "%s" does not exist in the discriminator map of class "%s". Available types: %s', $typeValue, $metadata->name, implode(', ', array_keys($metadata->discriminatorMap)) )); } return $this->metadataFactory->getMetadataForClass($metadata->discriminatorMap[$typeValue]); } private function leaveScope(Context $context, $data) { if ($context instanceof SerializationContext) { $context->stopVisiting($data); } elseif ($context instanceof DeserializationContext) { $context->decreaseDepth(); } } private function afterVisitingObject(ClassMetadata $metadata, $object, array $type, Context $context) { $this->leaveScope($context, $object); $context->popClassMetadata(); if ($context instanceof SerializationContext) { foreach ($metadata->postSerializeMethods as $method) { $method->invoke($object); } if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.post_serialize', $metadata->name, $context->getFormat())) { $this->dispatcher->dispatch('serializer.post_serialize', $metadata->name, $context->getFormat(), new ObjectEvent($context, $object, $type)); } return; } foreach ($metadata->postDeserializeMethods as $method) { $method->invoke($object); } if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.post_deserialize', $metadata->name, $context->getFormat())) { $this->dispatcher->dispatch('serializer.post_deserialize', $metadata->name, $context->getFormat(), new ObjectEvent($context, $object, $type)); } } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exception; use Symfony\Component\Validator\ConstraintViolationList; class ValidationFailedException extends RuntimeException { private $list; public function __construct(ConstraintViolationList $list) { parent::__construct(sprintf('Validation failed with %d error(s).', count($list))); $this->list = $list; } public function getConstraintViolationList() { return $this->list; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exception; /** * Base exception for the Serializer. * * @author Johannes M. Schmitt */ interface Exception { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exception; class XmlErrorException extends RuntimeException { private $xmlError; public function __construct(\LibXMLError $error) { switch ($error->level) { case LIBXML_ERR_WARNING: $level = 'WARNING'; break; case LIBXML_ERR_FATAL: $level = 'FATAL'; break; case LIBXML_ERR_ERROR: $level = 'ERROR'; break; default: $level = 'UNKNOWN'; } parent::__construct(sprintf('[%s] %s in %s (line: %d, column: %d)', $level, $error->message, $error->file, $error->line, $error->column)); $this->xmlError = $error; } public function getXmlError() { return $this->xmlError; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exception; class UnsupportedFormatException extends InvalidArgumentException { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exception; /** * InvalidArgumentException for the Serializer. * * @author Johannes M. Schmitt */ class InvalidArgumentException extends \InvalidArgumentException implements Exception { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exception; /** * LogicException for the Serializer. * * @author Johannes M. Schmitt */ class LogicException extends \LogicException implements Exception { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Exception; /** * RuntimeException for the Serializer. * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements Exception { } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; /** * Interface for visitors. * * This contains the minimal set of values that must be supported for any * output format. * * @author Johannes M. Schmitt */ interface VisitorInterface { /** * Allows visitors to convert the input data to a different representation * before the actual serialization/deserialization process starts. * * @param mixed $data * * @return mixed */ public function prepare($data); /** * @param mixed $data * @param array $type * * @return mixed */ public function visitNull($data, array $type, Context $context); /** * @param mixed $data * @param array $type * * @return mixed */ public function visitString($data, array $type, Context $context); /** * @param mixed $data * @param array $type * * @return mixed */ public function visitBoolean($data, array $type, Context $context); /** * @param mixed $data * @param array $type * * @return mixed */ public function visitDouble($data, array $type, Context $context); /** * @param mixed $data * @param array $type * * @return mixed */ public function visitInteger($data, array $type, Context $context); /** * @param mixed $data * @param array $type * * @return mixed */ public function visitArray($data, array $type, Context $context); /** * Called before the properties of the object are being visited. * * @param ClassMetadata $metadata * @param mixed $data * @param array $type * * @return void */ public function startVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context); /** * @param PropertyMetadata $metadata * @param mixed $data * * @return void */ public function visitProperty(PropertyMetadata $metadata, $data, Context $context); /** * Called after all properties of the object have been visited. * * @param ClassMetadata $metadata * @param mixed $data * @param array $type * * @return mixed */ public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context); /** * Called before serialization/deserialization starts. * * @param GraphNavigator $navigator * * @return void */ public function setNavigator(GraphNavigator $navigator); /** * @deprecated use Context::getNavigator/Context::accept instead * @return GraphNavigator */ public function getNavigator(); /** * @return object|array|scalar */ public function getResult(); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Construction; use Doctrine\Common\Persistence\ManagerRegistry; use JMS\Serializer\VisitorInterface; use JMS\Serializer\Metadata\ClassMetadata; /** * Doctrine object constructor for new (or existing) objects during deserialization. */ class DoctrineObjectConstructor implements ObjectConstructorInterface { private $managerRegistry; private $fallbackConstructor; /** * Constructor. * * @param ManagerRegistry $managerRegistry Manager registry * @param ObjectConstructorInterface $fallbackConstructor Fallback object constructor */ public function __construct(ManagerRegistry $managerRegistry, ObjectConstructorInterface $fallbackConstructor) { $this->managerRegistry = $managerRegistry; $this->fallbackConstructor = $fallbackConstructor; } /** * {@inheritdoc} */ public function construct(VisitorInterface $visitor, ClassMetadata $metadata, $data, array $type) { // Locate possible ObjectManager $objectManager = $this->managerRegistry->getManagerForClass($metadata->name); if (!$objectManager) { // No ObjectManager found, proceed with normal deserialization return $this->fallbackConstructor->construct($visitor, $metadata, $data, $type); } // Locate possible ClassMetadata $classMetadataFactory = $objectManager->getMetadataFactory(); if ($classMetadataFactory->isTransient($metadata->name)) { // No ClassMetadata found, proceed with normal deserialization return $this->fallbackConstructor->construct($visitor, $metadata, $data, $type); } // Managed entity, check for proxy load if (!is_array($data)) { // Single identifier, load proxy return $objectManager->getReference($metadata->name, $data); } // Fallback to default constructor if missing identifier(s) $classMetadata = $objectManager->getClassMetadata($metadata->name); $identifierList = array(); foreach ($classMetadata->getIdentifierFieldNames() as $name) { if ( ! array_key_exists($name, $data)) { return $this->fallbackConstructor->construct($visitor, $metadata, $data, $type); } $identifierList[$name] = $data[$name]; } // Entity update, load it from database $object = $objectManager->find($metadata->name, $identifierList); $objectManager->initializeObject($object); return $object; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Construction; use JMS\Serializer\VisitorInterface; use JMS\Serializer\Metadata\ClassMetadata; /** * Implementations of this interface construct new objects during deserialization. * * @author Johannes M. Schmitt */ interface ObjectConstructorInterface { /** * Constructs a new object. * * Implementations could for example create a new object calling "new", use * "unserialize" techniques, reflection, or other means. * * @param VisitorInterface $visitor * @param ClassMetadata $metadata * @param mixed $data * @param array $type ["name" => string, "params" => array] * * @return object */ public function construct(VisitorInterface $visitor, ClassMetadata $metadata, $data, array $type); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer\Construction; use JMS\Serializer\VisitorInterface; use JMS\Serializer\Metadata\ClassMetadata; class UnserializeObjectConstructor implements ObjectConstructorInterface { public function construct(VisitorInterface $visitor, ClassMetadata $metadata, $data, array $type) { return unserialize(sprintf('O:%d:"%s":0:{}', strlen($metadata->name), $metadata->name)); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace JMS\Serializer; /** * Parses a serializer type. * * @author Johannes M. Schmitt */ final class TypeParser extends \JMS\Parser\AbstractParser { const T_NAME = 1; const T_STRING = 2; const T_OPEN_BRACKET = 3; const T_CLOSE_BRACKET = 4; const T_COMMA = 5; const T_NONE = 6; public function __construct() { parent::__construct(new \JMS\Parser\SimpleLexer( '/ # PHP Class Names ((?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*) # Strings |("(?:[^"]|"")*"|\'(?:[^\']|\'\')*\') # Ignore whitespace |\s* # Terminals |(.) /x', array(self::T_NAME => 'T_NAME', self::T_STRING => 'T_STRING', self::T_OPEN_BRACKET => 'T_OPEN_BRACKET', self::T_CLOSE_BRACKET => 'T_CLOSE_BRACKET', self::T_COMMA => 'T_COMMA', self::T_NONE => 'T_NONE'), function($value) { switch ($value[0]) { case '"': case "'": return array(TypeParser::T_STRING, substr($value, 1, -1)); case '<': return array(TypeParser::T_OPEN_BRACKET, '<'); case '>': return array(TypeParser::T_CLOSE_BRACKET, '>'); case ',': return array(TypeParser::T_COMMA, ','); default: if (preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $value)) { return array(TypeParser::T_NAME, $value); } return array(TypeParser::T_NONE, $value); } } )); } /** * @return array of the format ["name" => string, "params" => array] */ protected function parseInternal() { $typeName = $this->match(self::T_NAME); if ( ! $this->lexer->isNext(self::T_OPEN_BRACKET)) { return array('name' => $typeName, 'params' => array()); } $this->match(self::T_OPEN_BRACKET); $params = array(); do { if ($this->lexer->isNext(self::T_NAME)) { $params[] = $this->parseInternal(); } else if ($this->lexer->isNext(self::T_STRING)) { $params[] = $this->match(self::T_STRING); } else { $this->matchAny(array(self::T_NAME, self::T_STRING)); // Will throw an exception. } } while ($this->lexer->isNext(self::T_COMMA) && $this->lexer->moveNext()); $this->match(self::T_CLOSE_BRACKET); return array('name' => $typeName, 'params' => $params); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; use Monolog\Handler\HandlerInterface; use Monolog\Handler\StreamHandler; use Psr\Log\LoggerInterface; use Psr\Log\InvalidArgumentException; /** * Monolog log channel * * It contains a stack of Handlers and a stack of Processors, * and uses them to store records that are added to it. * * @author Jordi Boggiano */ class Logger implements LoggerInterface { /** * Detailed debug information */ const DEBUG = 100; /** * Interesting events * * Examples: User logs in, SQL logs. */ const INFO = 200; /** * Uncommon events */ const NOTICE = 250; /** * Exceptional occurrences that are not errors * * Examples: Use of deprecated APIs, poor use of an API, * undesirable things that are not necessarily wrong. */ const WARNING = 300; /** * Runtime errors */ const ERROR = 400; /** * Critical conditions * * Example: Application component unavailable, unexpected exception. */ const CRITICAL = 500; /** * Action must be taken immediately * * Example: Entire website down, database unavailable, etc. * This should trigger the SMS alerts and wake you up. */ const ALERT = 550; /** * Urgent alert. */ const EMERGENCY = 600; /** * Monolog API version * * This is only bumped when API breaks are done and should * follow the major version of the library * * @var int */ const API = 1; /** * Logging levels from syslog protocol defined in RFC 5424 * * @var array $levels Logging levels */ protected static $levels = array( self::DEBUG => 'DEBUG', self::INFO => 'INFO', self::NOTICE => 'NOTICE', self::WARNING => 'WARNING', self::ERROR => 'ERROR', self::CRITICAL => 'CRITICAL', self::ALERT => 'ALERT', self::EMERGENCY => 'EMERGENCY', ); /** * @var \DateTimeZone */ protected static $timezone; /** * @var string */ protected $name; /** * The handler stack * * @var HandlerInterface[] */ protected $handlers; /** * Processors that will process all log records * * To process records of a single handler instead, add the processor on that specific handler * * @var callable[] */ protected $processors; /** * @var bool */ protected $microsecondTimestamps = true; /** * @param string $name The logging channel * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc. * @param callable[] $processors Optional array of processors */ public function __construct($name, array $handlers = array(), array $processors = array()) { $this->name = $name; $this->handlers = $handlers; $this->processors = $processors; } /** * @return string */ public function getName() { return $this->name; } /** * Return a new cloned instance with the name changed * * @return static */ public function withName($name) { $new = clone $this; $new->name = $name; return $new; } /** * Pushes a handler on to the stack. * * @param HandlerInterface $handler * @return $this */ public function pushHandler(HandlerInterface $handler) { array_unshift($this->handlers, $handler); return $this; } /** * Pops a handler from the stack * * @return HandlerInterface */ public function popHandler() { if (!$this->handlers) { throw new \LogicException('You tried to pop from an empty handler stack.'); } return array_shift($this->handlers); } /** * Set handlers, replacing all existing ones. * * If a map is passed, keys will be ignored. * * @param HandlerInterface[] $handlers * @return $this */ public function setHandlers(array $handlers) { $this->handlers = array(); foreach (array_reverse($handlers) as $handler) { $this->pushHandler($handler); } return $this; } /** * @return HandlerInterface[] */ public function getHandlers() { return $this->handlers; } /** * Adds a processor on to the stack. * * @param callable $callback * @return $this */ public function pushProcessor($callback) { if (!is_callable($callback)) { throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given'); } array_unshift($this->processors, $callback); return $this; } /** * Removes the processor on top of the stack and returns it. * * @return callable */ public function popProcessor() { if (!$this->processors) { throw new \LogicException('You tried to pop from an empty processor stack.'); } return array_shift($this->processors); } /** * @return callable[] */ public function getProcessors() { return $this->processors; } /** * Control the use of microsecond resolution timestamps in the 'datetime' * member of new records. * * Generating microsecond resolution timestamps by calling * microtime(true), formatting the result via sprintf() and then parsing * the resulting string via \DateTime::createFromFormat() can incur * a measurable runtime overhead vs simple usage of DateTime to capture * a second resolution timestamp in systems which generate a large number * of log events. * * @param bool $micro True to use microtime() to create timestamps */ public function useMicrosecondTimestamps($micro) { $this->microsecondTimestamps = (bool) $micro; } /** * Adds a log record. * * @param int $level The logging level * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function addRecord($level, $message, array $context = array()) { if (!$this->handlers) { $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG)); } $levelName = static::getLevelName($level); // check if any handler will handle this message so we can return early and save cycles $handlerKey = null; reset($this->handlers); while ($handler = current($this->handlers)) { if ($handler->isHandling(array('level' => $level))) { $handlerKey = key($this->handlers); break; } next($this->handlers); } if (null === $handlerKey) { return false; } if (!static::$timezone) { static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC'); } if ($this->microsecondTimestamps) { $ts = \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone); } else { $ts = new \DateTime(null, static::$timezone); } $ts->setTimezone(static::$timezone); $record = array( 'message' => (string) $message, 'context' => $context, 'level' => $level, 'level_name' => $levelName, 'channel' => $this->name, 'datetime' => $ts, 'extra' => array(), ); foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } while ($handler = current($this->handlers)) { if (true === $handler->handle($record)) { break; } next($this->handlers); } return true; } /** * Adds a log record at the DEBUG level. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function addDebug($message, array $context = array()) { return $this->addRecord(static::DEBUG, $message, $context); } /** * Adds a log record at the INFO level. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function addInfo($message, array $context = array()) { return $this->addRecord(static::INFO, $message, $context); } /** * Adds a log record at the NOTICE level. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function addNotice($message, array $context = array()) { return $this->addRecord(static::NOTICE, $message, $context); } /** * Adds a log record at the WARNING level. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function addWarning($message, array $context = array()) { return $this->addRecord(static::WARNING, $message, $context); } /** * Adds a log record at the ERROR level. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function addError($message, array $context = array()) { return $this->addRecord(static::ERROR, $message, $context); } /** * Adds a log record at the CRITICAL level. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function addCritical($message, array $context = array()) { return $this->addRecord(static::CRITICAL, $message, $context); } /** * Adds a log record at the ALERT level. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function addAlert($message, array $context = array()) { return $this->addRecord(static::ALERT, $message, $context); } /** * Adds a log record at the EMERGENCY level. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function addEmergency($message, array $context = array()) { return $this->addRecord(static::EMERGENCY, $message, $context); } /** * Gets all supported logging levels. * * @return array Assoc array with human-readable level names => level codes. */ public static function getLevels() { return array_flip(static::$levels); } /** * Gets the name of the logging level. * * @param int $level * @return string */ public static function getLevelName($level) { if (!isset(static::$levels[$level])) { throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels))); } return static::$levels[$level]; } /** * Converts PSR-3 levels to Monolog ones if necessary * * @param string|int Level number (monolog) or name (PSR-3) * @return int */ public static function toMonologLevel($level) { if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) { return constant(__CLASS__.'::'.strtoupper($level)); } return $level; } /** * Checks whether the Logger has a handler that listens on the given level * * @param int $level * @return Boolean */ public function isHandling($level) { $record = array( 'level' => $level, ); foreach ($this->handlers as $handler) { if ($handler->isHandling($record)) { return true; } } return false; } /** * Adds a log record at an arbitrary level. * * This method allows for compatibility with common interfaces. * * @param mixed $level The log level * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function log($level, $message, array $context = array()) { $level = static::toMonologLevel($level); return $this->addRecord($level, $message, $context); } /** * Adds a log record at the DEBUG level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function debug($message, array $context = array()) { return $this->addRecord(static::DEBUG, $message, $context); } /** * Adds a log record at the INFO level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function info($message, array $context = array()) { return $this->addRecord(static::INFO, $message, $context); } /** * Adds a log record at the NOTICE level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function notice($message, array $context = array()) { return $this->addRecord(static::NOTICE, $message, $context); } /** * Adds a log record at the WARNING level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function warn($message, array $context = array()) { return $this->addRecord(static::WARNING, $message, $context); } /** * Adds a log record at the WARNING level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function warning($message, array $context = array()) { return $this->addRecord(static::WARNING, $message, $context); } /** * Adds a log record at the ERROR level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function err($message, array $context = array()) { return $this->addRecord(static::ERROR, $message, $context); } /** * Adds a log record at the ERROR level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function error($message, array $context = array()) { return $this->addRecord(static::ERROR, $message, $context); } /** * Adds a log record at the CRITICAL level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function crit($message, array $context = array()) { return $this->addRecord(static::CRITICAL, $message, $context); } /** * Adds a log record at the CRITICAL level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function critical($message, array $context = array()) { return $this->addRecord(static::CRITICAL, $message, $context); } /** * Adds a log record at the ALERT level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function alert($message, array $context = array()) { return $this->addRecord(static::ALERT, $message, $context); } /** * Adds a log record at the EMERGENCY level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function emerg($message, array $context = array()) { return $this->addRecord(static::EMERGENCY, $message, $context); } /** * Adds a log record at the EMERGENCY level. * * This method allows for compatibility with common interfaces. * * @param string $message The log message * @param array $context The log context * @return Boolean Whether the record has been processed */ public function emergency($message, array $context = array()) { return $this->addRecord(static::EMERGENCY, $message, $context); } /** * Set the timezone to be used for the timestamp of log records. * * This is stored globally for all Logger instances * * @param \DateTimeZone $tz Timezone object */ public static function setTimezone(\DateTimeZone $tz) { self::$timezone = $tz; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Adds a unique identifier into records * * @author Simon Mönch */ class UidProcessor { private $uid; public function __construct($length = 7) { if (!is_int($length) || $length > 32 || $length < 1) { throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32'); } $this->uid = substr(hash('md5', uniqid('', true)), 0, $length); } public function __invoke(array $record) { $record['extra']['uid'] = $this->uid; return $record; } /** * @return string */ public function getUid() { return $this->uid; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Injects url/method and remote IP of the current web request in all records * * @author Jordi Boggiano */ class WebProcessor { /** * @var array|\ArrayAccess */ protected $serverData; /** * Default fields * * Array is structured as [key in record.extra => key in $serverData] * * @var array */ protected $extraFields = array( 'url' => 'REQUEST_URI', 'ip' => 'REMOTE_ADDR', 'http_method' => 'REQUEST_METHOD', 'server' => 'SERVER_NAME', 'referrer' => 'HTTP_REFERER', ); /** * @param array|\ArrayAccess $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data * @param array|null $extraFields Field names and the related key inside $serverData to be added. If not provided it defaults to: url, ip, http_method, server, referrer */ public function __construct($serverData = null, array $extraFields = null) { if (null === $serverData) { $this->serverData = &$_SERVER; } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) { $this->serverData = $serverData; } else { throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.'); } if (null !== $extraFields) { if (isset($extraFields[0])) { foreach (array_keys($this->extraFields) as $fieldName) { if (!in_array($fieldName, $extraFields)) { unset($this->extraFields[$fieldName]); } } } else { $this->extraFields = $extraFields; } } } /** * @param array $record * @return array */ public function __invoke(array $record) { // skip processing if for some reason request data // is not present (CLI or wonky SAPIs) if (!isset($this->serverData['REQUEST_URI'])) { return $record; } $record['extra'] = $this->appendExtraFields($record['extra']); return $record; } /** * @param string $extraName * @param string $serverName * @return $this */ public function addExtraField($extraName, $serverName) { $this->extraFields[$extraName] = $serverName; return $this; } /** * @param array $extra * @return array */ private function appendExtraFields(array $extra) { foreach ($this->extraFields as $extraName => $serverName) { $extra[$extraName] = isset($this->serverData[$serverName]) ? $this->serverData[$serverName] : null; } if (isset($this->serverData['UNIQUE_ID'])) { $extra['unique_id'] = $this->serverData['UNIQUE_ID']; } return $extra; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Some methods that are common for all memory processors * * @author Rob Jensen */ abstract class MemoryProcessor { /** * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported. */ protected $realUsage; /** * @var bool If true, then format memory size to human readable string (MB, KB, B depending on size) */ protected $useFormatting; /** * @param bool $realUsage Set this to true to get the real size of memory allocated from system. * @param bool $useFormatting If true, then format memory size to human readable string (MB, KB, B depending on size) */ public function __construct($realUsage = true, $useFormatting = true) { $this->realUsage = (boolean) $realUsage; $this->useFormatting = (boolean) $useFormatting; } /** * Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is * * @param int $bytes * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as is */ protected function formatBytes($bytes) { $bytes = (int) $bytes; if (!$this->useFormatting) { return $bytes; } if ($bytes > 1024 * 1024) { return round($bytes / 1024 / 1024, 2).' MB'; } elseif ($bytes > 1024) { return round($bytes / 1024, 2).' KB'; } return $bytes . ' B'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Processes a record's message according to PSR-3 rules * * It replaces {foo} with the value from $context['foo'] * * @author Jordi Boggiano */ class PsrLogMessageProcessor { /** * @param array $record * @return array */ public function __invoke(array $record) { if (false === strpos($record['message'], '{')) { return $record; } $replacements = array(); foreach ($record['context'] as $key => $val) { if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) { $replacements['{'.$key.'}'] = $val; } elseif (is_object($val)) { $replacements['{'.$key.'}'] = '[object '.get_class($val).']'; } else { $replacements['{'.$key.'}'] = '['.gettype($val).']'; } } $record['message'] = strtr($record['message'], $replacements); return $record; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Adds value of getmypid into records * * @author Andreas Hörnicke */ class ProcessIdProcessor { /** * @param array $record * @return array */ public function __invoke(array $record) { $record['extra']['process_id'] = getmypid(); return $record; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; use Monolog\Logger; /** * Injects Git branch and Git commit SHA in all records * * @author Nick Otter * @author Jordi Boggiano */ class GitProcessor { private $level; private static $cache; public function __construct($level = Logger::DEBUG) { $this->level = Logger::toMonologLevel($level); } /** * @param array $record * @return array */ public function __invoke(array $record) { // return if the level is not high enough if ($record['level'] < $this->level) { return $record; } $record['extra']['git'] = self::getGitInfo(); return $record; } private static function getGitInfo() { if (self::$cache) { return self::$cache; } $branches = `git branch -v --no-abbrev`; if (preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) { return self::$cache = array( 'branch' => $matches[1], 'commit' => $matches[2], ); } return self::$cache = array(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; use Monolog\Logger; /** * Injects line/file:class/function where the log message came from * * Warning: This only works if the handler processes the logs directly. * If you put the processor on a handler that is behind a FingersCrossedHandler * for example, the processor will only be called once the trigger level is reached, * and all the log records will have the same file/line/.. data from the call that * triggered the FingersCrossedHandler. * * @author Jordi Boggiano */ class IntrospectionProcessor { private $level; private $skipClassesPartials; private $skipStackFramesCount; private $skipFunctions = array( 'call_user_func', 'call_user_func_array', ); public function __construct($level = Logger::DEBUG, array $skipClassesPartials = array(), $skipStackFramesCount = 0) { $this->level = Logger::toMonologLevel($level); $this->skipClassesPartials = array_merge(array('Monolog\\'), $skipClassesPartials); $this->skipStackFramesCount = $skipStackFramesCount; } /** * @param array $record * @return array */ public function __invoke(array $record) { // return if the level is not high enough if ($record['level'] < $this->level) { return $record; } $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); // skip first since it's always the current method array_shift($trace); // the call_user_func call is also skipped array_shift($trace); $i = 0; while ($this->isTraceClassOrSkippedFunction($trace, $i)) { if (isset($trace[$i]['class'])) { foreach ($this->skipClassesPartials as $part) { if (strpos($trace[$i]['class'], $part) !== false) { $i++; continue 2; } } } elseif (in_array($trace[$i]['function'], $this->skipFunctions)) { $i++; continue; } break; } $i += $this->skipStackFramesCount; // we should have the call source now $record['extra'] = array_merge( $record['extra'], array( 'file' => isset($trace[$i - 1]['file']) ? $trace[$i - 1]['file'] : null, 'line' => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null, 'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null, 'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null, ) ); return $record; } private function isTraceClassOrSkippedFunction(array $trace, $index) { if (!isset($trace[$index])) { return false; } return isset($trace[$index]['class']) || in_array($trace[$index]['function'], $this->skipFunctions); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Adds a tags array into record * * @author Martijn Riemers */ class TagProcessor { private $tags; public function __construct(array $tags = array()) { $this->setTags($tags); } public function addTags(array $tags = array()) { $this->tags = array_merge($this->tags, $tags); } public function setTags(array $tags = array()) { $this->tags = $tags; } public function __invoke(array $record) { $record['extra']['tags'] = $this->tags; return $record; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Injects memory_get_usage in all records * * @see Monolog\Processor\MemoryProcessor::__construct() for options * @author Rob Jensen */ class MemoryUsageProcessor extends MemoryProcessor { /** * @param array $record * @return array */ public function __invoke(array $record) { $bytes = memory_get_usage($this->realUsage); $formatted = $this->formatBytes($bytes); $record['extra']['memory_usage'] = $formatted; return $record; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Processor; /** * Injects memory_get_peak_usage in all records * * @see Monolog\Processor\MemoryProcessor::__construct() for options * @author Rob Jensen */ class MemoryPeakUsageProcessor extends MemoryProcessor { /** * @param array $record * @return array */ public function __invoke(array $record) { $bytes = memory_get_peak_usage($this->realUsage); $formatted = $this->formatBytes($bytes); $record['extra']['memory_peak_usage'] = $formatted; return $record; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\JsonFormatter; use PhpAmqpLib\Message\AMQPMessage; use PhpAmqpLib\Channel\AMQPChannel; use AMQPExchange; class AmqpHandler extends AbstractProcessingHandler { /** * @var AMQPExchange|AMQPChannel $exchange */ protected $exchange; /** * @var string */ protected $exchangeName; /** * @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use * @param string $exchangeName * @param int $level * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($exchange, $exchangeName = 'log', $level = Logger::DEBUG, $bubble = true) { if ($exchange instanceof AMQPExchange) { $exchange->setName($exchangeName); } elseif ($exchange instanceof AMQPChannel) { $this->exchangeName = $exchangeName; } else { throw new \InvalidArgumentException('PhpAmqpLib\Channel\AMQPChannel or AMQPExchange instance required'); } $this->exchange = $exchange; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record) { $data = $record["formatted"]; $routingKey = $this->getRoutingKey($record); if ($this->exchange instanceof AMQPExchange) { $this->exchange->publish( $data, $routingKey, 0, array( 'delivery_mode' => 2, 'content_type' => 'application/json', ) ); } else { $this->exchange->basic_publish( $this->createAmqpMessage($data), $this->exchangeName, $routingKey ); } } /** * {@inheritDoc} */ public function handleBatch(array $records) { if ($this->exchange instanceof AMQPExchange) { parent::handleBatch($records); return; } foreach ($records as $record) { if (!$this->isHandling($record)) { continue; } $record = $this->processRecord($record); $data = $this->getFormatter()->format($record); $this->exchange->batch_basic_publish( $this->createAmqpMessage($data), $this->exchangeName, $this->getRoutingKey($record) ); } $this->exchange->publish_batch(); } /** * Gets the routing key for the AMQP exchange * * @param array $record * @return string */ private function getRoutingKey(array $record) { $routingKey = sprintf( '%s.%s', // TODO 2.0 remove substr call substr($record['level_name'], 0, 4), $record['channel'] ); return strtolower($routingKey); } /** * @param string $data * @return AMQPMessage */ private function createAmqpMessage($data) { return new AMQPMessage( (string) $data, array( 'delivery_mode' => 2, 'content_type' => 'application/json', ) ); } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\NormalizerFormatter; /** * Class to record a log on a NewRelic application. * Enabling New Relic High Security mode may prevent capture of useful information. * * @see https://docs.newrelic.com/docs/agents/php-agent * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security */ class NewRelicHandler extends AbstractProcessingHandler { /** * Name of the New Relic application that will receive logs from this handler. * * @var string */ protected $appName; /** * Name of the current transaction * * @var string */ protected $transactionName; /** * Some context and extra data is passed into the handler as arrays of values. Do we send them as is * (useful if we are using the API), or explode them for display on the NewRelic RPM website? * * @var bool */ protected $explodeArrays; /** * {@inheritDoc} * * @param string $appName * @param bool $explodeArrays * @param string $transactionName */ public function __construct( $level = Logger::ERROR, $bubble = true, $appName = null, $explodeArrays = false, $transactionName = null ) { parent::__construct($level, $bubble); $this->appName = $appName; $this->explodeArrays = $explodeArrays; $this->transactionName = $transactionName; } /** * {@inheritDoc} */ protected function write(array $record) { if (!$this->isNewRelicEnabled()) { throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler'); } if ($appName = $this->getAppName($record['context'])) { $this->setNewRelicAppName($appName); } if ($transactionName = $this->getTransactionName($record['context'])) { $this->setNewRelicTransactionName($transactionName); unset($record['formatted']['context']['transaction_name']); } if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) { newrelic_notice_error($record['message'], $record['context']['exception']); unset($record['formatted']['context']['exception']); } else { newrelic_notice_error($record['message']); } foreach ($record['formatted']['context'] as $key => $parameter) { if (is_array($parameter) && $this->explodeArrays) { foreach ($parameter as $paramKey => $paramValue) { $this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue); } } else { $this->setNewRelicParameter('context_' . $key, $parameter); } } foreach ($record['formatted']['extra'] as $key => $parameter) { if (is_array($parameter) && $this->explodeArrays) { foreach ($parameter as $paramKey => $paramValue) { $this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue); } } else { $this->setNewRelicParameter('extra_' . $key, $parameter); } } } /** * Checks whether the NewRelic extension is enabled in the system. * * @return bool */ protected function isNewRelicEnabled() { return extension_loaded('newrelic'); } /** * Returns the appname where this log should be sent. Each log can override the default appname, set in this * handler's constructor, by providing the appname in it's context. * * @param array $context * @return null|string */ protected function getAppName(array $context) { if (isset($context['appname'])) { return $context['appname']; } return $this->appName; } /** * Returns the name of the current transaction. Each log can override the default transaction name, set in this * handler's constructor, by providing the transaction_name in it's context * * @param array $context * * @return null|string */ protected function getTransactionName(array $context) { if (isset($context['transaction_name'])) { return $context['transaction_name']; } return $this->transactionName; } /** * Sets the NewRelic application that should receive this log. * * @param string $appName */ protected function setNewRelicAppName($appName) { newrelic_set_appname($appName); } /** * Overwrites the name of the current transaction * * @param string $transactionName */ protected function setNewRelicTransactionName($transactionName) { newrelic_name_transaction($transactionName); } /** * @param string $key * @param mixed $value */ protected function setNewRelicParameter($key, $value) { if (null === $value || is_scalar($value)) { newrelic_add_custom_parameter($key, $value); } else { newrelic_add_custom_parameter($key, @json_encode($value)); } } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new NormalizerFormatter(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; use Monolog\Handler\FingersCrossed\ActivationStrategyInterface; use Monolog\Logger; /** * Buffers all records until a certain level is reached * * The advantage of this approach is that you don't get any clutter in your log files. * Only requests which actually trigger an error (or whatever your actionLevel is) will be * in the logs, but they will contain all records, not only those above the level threshold. * * You can find the various activation strategies in the * Monolog\Handler\FingersCrossed\ namespace. * * @author Jordi Boggiano */ class FingersCrossedHandler extends AbstractHandler { protected $handler; protected $activationStrategy; protected $buffering = true; protected $bufferSize; protected $buffer = array(); protected $stopBuffering; protected $passthruLevel; /** * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler). * @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not * @param Boolean $stopBuffering Whether the handler should stop buffering after being triggered (default true) * @param int $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered */ public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = true, $stopBuffering = true, $passthruLevel = null) { if (null === $activationStrategy) { $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING); } // convert simple int activationStrategy to an object if (!$activationStrategy instanceof ActivationStrategyInterface) { $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy); } $this->handler = $handler; $this->activationStrategy = $activationStrategy; $this->bufferSize = $bufferSize; $this->bubble = $bubble; $this->stopBuffering = $stopBuffering; if ($passthruLevel !== null) { $this->passthruLevel = Logger::toMonologLevel($passthruLevel); } if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); } } /** * {@inheritdoc} */ public function isHandling(array $record) { return true; } /** * {@inheritdoc} */ public function handle(array $record) { if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } if ($this->buffering) { $this->buffer[] = $record; if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { array_shift($this->buffer); } if ($this->activationStrategy->isHandlerActivated($record)) { if ($this->stopBuffering) { $this->buffering = false; } if (!$this->handler instanceof HandlerInterface) { $this->handler = call_user_func($this->handler, $record, $this); if (!$this->handler instanceof HandlerInterface) { throw new \RuntimeException("The factory callable should return a HandlerInterface"); } } $this->handler->handleBatch($this->buffer); $this->buffer = array(); } } else { $this->handler->handle($record); } return false === $this->bubble; } /** * {@inheritdoc} */ public function close() { if (null !== $this->passthruLevel) { $level = $this->passthruLevel; $this->buffer = array_filter($this->buffer, function ($record) use ($level) { return $record['level'] >= $level; }); if (count($this->buffer) > 0) { $this->handler->handleBatch($this->buffer); $this->buffer = array(); } } } /** * Resets the state of the handler. Stops forwarding records to the wrapped handler. */ public function reset() { $this->buffering = true; } /** * Clears the buffer without flushing any messages down to the wrapped handler. * * It also resets the handler to its initial buffering state. */ public function clear() { $this->buffer = array(); $this->reset(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\WildfireFormatter; /** * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol. * * @author Eric Clemmons (@ericclemmons) */ class FirePHPHandler extends AbstractProcessingHandler { /** * WildFire JSON header message format */ const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2'; /** * FirePHP structure for parsing messages & their presentation */ const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'; /** * Must reference a "known" plugin, otherwise headers won't display in FirePHP */ const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3'; /** * Header prefix for Wildfire to recognize & parse headers */ const HEADER_PREFIX = 'X-Wf'; /** * Whether or not Wildfire vendor-specific headers have been generated & sent yet */ protected static $initialized = false; /** * Shared static message index between potentially multiple handlers * @var int */ protected static $messageIndex = 1; protected static $sendHeaders = true; /** * Base header creation function used by init headers & record headers * * @param array $meta Wildfire Plugin, Protocol & Structure Indexes * @param string $message Log message * @return array Complete header string ready for the client as key and message as value */ protected function createHeader(array $meta, $message) { $header = sprintf('%s-%s', self::HEADER_PREFIX, join('-', $meta)); return array($header => $message); } /** * Creates message header from record * * @see createHeader() * @param array $record * @return string */ protected function createRecordHeader(array $record) { // Wildfire is extensible to support multiple protocols & plugins in a single request, // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake. return $this->createHeader( array(1, 1, 1, self::$messageIndex++), $record['formatted'] ); } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new WildfireFormatter(); } /** * Wildfire initialization headers to enable message parsing * * @see createHeader() * @see sendHeader() * @return array */ protected function getInitHeaders() { // Initial payload consists of required headers for Wildfire return array_merge( $this->createHeader(array('Protocol', 1), self::PROTOCOL_URI), $this->createHeader(array(1, 'Structure', 1), self::STRUCTURE_URI), $this->createHeader(array(1, 'Plugin', 1), self::PLUGIN_URI) ); } /** * Send header string to the client * * @param string $header * @param string $content */ protected function sendHeader($header, $content) { if (!headers_sent() && self::$sendHeaders) { header(sprintf('%s: %s', $header, $content)); } } /** * Creates & sends header for a record, ensuring init headers have been sent prior * * @see sendHeader() * @see sendInitHeaders() * @param array $record */ protected function write(array $record) { if (!self::$sendHeaders) { return; } // WildFire-specific headers must be sent prior to any messages if (!self::$initialized) { self::$initialized = true; self::$sendHeaders = $this->headersAccepted(); if (!self::$sendHeaders) { return; } foreach ($this->getInitHeaders() as $header => $content) { $this->sendHeader($header, $content); } } $header = $this->createRecordHeader($record); if (trim(current($header)) !== '') { $this->sendHeader(key($header), current($header)); } } /** * Verifies if the headers are accepted by the current user agent * * @return Boolean */ protected function headersAccepted() { if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) { return true; } return isset($_SERVER['HTTP_X_FIREPHP_VERSION']); } /** * BC getter for the sendHeaders property that has been made static */ public function __get($property) { if ('sendHeaders' !== $property) { throw new \InvalidArgumentException('Undefined property '.$property); } return static::$sendHeaders; } /** * BC setter for the sendHeaders property that has been made static */ public function __set($property, $value) { if ('sendHeaders' !== $property) { throw new \InvalidArgumentException('Undefined property '.$property); } static::$sendHeaders = $value; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\NormalizerFormatter; use Doctrine\CouchDB\CouchDBClient; /** * CouchDB handler for Doctrine CouchDB ODM * * @author Markus Bachmann */ class DoctrineCouchDBHandler extends AbstractProcessingHandler { private $client; public function __construct(CouchDBClient $client, $level = Logger::DEBUG, $bubble = true) { $this->client = $client; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record) { $this->client->postDocument($record['formatted']); } protected function getDefaultFormatter() { return new NormalizerFormatter; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Stores to any socket - uses fsockopen() or pfsockopen(). * * @author Pablo de Leon Belloc * @see http://php.net/manual/en/function.fsockopen.php */ class SocketHandler extends AbstractProcessingHandler { private $connectionString; private $connectionTimeout; private $resource; private $timeout = 0; private $writingTimeout = 10; private $lastSentBytes = null; private $persistent = false; private $errno; private $errstr; private $lastWritingAt; /** * @param string $connectionString Socket connection string * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); $this->connectionString = $connectionString; $this->connectionTimeout = (float) ini_get('default_socket_timeout'); } /** * Connect (if necessary) and write to the socket * * @param array $record * * @throws \UnexpectedValueException * @throws \RuntimeException */ protected function write(array $record) { $this->connectIfNotConnected(); $data = $this->generateDataStream($record); $this->writeToSocket($data); } /** * We will not close a PersistentSocket instance so it can be reused in other requests. */ public function close() { if (!$this->isPersistent()) { $this->closeSocket(); } } /** * Close socket, if open */ public function closeSocket() { if (is_resource($this->resource)) { fclose($this->resource); $this->resource = null; } } /** * Set socket connection to nbe persistent. It only has effect before the connection is initiated. * * @param bool $persistent */ public function setPersistent($persistent) { $this->persistent = (boolean) $persistent; } /** * Set connection timeout. Only has effect before we connect. * * @param float $seconds * * @see http://php.net/manual/en/function.fsockopen.php */ public function setConnectionTimeout($seconds) { $this->validateTimeout($seconds); $this->connectionTimeout = (float) $seconds; } /** * Set write timeout. Only has effect before we connect. * * @param float $seconds * * @see http://php.net/manual/en/function.stream-set-timeout.php */ public function setTimeout($seconds) { $this->validateTimeout($seconds); $this->timeout = (float) $seconds; } /** * Set writing timeout. Only has effect during connection in the writing cycle. * * @param float $seconds 0 for no timeout */ public function setWritingTimeout($seconds) { $this->validateTimeout($seconds); $this->writingTimeout = (float) $seconds; } /** * Get current connection string * * @return string */ public function getConnectionString() { return $this->connectionString; } /** * Get persistent setting * * @return bool */ public function isPersistent() { return $this->persistent; } /** * Get current connection timeout setting * * @return float */ public function getConnectionTimeout() { return $this->connectionTimeout; } /** * Get current in-transfer timeout * * @return float */ public function getTimeout() { return $this->timeout; } /** * Get current local writing timeout * * @return float */ public function getWritingTimeout() { return $this->writingTimeout; } /** * Check to see if the socket is currently available. * * UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details. * * @return bool */ public function isConnected() { return is_resource($this->resource) && !feof($this->resource); // on TCP - other party can close connection. } /** * Wrapper to allow mocking */ protected function pfsockopen() { return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); } /** * Wrapper to allow mocking */ protected function fsockopen() { return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); } /** * Wrapper to allow mocking * * @see http://php.net/manual/en/function.stream-set-timeout.php */ protected function streamSetTimeout() { $seconds = floor($this->timeout); $microseconds = round(($this->timeout - $seconds) * 1e6); return stream_set_timeout($this->resource, $seconds, $microseconds); } /** * Wrapper to allow mocking */ protected function fwrite($data) { return @fwrite($this->resource, $data); } /** * Wrapper to allow mocking */ protected function streamGetMetadata() { return stream_get_meta_data($this->resource); } private function validateTimeout($value) { $ok = filter_var($value, FILTER_VALIDATE_FLOAT); if ($ok === false || $value < 0) { throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got $value)"); } } private function connectIfNotConnected() { if ($this->isConnected()) { return; } $this->connect(); } protected function generateDataStream($record) { return (string) $record['formatted']; } /** * @return resource|null */ protected function getResource() { return $this->resource; } private function connect() { $this->createSocketResource(); $this->setSocketTimeout(); } private function createSocketResource() { if ($this->isPersistent()) { $resource = $this->pfsockopen(); } else { $resource = $this->fsockopen(); } if (!$resource) { throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)"); } $this->resource = $resource; } private function setSocketTimeout() { if (!$this->streamSetTimeout()) { throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()"); } } private function writeToSocket($data) { $length = strlen($data); $sent = 0; $this->lastSentBytes = $sent; while ($this->isConnected() && $sent < $length) { if (0 == $sent) { $chunk = $this->fwrite($data); } else { $chunk = $this->fwrite(substr($data, $sent)); } if ($chunk === false) { throw new \RuntimeException("Could not write to socket"); } $sent += $chunk; $socketInfo = $this->streamGetMetadata(); if ($socketInfo['timed_out']) { throw new \RuntimeException("Write timed-out"); } if ($this->writingIsTimedOut($sent)) { throw new \RuntimeException("Write timed-out, no data sent for `{$this->writingTimeout}` seconds, probably we got disconnected (sent $sent of $length)"); } } if (!$this->isConnected() && $sent < $length) { throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); } } private function writingIsTimedOut($sent) { $writingTimeout = (int) floor($this->writingTimeout); if (0 === $writingTimeout) { return false; } if ($sent !== $this->lastSentBytes) { $this->lastWritingAt = time(); $this->lastSentBytes = $sent; return false; } else { usleep(100); } if ((time() - $this->lastWritingAt) >= $writingTimeout) { $this->closeSocket(); return true; } return false; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Simple handler wrapper that deduplicates log records across multiple requests * * It also includes the BufferHandler functionality and will buffer * all messages until the end of the request or flush() is called. * * This works by storing all log records' messages above $deduplicationLevel * to the file specified by $deduplicationStore. When further logs come in at the end of the * request (or when flush() is called), all those above $deduplicationLevel are checked * against the existing stored logs. If they match and the timestamps in the stored log is * not older than $time seconds, the new log record is discarded. If no log record is new, the * whole data set is discarded. * * This is mainly useful in combination with Mail handlers or things like Slack or HipChat handlers * that send messages to people, to avoid spamming with the same message over and over in case of * a major component failure like a database server being down which makes all requests fail in the * same way. * * @author Jordi Boggiano */ class DeduplicationHandler extends BufferHandler { /** * @var string */ protected $deduplicationStore; /** * @var int */ protected $deduplicationLevel; /** * @var int */ protected $time; /** * @var bool */ private $gc = false; /** * @param HandlerInterface $handler Handler. * @param string $deduplicationStore The file/path where the deduplication log should be kept * @param int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(HandlerInterface $handler, $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, $time = 60, $bubble = true) { parent::__construct($handler, 0, Logger::DEBUG, $bubble, false); $this->deduplicationStore = $deduplicationStore === null ? sys_get_temp_dir() . '/monolog-dedup-' . substr(md5(__FILE__), 0, 20) .'.log' : $deduplicationStore; $this->deduplicationLevel = Logger::toMonologLevel($deduplicationLevel); $this->time = $time; } public function flush() { if ($this->bufferSize === 0) { return; } $passthru = null; foreach ($this->buffer as $record) { if ($record['level'] >= $this->deduplicationLevel) { $passthru = $passthru || !$this->isDuplicate($record); if ($passthru) { $this->appendRecord($record); } } } // default of null is valid as well as if no record matches duplicationLevel we just pass through if ($passthru === true || $passthru === null) { $this->handler->handleBatch($this->buffer); } $this->clear(); if ($this->gc) { $this->collectLogs(); } } private function isDuplicate(array $record) { if (!file_exists($this->deduplicationStore)) { return false; } $store = file($this->deduplicationStore, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); if (!is_array($store)) { return false; } $yesterday = time() - 86400; $timestampValidity = $record['datetime']->getTimestamp() - $this->time; $expectedMessage = preg_replace('{[\r\n].*}', '', $record['message']); for ($i = count($store) - 1; $i >= 0; $i--) { list($timestamp, $level, $message) = explode(':', $store[$i], 3); if ($level === $record['level_name'] && $message === $expectedMessage && $timestamp > $timestampValidity) { return true; } if ($timestamp < $yesterday) { $this->gc = true; } } return false; } private function collectLogs() { if (!file_exists($this->deduplicationStore)) { return false; } $handle = fopen($this->deduplicationStore, 'rw+'); flock($handle, LOCK_EX); $validLogs = array(); $timestampValidity = time() - $this->time; while (!feof($handle)) { $log = fgets($handle); if (substr($log, 0, 10) >= $timestampValidity) { $validLogs[] = $log; } } ftruncate($handle, 0); rewind($handle); foreach ($validLogs as $log) { fwrite($handle, $log); } flock($handle, LOCK_UN); fclose($handle); $this->gc = false; } private function appendRecord(array $record) { file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\r\n].*}', '', $record['message']) . "\n", FILE_APPEND); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\LineFormatter; /** * Sends notifications through Slack API * * @author Greg Kedzierski * @see https://api.slack.com/ */ class SlackHandler extends SocketHandler { /** * Slack API token * @var string */ private $token; /** * Slack channel (encoded ID or name) * @var string */ private $channel; /** * Name of a bot * @var string */ private $username; /** * Emoji icon name * @var string */ private $iconEmoji; /** * Whether the message should be added to Slack as attachment (plain text otherwise) * @var bool */ private $useAttachment; /** * Whether the the context/extra messages added to Slack as attachments are in a short style * @var bool */ private $useShortAttachment; /** * Whether the attachment should include context and extra data * @var bool */ private $includeContextAndExtra; /** * @var LineFormatter */ private $lineFormatter; /** * @param string $token Slack API token * @param string $channel Slack channel (encoded ID or name) * @param string $username Name of a bot * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise) * @param string|null $iconEmoji The emoji name to use (or null) * @param int $level The minimum logging level at which this handler will be triggered * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style * @param bool $includeContextAndExtra Whether the attachment should include context and extra data * @throws MissingExtensionException If no OpenSSL PHP extension configured */ public function __construct($token, $channel, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeContextAndExtra = false) { if (!extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler'); } parent::__construct('ssl://slack.com:443', $level, $bubble); $this->token = $token; $this->channel = $channel; $this->username = $username; $this->iconEmoji = trim($iconEmoji, ':'); $this->useAttachment = $useAttachment; $this->useShortAttachment = $useShortAttachment; $this->includeContextAndExtra = $includeContextAndExtra; if ($this->includeContextAndExtra && $this->useShortAttachment) { $this->lineFormatter = new LineFormatter; } } /** * {@inheritdoc} * * @param array $record * @return string */ protected function generateDataStream($record) { $content = $this->buildContent($record); return $this->buildHeader($content) . $content; } /** * Builds the body of API call * * @param array $record * @return string */ private function buildContent($record) { $dataArray = $this->prepareContentData($record); return http_build_query($dataArray); } /** * Prepares content data * * @param array $record * @return array */ protected function prepareContentData($record) { $dataArray = array( 'token' => $this->token, 'channel' => $this->channel, 'username' => $this->username, 'text' => '', 'attachments' => array(), ); if ($this->useAttachment) { $attachment = array( 'fallback' => $record['message'], 'color' => $this->getAttachmentColor($record['level']), 'fields' => array(), ); if ($this->useShortAttachment) { $attachment['title'] = $record['level_name']; $attachment['text'] = $record['message']; } else { $attachment['title'] = 'Message'; $attachment['text'] = $record['message']; $attachment['fields'][] = array( 'title' => 'Level', 'value' => $record['level_name'], 'short' => true, ); } if ($this->includeContextAndExtra) { if (!empty($record['extra'])) { if ($this->useShortAttachment) { $attachment['fields'][] = array( 'title' => "Extra", 'value' => $this->stringify($record['extra']), 'short' => $this->useShortAttachment, ); } else { // Add all extra fields as individual fields in attachment foreach ($record['extra'] as $var => $val) { $attachment['fields'][] = array( 'title' => $var, 'value' => $val, 'short' => $this->useShortAttachment, ); } } } if (!empty($record['context'])) { if ($this->useShortAttachment) { $attachment['fields'][] = array( 'title' => "Context", 'value' => $this->stringify($record['context']), 'short' => $this->useShortAttachment, ); } else { // Add all context fields as individual fields in attachment foreach ($record['context'] as $var => $val) { $attachment['fields'][] = array( 'title' => $var, 'value' => $val, 'short' => $this->useShortAttachment, ); } } } } $dataArray['attachments'] = json_encode(array($attachment)); } else { $dataArray['text'] = $record['message']; } if ($this->iconEmoji) { $dataArray['icon_emoji'] = ":{$this->iconEmoji}:"; } return $dataArray; } /** * Builds the header of the API Call * * @param string $content * @return string */ private function buildHeader($content) { $header = "POST /api/chat.postMessage HTTP/1.1\r\n"; $header .= "Host: slack.com\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($content) . "\r\n"; $header .= "\r\n"; return $header; } /** * {@inheritdoc} * * @param array $record */ protected function write(array $record) { parent::write($record); $res = $this->getResource(); if (is_resource($res)) { @fread($res, 2048); } $this->closeSocket(); } /** * Returned a Slack message attachment color associated with * provided level. * * @param int $level * @return string */ protected function getAttachmentColor($level) { switch (true) { case $level >= Logger::ERROR: return 'danger'; case $level >= Logger::WARNING: return 'warning'; case $level >= Logger::INFO: return 'good'; default: return '#e3e4e6'; } } /** * Stringifies an array of key/value pairs to be used in attachment fields * * @param array $fields * @return string */ protected function stringify($fields) { $string = ''; foreach ($fields as $var => $val) { $string .= $var.': '.$this->lineFormatter->stringify($val)." | "; } $string = rtrim($string, " |"); return $string; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; /** * Handler sending logs to browser's javascript console with no browser extension required * * @author Olivier Poitrey */ class BrowserConsoleHandler extends AbstractProcessingHandler { protected static $initialized = false; protected static $records = array(); /** * {@inheritDoc} * * Formatted output may contain some formatting markers to be transferred to `console.log` using the %c format. * * Example of formatted string: * * You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white} */ protected function getDefaultFormatter() { return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%'); } /** * {@inheritDoc} */ protected function write(array $record) { // Accumulate records self::$records[] = $record; // Register shutdown handler if not already done if (!self::$initialized) { self::$initialized = true; $this->registerShutdownFunction(); } } /** * Convert records to javascript console commands and send it to the browser. * This method is automatically called on PHP shutdown if output is HTML or Javascript. */ public static function send() { $format = self::getResponseFormat(); if ($format === 'unknown') { return; } if (count(self::$records)) { if ($format === 'html') { self::writeOutput(''); } elseif ($format === 'js') { self::writeOutput(self::generateScript()); } self::reset(); } } /** * Forget all logged records */ public static function reset() { self::$records = array(); } /** * Wrapper for register_shutdown_function to allow overriding */ protected function registerShutdownFunction() { if (PHP_SAPI !== 'cli') { register_shutdown_function(array('Monolog\Handler\BrowserConsoleHandler', 'send')); } } /** * Wrapper for echo to allow overriding * * @param string $str */ protected static function writeOutput($str) { echo $str; } /** * Checks the format of the response * * If Content-Type is set to application/javascript or text/javascript -> js * If Content-Type is set to text/html, or is unset -> html * If Content-Type is anything else -> unknown * * @return string One of 'js', 'html' or 'unknown' */ protected static function getResponseFormat() { // Check content type foreach (headers_list() as $header) { if (stripos($header, 'content-type:') === 0) { // This handler only works with HTML and javascript outputs // text/javascript is obsolete in favour of application/javascript, but still used if (stripos($header, 'application/javascript') !== false || stripos($header, 'text/javascript') !== false) { return 'js'; } if (stripos($header, 'text/html') === false) { return 'unknown'; } break; } } return 'html'; } private static function generateScript() { $script = array(); foreach (self::$records as $record) { $context = self::dump('Context', $record['context']); $extra = self::dump('Extra', $record['extra']); if (empty($context) && empty($extra)) { $script[] = self::call_array('log', self::handleStyles($record['formatted'])); } else { $script = array_merge($script, array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))), $context, $extra, array(self::call('groupEnd')) ); } } return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);"; } private static function handleStyles($formatted) { $args = array(self::quote('font-weight: normal')); $format = '%c' . $formatted; preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); foreach (array_reverse($matches) as $match) { $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0])); $args[] = '"font-weight: normal"'; $pos = $match[0][1]; $format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0])); } array_unshift($args, self::quote($format)); return $args; } private static function handleCustomStyles($style, $string) { static $colors = array('blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'); static $labels = array(); return preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function ($m) use ($string, &$colors, &$labels) { if (trim($m[1]) === 'autolabel') { // Format the string as a label with consistent auto assigned background color if (!isset($labels[$string])) { $labels[$string] = $colors[count($labels) % count($colors)]; } $color = $labels[$string]; return "background-color: $color; color: white; border-radius: 3px; padding: 0 2px 0 2px"; } return $m[1]; }, $style); } private static function dump($title, array $dict) { $script = array(); $dict = array_filter($dict); if (empty($dict)) { return $script; } $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title)); foreach ($dict as $key => $value) { $value = json_encode($value); if (empty($value)) { $value = self::quote(''); } $script[] = self::call('log', self::quote('%s: %o'), self::quote($key), $value); } return $script; } private static function quote($arg) { return '"' . addcslashes($arg, "\"\n\\") . '"'; } private static function call() { $args = func_get_args(); $method = array_shift($args); return self::call_array($method, $args); } private static function call_array($method, array $args) { return 'c.' . $method . '(' . implode(', ', $args) . ');'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Sends notifications through the pushover api to mobile phones * * @author Sebastian Göttschkes * @see https://www.pushover.net/api */ class PushoverHandler extends SocketHandler { private $token; private $users; private $title; private $user; private $retry; private $expire; private $highPriorityLevel; private $emergencyLevel; private $useFormattedMessage = false; /** * All parameters that can be sent to Pushover * @see https://pushover.net/api * @var array */ private $parameterNames = array( 'token' => true, 'user' => true, 'message' => true, 'device' => true, 'title' => true, 'url' => true, 'url_title' => true, 'priority' => true, 'timestamp' => true, 'sound' => true, 'retry' => true, 'expire' => true, 'callback' => true, ); /** * Sounds the api supports by default * @see https://pushover.net/api#sounds * @var array */ private $sounds = array( 'pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', 'persistent', 'echo', 'updown', 'none', ); /** * @param string $token Pushover api token * @param string|array $users Pushover user id or array of ids the message will be sent to * @param string $title Title sent to the Pushover API * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not * @param Boolean $useSSL Whether to connect via SSL. Required when pushing messages to users that are not * the pushover.net app owner. OpenSSL is required for this option. * @param int $highPriorityLevel The minimum logging level at which this handler will start * sending "high priority" requests to the Pushover API * @param int $emergencyLevel The minimum logging level at which this handler will start * sending "emergency" requests to the Pushover API * @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will send the same notification to the user. * @param int $expire The expire parameter specifies how many seconds your notification will continue to be retried for (every retry seconds). */ public function __construct($token, $users, $title = null, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $highPriorityLevel = Logger::CRITICAL, $emergencyLevel = Logger::EMERGENCY, $retry = 30, $expire = 25200) { $connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80'; parent::__construct($connectionString, $level, $bubble); $this->token = $token; $this->users = (array) $users; $this->title = $title ?: gethostname(); $this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel); $this->emergencyLevel = Logger::toMonologLevel($emergencyLevel); $this->retry = $retry; $this->expire = $expire; } protected function generateDataStream($record) { $content = $this->buildContent($record); return $this->buildHeader($content) . $content; } private function buildContent($record) { // Pushover has a limit of 512 characters on title and message combined. $maxMessageLength = 512 - strlen($this->title); $message = ($this->useFormattedMessage) ? $record['formatted'] : $record['message']; $message = substr($message, 0, $maxMessageLength); $timestamp = $record['datetime']->getTimestamp(); $dataArray = array( 'token' => $this->token, 'user' => $this->user, 'message' => $message, 'title' => $this->title, 'timestamp' => $timestamp, ); if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) { $dataArray['priority'] = 2; $dataArray['retry'] = $this->retry; $dataArray['expire'] = $this->expire; } elseif (isset($record['level']) && $record['level'] >= $this->highPriorityLevel) { $dataArray['priority'] = 1; } // First determine the available parameters $context = array_intersect_key($record['context'], $this->parameterNames); $extra = array_intersect_key($record['extra'], $this->parameterNames); // Least important info should be merged with subsequent info $dataArray = array_merge($extra, $context, $dataArray); // Only pass sounds that are supported by the API if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds)) { unset($dataArray['sound']); } return http_build_query($dataArray); } private function buildHeader($content) { $header = "POST /1/messages.json HTTP/1.1\r\n"; $header .= "Host: api.pushover.net\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($content) . "\r\n"; $header .= "\r\n"; return $header; } protected function write(array $record) { foreach ($this->users as $user) { $this->user = $user; parent::write($record); $this->closeSocket(); } $this->user = null; } public function setHighPriorityLevel($value) { $this->highPriorityLevel = $value; } public function setEmergencyLevel($value) { $this->emergencyLevel = $value; } /** * Use the formatted message? * @param bool $value */ public function useFormattedMessage($value) { $this->useFormattedMessage = (boolean) $value; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Logger; /** * Sends logs to Fleep.io using Webhook integrations * * You'll need a Fleep.io account to use this handler. * * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation * @author Ando Roots */ class FleepHookHandler extends SocketHandler { const FLEEP_HOST = 'fleep.io'; const FLEEP_HOOK_URI = '/hook/'; /** * @var string Webhook token (specifies the conversation where logs are sent) */ protected $token; /** * Construct a new Fleep.io Handler. * * For instructions on how to create a new web hook in your conversations * see https://fleep.io/integrations/webhooks/ * * @param string $token Webhook token * @param bool|int $level The minimum logging level at which this handler will be triggered * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * @throws MissingExtensionException */ public function __construct($token, $level = Logger::DEBUG, $bubble = true) { if (!extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler'); } $this->token = $token; $connectionString = 'ssl://' . self::FLEEP_HOST . ':443'; parent::__construct($connectionString, $level, $bubble); } /** * Returns the default formatter to use with this handler * * Overloaded to remove empty context and extra arrays from the end of the log message. * * @return LineFormatter */ protected function getDefaultFormatter() { return new LineFormatter(null, null, true, true); } /** * Handles a log record * * @param array $record */ public function write(array $record) { parent::write($record); $this->closeSocket(); } /** * {@inheritdoc} * * @param array $record * @return string */ protected function generateDataStream($record) { $content = $this->buildContent($record); return $this->buildHeader($content) . $content; } /** * Builds the header of the API Call * * @param string $content * @return string */ private function buildHeader($content) { $header = "POST " . self::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n"; $header .= "Host: " . self::FLEEP_HOST . "\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($content) . "\r\n"; $header .= "\r\n"; return $header; } /** * Builds the body of API call * * @param array $record * @return string */ private function buildContent($record) { $dataArray = array( 'message' => $record['formatted'], ); return http_build_query($dataArray); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\LineFormatter; /** * NativeMailerHandler uses the mail() function to send the emails * * @author Christophe Coevoet * @author Mark Garrett */ class NativeMailerHandler extends MailHandler { /** * The email addresses to which the message will be sent * @var array */ protected $to; /** * The subject of the email * @var string */ protected $subject; /** * Optional headers for the message * @var array */ protected $headers = array(); /** * Optional parameters for the message * @var array */ protected $parameters = array(); /** * The wordwrap length for the message * @var int */ protected $maxColumnWidth; /** * The Content-type for the message * @var string */ protected $contentType = 'text/plain'; /** * The encoding for the message * @var string */ protected $encoding = 'utf-8'; /** * @param string|array $to The receiver of the mail * @param string $subject The subject of the mail * @param string $from The sender of the mail * @param int $level The minimum logging level at which this handler will be triggered * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * @param int $maxColumnWidth The maximum column width that the message lines will have */ public function __construct($to, $subject, $from, $level = Logger::ERROR, $bubble = true, $maxColumnWidth = 70) { parent::__construct($level, $bubble); $this->to = is_array($to) ? $to : array($to); $this->subject = $subject; $this->addHeader(sprintf('From: %s', $from)); $this->maxColumnWidth = $maxColumnWidth; } /** * Add headers to the message * * @param string|array $headers Custom added headers * @return self */ public function addHeader($headers) { foreach ((array) $headers as $header) { if (strpos($header, "\n") !== false || strpos($header, "\r") !== false) { throw new \InvalidArgumentException('Headers can not contain newline characters for security reasons'); } $this->headers[] = $header; } return $this; } /** * Add parameters to the message * * @param string|array $parameters Custom added parameters * @return self */ public function addParameter($parameters) { $this->parameters = array_merge($this->parameters, (array) $parameters); return $this; } /** * {@inheritdoc} */ protected function send($content, array $records) { $content = wordwrap($content, $this->maxColumnWidth); $headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n"); $headers .= 'Content-type: ' . $this->getContentType() . '; charset=' . $this->getEncoding() . "\r\n"; if ($this->getContentType() == 'text/html' && false === strpos($headers, 'MIME-Version:')) { $headers .= 'MIME-Version: 1.0' . "\r\n"; } $subject = $this->subject; if ($records) { $subjectFormatter = new LineFormatter($this->subject); $subject = $subjectFormatter->format($this->getHighestRecord($records)); } $parameters = implode(' ', $this->parameters); foreach ($this->to as $to) { mail($to, $subject, $content, $headers, $parameters); } } /** * @return string $contentType */ public function getContentType() { return $this->contentType; } /** * @return string $encoding */ public function getEncoding() { return $this->encoding; } /** * @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML * messages. * @return self */ public function setContentType($contentType) { if (strpos($contentType, "\n") !== false || strpos($contentType, "\r") !== false) { throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection'); } $this->contentType = $contentType; return $this; } /** * @param string $encoding * @return self */ public function setEncoding($encoding) { if (strpos($encoding, "\n") !== false || strpos($encoding, "\r") !== false) { throw new \InvalidArgumentException('The encoding can not contain newline characters to prevent email header injection'); } $this->encoding = $encoding; return $this; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Handler\SyslogUdp\UdpSocket; /** * A Handler for logging to a remote syslogd server. * * @author Jesper Skovgaard Nielsen */ class SyslogUdpHandler extends AbstractSyslogHandler { protected $socket; /** * @param string $host * @param int $port * @param mixed $facility * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) { parent::__construct($facility, $level, $bubble); $this->socket = new UdpSocket($host, $port ?: 514); } protected function write(array $record) { $lines = $this->splitMessageIntoLines($record['formatted']); $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']]); foreach ($lines as $line) { $this->socket->write($line, $header); } } public function close() { $this->socket->close(); } private function splitMessageIntoLines($message) { if (is_array($message)) { $message = implode("\n", $message); } return preg_split('/$\R?^/m', $message); } /** * Make common syslog header (see rfc5424) */ protected function makeCommonSyslogHeader($severity) { $priority = $severity + $this->facility; return "<$priority>1 "; } /** * Inject your own socket, mainly used for testing */ public function setSocket($socket) { $this->socket = $socket; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Logger; /** * Stores to PHP error_log() handler. * * @author Elan Ruusamäe */ class ErrorLogHandler extends AbstractProcessingHandler { const OPERATING_SYSTEM = 0; const SAPI = 4; protected $messageType; protected $expandNewlines; /** * @param int $messageType Says where the error should go. * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not * @param Boolean $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries */ public function __construct($messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, $bubble = true, $expandNewlines = false) { parent::__construct($level, $bubble); if (false === in_array($messageType, self::getAvailableTypes())) { $message = sprintf('The given message type "%s" is not supported', print_r($messageType, true)); throw new \InvalidArgumentException($message); } $this->messageType = $messageType; $this->expandNewlines = $expandNewlines; } /** * @return array With all available types */ public static function getAvailableTypes() { return array( self::OPERATING_SYSTEM, self::SAPI, ); } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%'); } /** * {@inheritdoc} */ protected function write(array $record) { if ($this->expandNewlines) { $lines = preg_split('{[\r\n]+}', (string) $record['formatted']); foreach ($lines as $line) { error_log($line, $this->messageType); } } else { error_log((string) $record['formatted'], $this->messageType); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Forwards records to multiple handlers suppressing failures of each handler * and continuing through to give every handler a chance to succeed. * * @author Craig D'Amelio */ class WhatFailureGroupHandler extends GroupHandler { /** * {@inheritdoc} */ public function handle(array $record) { if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } foreach ($this->handlers as $handler) { try { $handler->handle($record); } catch (\Exception $e) { // What failure? } } return false === $this->bubble; } /** * {@inheritdoc} */ public function handleBatch(array $records) { foreach ($this->handlers as $handler) { try { $handler->handleBatch($records); } catch (\Exception $e) { // What failure? } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\FlowdockFormatter; use Monolog\Formatter\FormatterInterface; /** * Sends notifications through the Flowdock push API * * This must be configured with a FlowdockFormatter instance via setFormatter() * * Notes: * API token - Flowdock API token * * @author Dominik Liebler * @see https://www.flowdock.com/api/push */ class FlowdockHandler extends SocketHandler { /** * @var string */ protected $apiToken; /** * @param string $apiToken * @param bool|int $level The minimum logging level at which this handler will be triggered * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * * @throws MissingExtensionException if OpenSSL is missing */ public function __construct($apiToken, $level = Logger::DEBUG, $bubble = true) { if (!extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler'); } parent::__construct('ssl://api.flowdock.com:443', $level, $bubble); $this->apiToken = $apiToken; } /** * {@inheritdoc} */ public function setFormatter(FormatterInterface $formatter) { if (!$formatter instanceof FlowdockFormatter) { throw new \InvalidArgumentException('The FlowdockHandler requires an instance of Monolog\Formatter\FlowdockFormatter to function correctly'); } return parent::setFormatter($formatter); } /** * Gets the default formatter. * * @return FormatterInterface */ protected function getDefaultFormatter() { throw new \InvalidArgumentException('The FlowdockHandler must be configured (via setFormatter) with an instance of Monolog\Formatter\FlowdockFormatter to function correctly'); } /** * {@inheritdoc} * * @param array $record */ protected function write(array $record) { parent::write($record); $this->closeSocket(); } /** * {@inheritdoc} * * @param array $record * @return string */ protected function generateDataStream($record) { $content = $this->buildContent($record); return $this->buildHeader($content) . $content; } /** * Builds the body of API call * * @param array $record * @return string */ private function buildContent($record) { return json_encode($record['formatted']['flowdock']); } /** * Builds the header of the API Call * * @param string $content * @return string */ private function buildHeader($content) { $header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n"; $header .= "Host: api.flowdock.com\r\n"; $header .= "Content-Type: application/json\r\n"; $header .= "Content-Length: " . strlen($content) . "\r\n"; $header .= "\r\n"; return $header; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use RollbarNotifier; use Exception; use Monolog\Logger; /** * Sends errors to Rollbar * * If the context data contains a `payload` key, that is used as an array * of payload options to RollbarNotifier's report_message/report_exception methods. * * @author Paul Statezny */ class RollbarHandler extends AbstractProcessingHandler { /** * Rollbar notifier * * @var RollbarNotifier */ protected $rollbarNotifier; /** * Records whether any log records have been added since the last flush of the rollbar notifier * * @var bool */ private $hasRecords = false; /** * @param RollbarNotifier $rollbarNotifier RollbarNotifier object constructed with valid token * @param int $level The minimum logging level at which this handler will be triggered * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(RollbarNotifier $rollbarNotifier, $level = Logger::ERROR, $bubble = true) { $this->rollbarNotifier = $rollbarNotifier; parent::__construct($level, $bubble); } /** * {@inheritdoc} */ protected function write(array $record) { if (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) { $context = $record['context']; $exception = $context['exception']; unset($context['exception']); $payload = array(); if (isset($context['payload'])) { $payload = $context['payload']; unset($context['payload']); } $this->rollbarNotifier->report_exception($exception, $context, $payload); } else { $extraData = array( 'level' => $record['level'], 'channel' => $record['channel'], 'datetime' => $record['datetime']->format('U'), ); $context = $record['context']; $payload = array(); if (isset($context['payload'])) { $payload = $context['payload']; unset($context['payload']); } $this->rollbarNotifier->report_message( $record['message'], $record['level_name'], array_merge($record['context'], $record['extra'], $extraData), $payload ); } $this->hasRecords = true; } /** * {@inheritdoc} */ public function close() { if ($this->hasRecords) { $this->rollbarNotifier->flush(); $this->hasRecords = false; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Psr\Log\LoggerInterface; /** * Proxies log messages to an existing PSR-3 compliant logger. * * @author Michael Moussa */ class PsrHandler extends AbstractHandler { /** * PSR-3 compliant logger * * @var LoggerInterface */ protected $logger; /** * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); $this->logger = $logger; } /** * {@inheritDoc} */ public function handle(array $record) { if (!$this->isHandling($record)) { return false; } $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']); return false === $this->bubble; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Base Handler class providing the Handler structure * * Classes extending it should (in most cases) only implement write($record) * * @author Jordi Boggiano * @author Christophe Coevoet */ abstract class AbstractProcessingHandler extends AbstractHandler { /** * {@inheritdoc} */ public function handle(array $record) { if (!$this->isHandling($record)) { return false; } $record = $this->processRecord($record); $record['formatted'] = $this->getFormatter()->format($record); $this->write($record); return false === $this->bubble; } /** * Writes the record down to the log of the implementing handler * * @param array $record * @return void */ abstract protected function write(array $record); /** * Processes a record. * * @param array $record * @return array */ protected function processRecord(array $record) { if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } return $record; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Buffers all records until closing the handler and then pass them as batch. * * This is useful for a MailHandler to send only one mail per request instead of * sending one per log message. * * @author Christophe Coevoet */ class BufferHandler extends AbstractHandler { protected $handler; protected $bufferSize = 0; protected $bufferLimit; protected $flushOnOverflow; protected $buffer = array(); protected $initialized = false; /** * @param HandlerInterface $handler Handler. * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not * @param Boolean $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded */ public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false) { parent::__construct($level, $bubble); $this->handler = $handler; $this->bufferLimit = (int) $bufferLimit; $this->flushOnOverflow = $flushOnOverflow; } /** * {@inheritdoc} */ public function handle(array $record) { if ($record['level'] < $this->level) { return false; } if (!$this->initialized) { // __destructor() doesn't get called on Fatal errors register_shutdown_function(array($this, 'close')); $this->initialized = true; } if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) { if ($this->flushOnOverflow) { $this->flush(); } else { array_shift($this->buffer); $this->bufferSize--; } } if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } $this->buffer[] = $record; $this->bufferSize++; return false === $this->bubble; } public function flush() { if ($this->bufferSize === 0) { return; } $this->handler->handleBatch($this->buffer); $this->clear(); } public function __destruct() { // suppress the parent behavior since we already have register_shutdown_function() // to call close(), and the reference contained there will prevent this from being // GC'd until the end of the request } /** * {@inheritdoc} */ public function close() { $this->flush(); } /** * Clears the buffer without flushing any messages down to the wrapped handler. */ public function clear() { $this->bufferSize = 0; $this->buffer = array(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\FingersCrossed; use Monolog\Logger; /** * Error level based activation strategy. * * @author Johannes M. Schmitt */ class ErrorLevelActivationStrategy implements ActivationStrategyInterface { private $actionLevel; public function __construct($actionLevel) { $this->actionLevel = Logger::toMonologLevel($actionLevel); } public function isHandlerActivated(array $record) { return $record['level'] >= $this->actionLevel; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\FingersCrossed; /** * Interface for activation strategies for the FingersCrossedHandler. * * @author Johannes M. Schmitt */ interface ActivationStrategyInterface { /** * Returns whether the given record activates the handler. * * @param array $record * @return Boolean */ public function isHandlerActivated(array $record); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\FingersCrossed; use Monolog\Logger; /** * Channel and Error level based monolog activation strategy. Allows to trigger activation * based on level per channel. e.g. trigger activation on level 'ERROR' by default, except * for records of the 'sql' channel; those should trigger activation on level 'WARN'. * * Example: * * * $activationStrategy = new ChannelLevelActivationStrategy( * Logger::CRITICAL, * array( * 'request' => Logger::ALERT, * 'sensitive' => Logger::ERROR, * ) * ); * $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy); * * * @author Mike Meessen */ class ChannelLevelActivationStrategy implements ActivationStrategyInterface { private $defaultActionLevel; private $channelToActionLevel; /** * @param int $defaultActionLevel The default action level to be used if the record's category doesn't match any * @param array $channelToActionLevel An array that maps channel names to action levels. */ public function __construct($defaultActionLevel, $channelToActionLevel = array()) { $this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel); $this->channelToActionLevel = array_map('Monolog\Logger::toMonologLevel', $channelToActionLevel); } public function isHandlerActivated(array $record) { if (isset($this->channelToActionLevel[$record['channel']])) { return $record['level'] >= $this->channelToActionLevel[$record['channel']]; } return $record['level'] >= $this->defaultActionLevel; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * MandrillHandler uses cURL to send the emails to the Mandrill API * * @author Adam Nicholson */ class MandrillHandler extends MailHandler { protected $message; protected $apiKey; /** * @param string $apiKey A valid Mandrill API key * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($apiKey, $message, $level = Logger::ERROR, $bubble = true) { parent::__construct($level, $bubble); if (!$message instanceof \Swift_Message && is_callable($message)) { $message = call_user_func($message); } if (!$message instanceof \Swift_Message) { throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it'); } $this->message = $message; $this->apiKey = $apiKey; } /** * {@inheritdoc} */ protected function send($content, array $records) { $message = clone $this->message; $message->setBody($content); $message->setDate(time()); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array( 'key' => $this->apiKey, 'raw_message' => (string) $message, 'async' => false, ))); Curl\Util::execute($ch); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\LineFormatter; /** * Common syslog functionality */ abstract class AbstractSyslogHandler extends AbstractProcessingHandler { protected $facility; /** * Translates Monolog log levels to syslog log priorities. */ protected $logLevels = array( Logger::DEBUG => LOG_DEBUG, Logger::INFO => LOG_INFO, Logger::NOTICE => LOG_NOTICE, Logger::WARNING => LOG_WARNING, Logger::ERROR => LOG_ERR, Logger::CRITICAL => LOG_CRIT, Logger::ALERT => LOG_ALERT, Logger::EMERGENCY => LOG_EMERG, ); /** * List of valid log facility names. */ protected $facilities = array( 'auth' => LOG_AUTH, 'authpriv' => LOG_AUTHPRIV, 'cron' => LOG_CRON, 'daemon' => LOG_DAEMON, 'kern' => LOG_KERN, 'lpr' => LOG_LPR, 'mail' => LOG_MAIL, 'news' => LOG_NEWS, 'syslog' => LOG_SYSLOG, 'user' => LOG_USER, 'uucp' => LOG_UUCP, ); /** * @param mixed $facility * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { $this->facilities['local0'] = LOG_LOCAL0; $this->facilities['local1'] = LOG_LOCAL1; $this->facilities['local2'] = LOG_LOCAL2; $this->facilities['local3'] = LOG_LOCAL3; $this->facilities['local4'] = LOG_LOCAL4; $this->facilities['local5'] = LOG_LOCAL5; $this->facilities['local6'] = LOG_LOCAL6; $this->facilities['local7'] = LOG_LOCAL7; } else { $this->facilities['local0'] = 128; // LOG_LOCAL0 $this->facilities['local1'] = 136; // LOG_LOCAL1 $this->facilities['local2'] = 144; // LOG_LOCAL2 $this->facilities['local3'] = 152; // LOG_LOCAL3 $this->facilities['local4'] = 160; // LOG_LOCAL4 $this->facilities['local5'] = 168; // LOG_LOCAL5 $this->facilities['local6'] = 176; // LOG_LOCAL6 $this->facilities['local7'] = 184; // LOG_LOCAL7 } // convert textual description of facility to syslog constant if (array_key_exists(strtolower($facility), $this->facilities)) { $facility = $this->facilities[strtolower($facility)]; } elseif (!in_array($facility, array_values($this->facilities), true)) { throw new \UnexpectedValueException('Unknown facility value "'.$facility.'" given'); } $this->facility = $facility; } /** * {@inheritdoc} */ protected function getDefaultFormatter() { return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\LogglyFormatter; /** * Sends errors to Loggly. * * @author Przemek Sobstel * @author Adam Pancutt * @author Gregory Barchard */ class LogglyHandler extends AbstractProcessingHandler { const HOST = 'logs-01.loggly.com'; const ENDPOINT_SINGLE = 'inputs'; const ENDPOINT_BATCH = 'bulk'; protected $token; protected $tag = array(); public function __construct($token, $level = Logger::DEBUG, $bubble = true) { if (!extension_loaded('curl')) { throw new \LogicException('The curl extension is needed to use the LogglyHandler'); } $this->token = $token; parent::__construct($level, $bubble); } public function setTag($tag) { $tag = !empty($tag) ? $tag : array(); $this->tag = is_array($tag) ? $tag : array($tag); } public function addTag($tag) { if (!empty($tag)) { $tag = is_array($tag) ? $tag : array($tag); $this->tag = array_unique(array_merge($this->tag, $tag)); } } protected function write(array $record) { $this->send($record["formatted"], self::ENDPOINT_SINGLE); } public function handleBatch(array $records) { $level = $this->level; $records = array_filter($records, function ($record) use ($level) { return ($record['level'] >= $level); }); if ($records) { $this->send($this->getFormatter()->formatBatch($records), self::ENDPOINT_BATCH); } } protected function send($data, $endpoint) { $url = sprintf("https://%s/%s/%s/", self::HOST, $endpoint, $this->token); $headers = array('Content-Type: application/json'); if (!empty($this->tag)) { $headers[] = 'X-LOGGLY-TAG: '.implode(',', $this->tag); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); Curl\Util::execute($ch); } protected function getDefaultFormatter() { return new LogglyFormatter(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Simple handler wrapper that filters records based on a list of levels * * It can be configured with an exact list of levels to allow, or a min/max level. * * @author Hennadiy Verkh * @author Jordi Boggiano */ class FilterHandler extends AbstractHandler { /** * Handler or factory callable($record, $this) * * @var callable|\Monolog\Handler\HandlerInterface */ protected $handler; /** * Minimum level for logs that are passed to handler * * @var int[] */ protected $acceptedLevels; /** * Whether the messages that are handled can bubble up the stack or not * * @var Boolean */ protected $bubble; /** * @param callable|HandlerInterface $handler Handler or factory callable($record, $this). * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided * @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, $bubble = true) { $this->handler = $handler; $this->bubble = $bubble; $this->setAcceptedLevels($minLevelOrList, $maxLevel); if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); } } /** * @return array */ public function getAcceptedLevels() { return array_flip($this->acceptedLevels); } /** * @param int|string|array $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided * @param int|string $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array */ public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY) { if (is_array($minLevelOrList)) { $acceptedLevels = array_map('Monolog\Logger::toMonologLevel', $minLevelOrList); } else { $minLevelOrList = Logger::toMonologLevel($minLevelOrList); $maxLevel = Logger::toMonologLevel($maxLevel); $acceptedLevels = array_values(array_filter(Logger::getLevels(), function ($level) use ($minLevelOrList, $maxLevel) { return $level >= $minLevelOrList && $level <= $maxLevel; })); } $this->acceptedLevels = array_flip($acceptedLevels); } /** * {@inheritdoc} */ public function isHandling(array $record) { return isset($this->acceptedLevels[$record['level']]); } /** * {@inheritdoc} */ public function handle(array $record) { if (!$this->isHandling($record)) { return false; } // The same logic as in FingersCrossedHandler if (!$this->handler instanceof HandlerInterface) { $this->handler = call_user_func($this->handler, $record, $this); if (!$this->handler instanceof HandlerInterface) { throw new \RuntimeException("The factory callable should return a HandlerInterface"); } } if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } $this->handler->handle($record); return false === $this->bubble; } /** * {@inheritdoc} */ public function handleBatch(array $records) { $filtered = array(); foreach ($records as $record) { if ($this->isHandling($record)) { $filtered[] = $record; } } $this->handler->handleBatch($filtered); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Aws\Common\Aws; use Aws\DynamoDb\DynamoDbClient; use Monolog\Formatter\ScalarFormatter; use Monolog\Logger; /** * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/) * * @link https://github.com/aws/aws-sdk-php/ * @author Andrew Lawson */ class DynamoDbHandler extends AbstractProcessingHandler { const DATE_FORMAT = 'Y-m-d\TH:i:s.uO'; /** * @var DynamoDbClient */ protected $client; /** * @var string */ protected $table; /** * @param DynamoDbClient $client * @param string $table * @param int $level * @param bool $bubble */ public function __construct(DynamoDbClient $client, $table, $level = Logger::DEBUG, $bubble = true) { if (!defined('Aws\Common\Aws::VERSION') || version_compare('3.0', Aws::VERSION, '<=')) { throw new \RuntimeException('The DynamoDbHandler is only known to work with the AWS SDK 2.x releases'); } $this->client = $client; $this->table = $table; parent::__construct($level, $bubble); } /** * {@inheritdoc} */ protected function write(array $record) { $filtered = $this->filterEmptyFields($record['formatted']); $formatted = $this->client->formatAttributes($filtered); $this->client->putItem(array( 'TableName' => $this->table, 'Item' => $formatted, )); } /** * @param array $record * @return array */ protected function filterEmptyFields(array $record) { return array_filter($record, function ($value) { return !empty($value) || false === $value || 0 === $value; }); } /** * {@inheritdoc} */ protected function getDefaultFormatter() { return new ScalarFormatter(self::DATE_FORMAT); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\SyslogUdp; class UdpSocket { const DATAGRAM_MAX_LENGTH = 65023; protected $ip; protected $port; protected $socket; public function __construct($ip, $port = 514) { $this->ip = $ip; $this->port = $port; $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); } public function write($line, $header = "") { $this->send($this->assembleMessage($line, $header)); } public function close() { if (is_resource($this->socket)) { socket_close($this->socket); $this->socket = null; } } protected function send($chunk) { if (!is_resource($this->socket)) { throw new \LogicException('The UdpSocket to '.$this->ip.':'.$this->port.' has been closed and can not be written to anymore'); } socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port); } protected function assembleMessage($line, $header) { $chunkSize = self::DATAGRAM_MAX_LENGTH - strlen($header); return $header . substr($line, 0, $chunkSize); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; /** * Forwards records to multiple handlers * * @author Lenar Lõhmus */ class GroupHandler extends AbstractHandler { protected $handlers; /** * @param array $handlers Array of Handlers. * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(array $handlers, $bubble = true) { foreach ($handlers as $handler) { if (!$handler instanceof HandlerInterface) { throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.'); } } $this->handlers = $handlers; $this->bubble = $bubble; } /** * {@inheritdoc} */ public function isHandling(array $record) { foreach ($this->handlers as $handler) { if ($handler->isHandling($record)) { return true; } } return false; } /** * {@inheritdoc} */ public function handle(array $record) { if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } foreach ($this->handlers as $handler) { $handler->handle($record); } return false === $this->bubble; } /** * {@inheritdoc} */ public function handleBatch(array $records) { foreach ($this->handlers as $handler) { $handler->handleBatch($records); } } /** * {@inheritdoc} */ public function setFormatter(FormatterInterface $formatter) { foreach ($this->handlers as $handler) { $handler->setFormatter($formatter); } return $this; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\ChromePHPFormatter; use Monolog\Logger; /** * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/) * * This also works out of the box with Firefox 43+ * * @author Christophe Coevoet */ class ChromePHPHandler extends AbstractProcessingHandler { /** * Version of the extension */ const VERSION = '4.0'; /** * Header name */ const HEADER_NAME = 'X-ChromeLogger-Data'; /** * Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+) */ const USER_AGENT_REGEX = '{\b(?:Chrome/\d+(?:\.\d+)*|Firefox/(?:4[3-9]|[5-9]\d|\d{3,})(?:\.\d)*)\b}'; protected static $initialized = false; /** * Tracks whether we sent too much data * * Chrome limits the headers to 256KB, so when we sent 240KB we stop sending * * @var Boolean */ protected static $overflowed = false; protected static $json = array( 'version' => self::VERSION, 'columns' => array('label', 'log', 'backtrace', 'type'), 'rows' => array(), ); protected static $sendHeaders = true; /** * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); if (!function_exists('json_encode')) { throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s ChromePHPHandler'); } } /** * {@inheritdoc} */ public function handleBatch(array $records) { $messages = array(); foreach ($records as $record) { if ($record['level'] < $this->level) { continue; } $messages[] = $this->processRecord($record); } if (!empty($messages)) { $messages = $this->getFormatter()->formatBatch($messages); self::$json['rows'] = array_merge(self::$json['rows'], $messages); $this->send(); } } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new ChromePHPFormatter(); } /** * Creates & sends header for a record * * @see sendHeader() * @see send() * @param array $record */ protected function write(array $record) { self::$json['rows'][] = $record['formatted']; $this->send(); } /** * Sends the log header * * @see sendHeader() */ protected function send() { if (self::$overflowed || !self::$sendHeaders) { return; } if (!self::$initialized) { self::$initialized = true; self::$sendHeaders = $this->headersAccepted(); if (!self::$sendHeaders) { return; } self::$json['request_uri'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; } $json = @json_encode(self::$json); $data = base64_encode(utf8_encode($json)); if (strlen($data) > 240 * 1024) { self::$overflowed = true; $record = array( 'message' => 'Incomplete logs, chrome header size limit reached', 'context' => array(), 'level' => Logger::WARNING, 'level_name' => Logger::getLevelName(Logger::WARNING), 'channel' => 'monolog', 'datetime' => new \DateTime(), 'extra' => array(), ); self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record); $json = @json_encode(self::$json); $data = base64_encode(utf8_encode($json)); } if (trim($data) !== '') { $this->sendHeader(self::HEADER_NAME, $data); } } /** * Send header string to the client * * @param string $header * @param string $content */ protected function sendHeader($header, $content) { if (!headers_sent() && self::$sendHeaders) { header(sprintf('%s: %s', $header, $content)); } } /** * Verifies if the headers are accepted by the current user agent * * @return Boolean */ protected function headersAccepted() { if (empty($_SERVER['HTTP_USER_AGENT'])) { return false; } return preg_match(self::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']); } /** * BC getter for the sendHeaders property that has been made static */ public function __get($property) { if ('sendHeaders' !== $property) { throw new \InvalidArgumentException('Undefined property '.$property); } return static::$sendHeaders; } /** * BC setter for the sendHeaders property that has been made static */ public function __set($property, $value) { if ('sendHeaders' !== $property) { throw new \InvalidArgumentException('Undefined property '.$property); } static::$sendHeaders = $value; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Exception can be thrown if an extension for an handler is missing * * @author Christian Bergau */ class MissingExtensionException extends \Exception { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Logs to Cube. * * @link http://square.github.com/cube/ * @author Wan Chen */ class CubeHandler extends AbstractProcessingHandler { private $udpConnection; private $httpConnection; private $scheme; private $host; private $port; private $acceptedSchemes = array('http', 'udp'); /** * Create a Cube handler * * @throws \UnexpectedValueException when given url is not a valid url. * A valid url must consist of three parts : protocol://host:port * Only valid protocols used by Cube are http and udp */ public function __construct($url, $level = Logger::DEBUG, $bubble = true) { $urlInfo = parse_url($url); if (!isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) { throw new \UnexpectedValueException('URL "'.$url.'" is not valid'); } if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) { throw new \UnexpectedValueException( 'Invalid protocol (' . $urlInfo['scheme'] . ').' . ' Valid options are ' . implode(', ', $this->acceptedSchemes)); } $this->scheme = $urlInfo['scheme']; $this->host = $urlInfo['host']; $this->port = $urlInfo['port']; parent::__construct($level, $bubble); } /** * Establish a connection to an UDP socket * * @throws \LogicException when unable to connect to the socket * @throws MissingExtensionException when there is no socket extension */ protected function connectUdp() { if (!extension_loaded('sockets')) { throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler'); } $this->udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0); if (!$this->udpConnection) { throw new \LogicException('Unable to create a socket'); } if (!socket_connect($this->udpConnection, $this->host, $this->port)) { throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port); } } /** * Establish a connection to a http server * @throws \LogicException when no curl extension */ protected function connectHttp() { if (!extension_loaded('curl')) { throw new \LogicException('The curl extension is needed to use http URLs with the CubeHandler'); } $this->httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put'); if (!$this->httpConnection) { throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port); } curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true); } /** * {@inheritdoc} */ protected function write(array $record) { $date = $record['datetime']; $data = array('time' => $date->format('Y-m-d\TH:i:s.uO')); unset($record['datetime']); if (isset($record['context']['type'])) { $data['type'] = $record['context']['type']; unset($record['context']['type']); } else { $data['type'] = $record['channel']; } $data['data'] = $record['context']; $data['data']['level'] = $record['level']; if ($this->scheme === 'http') { $this->writeHttp(json_encode($data)); } else { $this->writeUdp(json_encode($data)); } } private function writeUdp($data) { if (!$this->udpConnection) { $this->connectUdp(); } socket_send($this->udpConnection, $data, strlen($data), 0); } private function writeHttp($data) { if (!$this->httpConnection) { $this->connectHttp(); } curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']'); curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen('['.$data.']'), )); Curl\Util::execute($this->httpConnection, 5, false); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; use Monolog\Logger; use Raven_Client; /** * Handler to send messages to a Sentry (https://github.com/getsentry/sentry) server * using raven-php (https://github.com/getsentry/raven-php) * * @author Marc Abramowitz */ class RavenHandler extends AbstractProcessingHandler { /** * Translates Monolog log levels to Raven log levels. */ private $logLevels = array( Logger::DEBUG => Raven_Client::DEBUG, Logger::INFO => Raven_Client::INFO, Logger::NOTICE => Raven_Client::INFO, Logger::WARNING => Raven_Client::WARNING, Logger::ERROR => Raven_Client::ERROR, Logger::CRITICAL => Raven_Client::FATAL, Logger::ALERT => Raven_Client::FATAL, Logger::EMERGENCY => Raven_Client::FATAL, ); /** * @var string should represent the current version of the calling * software. Can be any string (git commit, version number) */ private $release; /** * @var Raven_Client the client object that sends the message to the server */ protected $ravenClient; /** * @var LineFormatter The formatter to use for the logs generated via handleBatch() */ protected $batchFormatter; /** * @param Raven_Client $ravenClient * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); $this->ravenClient = $ravenClient; } /** * {@inheritdoc} */ public function handleBatch(array $records) { $level = $this->level; // filter records based on their level $records = array_filter($records, function ($record) use ($level) { return $record['level'] >= $level; }); if (!$records) { return; } // the record with the highest severity is the "main" one $record = array_reduce($records, function ($highest, $record) { if ($record['level'] >= $highest['level']) { return $record; } return $highest; }); // the other ones are added as a context item $logs = array(); foreach ($records as $r) { $logs[] = $this->processRecord($r); } if ($logs) { $record['context']['logs'] = (string) $this->getBatchFormatter()->formatBatch($logs); } $this->handle($record); } /** * Sets the formatter for the logs generated by handleBatch(). * * @param FormatterInterface $formatter */ public function setBatchFormatter(FormatterInterface $formatter) { $this->batchFormatter = $formatter; } /** * Gets the formatter for the logs generated by handleBatch(). * * @return FormatterInterface */ public function getBatchFormatter() { if (!$this->batchFormatter) { $this->batchFormatter = $this->getDefaultBatchFormatter(); } return $this->batchFormatter; } /** * {@inheritdoc} */ protected function write(array $record) { $previousUserContext = false; $options = array(); $options['level'] = $this->logLevels[$record['level']]; $options['tags'] = array(); if (!empty($record['extra']['tags'])) { $options['tags'] = array_merge($options['tags'], $record['extra']['tags']); unset($record['extra']['tags']); } if (!empty($record['context']['tags'])) { $options['tags'] = array_merge($options['tags'], $record['context']['tags']); unset($record['context']['tags']); } if (!empty($record['context']['fingerprint'])) { $options['fingerprint'] = $record['context']['fingerprint']; unset($record['context']['fingerprint']); } if (!empty($record['context']['logger'])) { $options['logger'] = $record['context']['logger']; unset($record['context']['logger']); } else { $options['logger'] = $record['channel']; } foreach ($this->getExtraParameters() as $key) { foreach (array('extra', 'context') as $source) { if (!empty($record[$source][$key])) { $options[$key] = $record[$source][$key]; unset($record[$source][$key]); } } } if (!empty($record['context'])) { $options['extra']['context'] = $record['context']; if (!empty($record['context']['user'])) { $previousUserContext = $this->ravenClient->context->user; $this->ravenClient->user_context($record['context']['user']); unset($options['extra']['context']['user']); } } if (!empty($record['extra'])) { $options['extra']['extra'] = $record['extra']; } if (!empty($this->release) && !isset($options['release'])) { $options['release'] = $this->release; } if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) { $options['extra']['message'] = $record['formatted']; $this->ravenClient->captureException($record['context']['exception'], $options); } else { $this->ravenClient->captureMessage($record['formatted'], array(), $options); } if ($previousUserContext !== false) { $this->ravenClient->user_context($previousUserContext); } } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new LineFormatter('[%channel%] %message%'); } /** * Gets the default formatter for the logs generated by handleBatch(). * * @return FormatterInterface */ protected function getDefaultBatchFormatter() { return new LineFormatter(); } /** * Gets extra parameters supported by Raven that can be found in "extra" and "context" * * @return array */ protected function getExtraParameters() { return array('checksum', 'release'); } /** * @param string $value */ public function setRelease($value) { $this->release = $value; return $this; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\LineFormatter; /** * SwiftMailerHandler uses Swift_Mailer to send the emails * * @author Gyula Sallai */ class SwiftMailerHandler extends MailHandler { protected $mailer; private $messageTemplate; /** * @param \Swift_Mailer $mailer The mailer to use * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true) { parent::__construct($level, $bubble); $this->mailer = $mailer; $this->messageTemplate = $message; } /** * {@inheritdoc} */ protected function send($content, array $records) { $this->mailer->send($this->buildMessage($content, $records)); } /** * Creates instance of Swift_Message to be sent * * @param string $content formatted email body to be sent * @param array $records Log records that formed the content * @return \Swift_Message */ protected function buildMessage($content, array $records) { $message = null; if ($this->messageTemplate instanceof \Swift_Message) { $message = clone $this->messageTemplate; $message->generateId(); } elseif (is_callable($this->messageTemplate)) { $message = call_user_func($this->messageTemplate, $content, $records); } if (!$message instanceof \Swift_Message) { throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it'); } if ($records) { $subjectFormatter = new LineFormatter($message->getSubject()); $message->setSubject($subjectFormatter->format($this->getHighestRecord($records))); } $message->setBody($content); $message->setDate(time()); return $message; } /** * BC getter, to be removed in 2.0 */ public function __get($name) { if ($name === 'message') { trigger_error('SwiftMailerHandler->message is deprecated, use ->buildMessage() instead to retrieve the message', E_USER_DEPRECATED); return $this->buildMessage(null, array()); } throw new \InvalidArgumentException('Invalid property '.$name); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Sampling handler * * A sampled event stream can be useful for logging high frequency events in * a production environment where you only need an idea of what is happening * and are not concerned with capturing every occurrence. Since the decision to * handle or not handle a particular event is determined randomly, the * resulting sampled log is not guaranteed to contain 1/N of the events that * occurred in the application, but based on the Law of large numbers, it will * tend to be close to this ratio with a large number of attempts. * * @author Bryan Davis * @author Kunal Mehta */ class SamplingHandler extends AbstractHandler { /** * @var callable|HandlerInterface $handler */ protected $handler; /** * @var int $factor */ protected $factor; /** * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler). * @param int $factor Sample factor */ public function __construct($handler, $factor) { parent::__construct(); $this->handler = $handler; $this->factor = $factor; if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); } } public function isHandling(array $record) { return $this->handler->isHandling($record); } public function handle(array $record) { if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) { // The same logic as in FingersCrossedHandler if (!$this->handler instanceof HandlerInterface) { $this->handler = call_user_func($this->handler, $record, $this); if (!$this->handler instanceof HandlerInterface) { throw new \RuntimeException("The factory callable should return a HandlerInterface"); } } if ($this->processors) { foreach ($this->processors as $processor) { $record = call_user_func($processor, $record); } } $this->handler->handle($record); } return false === $this->bubble; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\JsonFormatter; use Monolog\Logger; /** * CouchDB handler * * @author Markus Bachmann */ class CouchDBHandler extends AbstractProcessingHandler { private $options; public function __construct(array $options = array(), $level = Logger::DEBUG, $bubble = true) { $this->options = array_merge(array( 'host' => 'localhost', 'port' => 5984, 'dbname' => 'logger', 'username' => null, 'password' => null, ), $options); parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record) { $basicAuth = null; if ($this->options['username']) { $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']); } $url = 'http://'.$basicAuth.$this->options['host'].':'.$this->options['port'].'/'.$this->options['dbname']; $context = stream_context_create(array( 'http' => array( 'method' => 'POST', 'content' => $record['formatted'], 'ignore_errors' => true, 'max_redirects' => 0, 'header' => 'Content-type: application/json', ), )); if (false === @file_get_contents($url, null, $context)) { throw new \RuntimeException(sprintf('Could not connect to %s', $url)); } } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; /** * Base Handler class providing the Handler structure * * @author Jordi Boggiano */ abstract class AbstractHandler implements HandlerInterface { protected $level = Logger::DEBUG; protected $bubble = true; /** * @var FormatterInterface */ protected $formatter; protected $processors = array(); /** * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($level = Logger::DEBUG, $bubble = true) { $this->setLevel($level); $this->bubble = $bubble; } /** * {@inheritdoc} */ public function isHandling(array $record) { return $record['level'] >= $this->level; } /** * {@inheritdoc} */ public function handleBatch(array $records) { foreach ($records as $record) { $this->handle($record); } } /** * Closes the handler. * * This will be called automatically when the object is destroyed */ public function close() { } /** * {@inheritdoc} */ public function pushProcessor($callback) { if (!is_callable($callback)) { throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given'); } array_unshift($this->processors, $callback); return $this; } /** * {@inheritdoc} */ public function popProcessor() { if (!$this->processors) { throw new \LogicException('You tried to pop from an empty processor stack.'); } return array_shift($this->processors); } /** * {@inheritdoc} */ public function setFormatter(FormatterInterface $formatter) { $this->formatter = $formatter; return $this; } /** * {@inheritdoc} */ public function getFormatter() { if (!$this->formatter) { $this->formatter = $this->getDefaultFormatter(); } return $this->formatter; } /** * Sets minimum logging level at which this handler will be triggered. * * @param int|string $level Level or level name * @return self */ public function setLevel($level) { $this->level = Logger::toMonologLevel($level); return $this; } /** * Gets minimum logging level at which this handler will be triggered. * * @return int */ public function getLevel() { return $this->level; } /** * Sets the bubbling behavior. * * @param Boolean $bubble true means that this handler allows bubbling. * false means that bubbling is not permitted. * @return self */ public function setBubble($bubble) { $this->bubble = $bubble; return $this; } /** * Gets the bubbling behavior. * * @return Boolean true means that this handler allows bubbling. * false means that bubbling is not permitted. */ public function getBubble() { return $this->bubble; } public function __destruct() { try { $this->close(); } catch (\Exception $e) { // do nothing } } /** * Gets the default formatter. * * @return FormatterInterface */ protected function getDefaultFormatter() { return new LineFormatter(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler\Curl; class Util { private static $retriableErrorCodes = array( CURLE_COULDNT_RESOLVE_HOST, CURLE_COULDNT_CONNECT, CURLE_HTTP_NOT_FOUND, CURLE_READ_ERROR, CURLE_OPERATION_TIMEOUTED, CURLE_HTTP_POST_ERROR, CURLE_SSL_CONNECT_ERROR, ); /** * Executes a CURL request with optional retries and exception on failure * * @param resource $ch curl handler * @throws \RuntimeException */ public static function execute($ch, $retries = 5, $closeAfterDone = true) { while ($retries--) { if (curl_exec($ch) === false) { $curlErrno = curl_errno($ch); if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || !$retries) { $curlError = curl_error($ch); if ($closeAfterDone) { curl_close($ch); } throw new \RuntimeException(sprintf('Curl error (code %s): %s', $curlErrno, $curlError)); } continue; } if ($closeAfterDone) { curl_close($ch); } break; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; /** * Interface that all Monolog Handlers must implement * * @author Jordi Boggiano */ interface HandlerInterface { /** * Checks whether the given record will be handled by this handler. * * This is mostly done for performance reasons, to avoid calling processors for nothing. * * Handlers should still check the record levels within handle(), returning false in isHandling() * is no guarantee that handle() will not be called, and isHandling() might not be called * for a given record. * * @param array $record Partial log record containing only a level key * * @return Boolean */ public function isHandling(array $record); /** * Handles a record. * * All records may be passed to this method, and the handler should discard * those that it does not want to handle. * * The return value of this function controls the bubbling process of the handler stack. * Unless the bubbling is interrupted (by returning true), the Logger class will keep on * calling further handlers in the stack with a given log record. * * @param array $record The record to handle * @return Boolean true means that this handler handled the record, and that bubbling is not permitted. * false means the record was either not processed or that this handler allows bubbling. */ public function handle(array $record); /** * Handles a set of records at once. * * @param array $records The records to handle (an array of record arrays) */ public function handleBatch(array $records); /** * Adds a processor in the stack. * * @param callable $callback * @return self */ public function pushProcessor($callback); /** * Removes the processor on top of the stack and returns it. * * @return callable */ public function popProcessor(); /** * Sets the formatter. * * @param FormatterInterface $formatter * @return self */ public function setFormatter(FormatterInterface $formatter); /** * Gets the formatter. * * @return FormatterInterface */ public function getFormatter(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Used for testing purposes. * * It records all records and gives you access to them for verification. * * @author Jordi Boggiano * * @method bool hasEmergency($record) * @method bool hasAlert($record) * @method bool hasCritical($record) * @method bool hasError($record) * @method bool hasWarning($record) * @method bool hasNotice($record) * @method bool hasInfo($record) * @method bool hasDebug($record) * * @method bool hasEmergencyRecords() * @method bool hasAlertRecords() * @method bool hasCriticalRecords() * @method bool hasErrorRecords() * @method bool hasWarningRecords() * @method bool hasNoticeRecords() * @method bool hasInfoRecords() * @method bool hasDebugRecords() * * @method bool hasEmergencyThatContains($message) * @method bool hasAlertThatContains($message) * @method bool hasCriticalThatContains($message) * @method bool hasErrorThatContains($message) * @method bool hasWarningThatContains($message) * @method bool hasNoticeThatContains($message) * @method bool hasInfoThatContains($message) * @method bool hasDebugThatContains($message) * * @method bool hasEmergencyThatMatches($message) * @method bool hasAlertThatMatches($message) * @method bool hasCriticalThatMatches($message) * @method bool hasErrorThatMatches($message) * @method bool hasWarningThatMatches($message) * @method bool hasNoticeThatMatches($message) * @method bool hasInfoThatMatches($message) * @method bool hasDebugThatMatches($message) * * @method bool hasEmergencyThatPasses($message) * @method bool hasAlertThatPasses($message) * @method bool hasCriticalThatPasses($message) * @method bool hasErrorThatPasses($message) * @method bool hasWarningThatPasses($message) * @method bool hasNoticeThatPasses($message) * @method bool hasInfoThatPasses($message) * @method bool hasDebugThatPasses($message) */ class TestHandler extends AbstractProcessingHandler { protected $records = array(); protected $recordsByLevel = array(); public function getRecords() { return $this->records; } public function clear() { $this->records = array(); $this->recordsByLevel = array(); } protected function hasRecordRecords($level) { return isset($this->recordsByLevel[$level]); } protected function hasRecord($record, $level) { if (is_array($record)) { $record = $record['message']; } return $this->hasRecordThatPasses(function ($rec) use ($record) { return $rec['message'] === $record; }, $level); } public function hasRecordThatContains($message, $level) { return $this->hasRecordThatPasses(function ($rec) use ($message) { return strpos($rec['message'], $message) !== false; }, $level); } public function hasRecordThatMatches($regex, $level) { return $this->hasRecordThatPasses(function ($rec) use ($regex) { return preg_match($regex, $rec['message']) > 0; }, $level); } public function hasRecordThatPasses($predicate, $level) { if (!is_callable($predicate)) { throw new \InvalidArgumentException("Expected a callable for hasRecordThatSucceeds"); } if (!isset($this->recordsByLevel[$level])) { return false; } foreach ($this->recordsByLevel[$level] as $i => $rec) { if (call_user_func($predicate, $rec, $i)) { return true; } } return false; } /** * {@inheritdoc} */ protected function write(array $record) { $this->recordsByLevel[$record['level']][] = $record; $this->records[] = $record; } public function __call($method, $args) { if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { $genericMethod = $matches[1] . 'Record' . $matches[3]; $level = constant('Monolog\Logger::' . strtoupper($matches[2])); if (method_exists($this, $genericMethod)) { $args[] = $level; return call_user_func_array(array($this, $genericMethod), $args); } } throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Blackhole * * Any record it can handle will be thrown away. This can be used * to put on top of an existing stack to override it temporarily. * * @author Jordi Boggiano */ class NullHandler extends AbstractHandler { /** * @param int $level The minimum logging level at which this handler will be triggered */ public function __construct($level = Logger::DEBUG) { parent::__construct($level, false); } /** * {@inheritdoc} */ public function handle(array $record) { if ($record['level'] < $this->level) { return false; } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * IFTTTHandler uses cURL to trigger IFTTT Maker actions * * Register a secret key and trigger/event name at https://ifttt.com/maker * * value1 will be the channel from monolog's Logger constructor, * value2 will be the level name (ERROR, WARNING, ..) * value3 will be the log record's message * * @author Nehal Patel */ class IFTTTHandler extends AbstractProcessingHandler { private $eventName; private $secretKey; /** * @param string $eventName The name of the IFTTT Maker event that should be triggered * @param string $secretKey A valid IFTTT secret key * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($eventName, $secretKey, $level = Logger::ERROR, $bubble = true) { $this->eventName = $eventName; $this->secretKey = $secretKey; parent::__construct($level, $bubble); } /** * {@inheritdoc} */ public function write(array $record) { $postData = array( "value1" => $record["channel"], "value2" => $record["level_name"], "value3" => $record["message"], ); $postString = json_encode($postData); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postString); curl_setopt($ch, CURLOPT_HTTPHEADER, array( "Content-Type: application/json", )); Curl\Util::execute($ch); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * @author Robert Kaufmann III */ class LogEntriesHandler extends SocketHandler { /** * @var string */ protected $logToken; /** * @param string $token Log token supplied by LogEntries * @param bool $useSSL Whether or not SSL encryption should be used. * @param int $level The minimum logging level to trigger this handler * @param bool $bubble Whether or not messages that are handled should bubble up the stack. * * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing */ public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true) { if ($useSSL && !extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler'); } $endpoint = $useSSL ? 'ssl://data.logentries.com:443' : 'data.logentries.com:80'; parent::__construct($endpoint, $level, $bubble); $this->logToken = $token; } /** * {@inheritdoc} * * @param array $record * @return string */ protected function generateDataStream($record) { return $this->logToken . ' ' . $record['formatted']; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Stores logs to files that are rotated every day and a limited number of files are kept. * * This rotation is only intended to be used as a workaround. Using logrotate to * handle the rotation is strongly encouraged when you can use it. * * @author Christophe Coevoet * @author Jordi Boggiano */ class RotatingFileHandler extends StreamHandler { protected $filename; protected $maxFiles; protected $mustRotate; protected $nextRotation; protected $filenameFormat; protected $dateFormat; /** * @param string $filename * @param int $maxFiles The maximal amount of files to keep (0 means unlimited) * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) * @param Boolean $useLocking Try to lock log file before doing any writes */ public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) { $this->filename = $filename; $this->maxFiles = (int) $maxFiles; $this->nextRotation = new \DateTime('tomorrow'); $this->filenameFormat = '{filename}-{date}'; $this->dateFormat = 'Y-m-d'; parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking); } /** * {@inheritdoc} */ public function close() { parent::close(); if (true === $this->mustRotate) { $this->rotate(); } } public function setFilenameFormat($filenameFormat, $dateFormat) { $this->filenameFormat = $filenameFormat; $this->dateFormat = $dateFormat; $this->url = $this->getTimedFilename(); $this->close(); } /** * {@inheritdoc} */ protected function write(array $record) { // on the first record written, if the log is new, we should rotate (once per day) if (null === $this->mustRotate) { $this->mustRotate = !file_exists($this->url); } if ($this->nextRotation < $record['datetime']) { $this->mustRotate = true; $this->close(); } parent::write($record); } /** * Rotates the files. */ protected function rotate() { // update filename $this->url = $this->getTimedFilename(); $this->nextRotation = new \DateTime('tomorrow'); // skip GC of old logs if files are unlimited if (0 === $this->maxFiles) { return; } $logFiles = glob($this->getGlobPattern()); if ($this->maxFiles >= count($logFiles)) { // no files to remove return; } // Sorting the files by name to remove the older ones usort($logFiles, function ($a, $b) { return strcmp($b, $a); }); foreach (array_slice($logFiles, $this->maxFiles) as $file) { if (is_writable($file)) { // suppress errors here as unlink() might fail if two processes // are cleaning up/rotating at the same time set_error_handler(function ($errno, $errstr, $errfile, $errline) {}); unlink($file); restore_error_handler(); } } $this->mustRotate = false; } protected function getTimedFilename() { $fileInfo = pathinfo($this->filename); $timedFilename = str_replace( array('{filename}', '{date}'), array($fileInfo['filename'], date($this->dateFormat)), $fileInfo['dirname'] . '/' . $this->filenameFormat ); if (!empty($fileInfo['extension'])) { $timedFilename .= '.'.$fileInfo['extension']; } return $timedFilename; } protected function getGlobPattern() { $fileInfo = pathinfo($this->filename); $glob = str_replace( array('{filename}', '{date}'), array($fileInfo['filename'], '*'), $fileInfo['dirname'] . '/' . $this->filenameFormat ); if (!empty($fileInfo['extension'])) { $glob .= '.'.$fileInfo['extension']; } return $glob; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\NormalizerFormatter; use Monolog\Logger; /** * Handler sending logs to Zend Monitor * * @author Christian Bergau */ class ZendMonitorHandler extends AbstractProcessingHandler { /** * Monolog level / ZendMonitor Custom Event priority map * * @var array */ protected $levelMap = array( Logger::DEBUG => 1, Logger::INFO => 2, Logger::NOTICE => 3, Logger::WARNING => 4, Logger::ERROR => 5, Logger::CRITICAL => 6, Logger::ALERT => 7, Logger::EMERGENCY => 0, ); /** * Construct * * @param int $level * @param bool $bubble * @throws MissingExtensionException */ public function __construct($level = Logger::DEBUG, $bubble = true) { if (!function_exists('zend_monitor_custom_event')) { throw new MissingExtensionException('You must have Zend Server installed in order to use this handler'); } parent::__construct($level, $bubble); } /** * {@inheritdoc} */ protected function write(array $record) { $this->writeZendMonitorCustomEvent( $this->levelMap[$record['level']], $record['message'], $record['formatted'] ); } /** * Write a record to Zend Monitor * * @param int $level * @param string $message * @param array $formatted */ protected function writeZendMonitorCustomEvent($level, $message, $formatted) { zend_monitor_custom_event($level, $message, $formatted); } /** * {@inheritdoc} */ public function getDefaultFormatter() { return new NormalizerFormatter(); } /** * Get the level map * * @return array */ public function getLevelMap() { return $this->levelMap; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Exception; use Monolog\Formatter\LineFormatter; use Monolog\Logger; use PhpConsole\Connector; use PhpConsole\Handler; use PhpConsole\Helper; /** * Monolog handler for Google Chrome extension "PHP Console" * * Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely * * Usage: * 1. Install Google Chrome extension https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef * 2. See overview https://github.com/barbushin/php-console#overview * 3. Install PHP Console library https://github.com/barbushin/php-console#installation * 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png) * * $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler())); * \Monolog\ErrorHandler::register($logger); * echo $undefinedVar; * $logger->addDebug('SELECT * FROM users', array('db', 'time' => 0.012)); * PC::debug($_SERVER); // PHP Console debugger for any type of vars * * @author Sergey Barbushin https://www.linkedin.com/in/barbushin */ class PHPConsoleHandler extends AbstractProcessingHandler { private $options = array( 'enabled' => true, // bool Is PHP Console server enabled 'classesPartialsTraceIgnore' => array('Monolog\\'), // array Hide calls of classes started with... 'debugTagsKeysInContext' => array(0, 'tag'), // bool Is PHP Console server enabled 'useOwnErrorsHandler' => false, // bool Enable errors handling 'useOwnExceptionsHandler' => false, // bool Enable exceptions handling 'sourcesBasePath' => null, // string Base path of all project sources to strip in errors source paths 'registerHelper' => true, // bool Register PhpConsole\Helper that allows short debug calls like PC::debug($var, 'ta.g.s') 'serverEncoding' => null, // string|null Server internal encoding 'headersLimit' => null, // int|null Set headers size limit for your web-server 'password' => null, // string|null Protect PHP Console connection by password 'enableSslOnlyMode' => false, // bool Force connection by SSL for clients with PHP Console installed 'ipMasks' => array(), // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1') 'enableEvalListener' => false, // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required) 'dumperDetectCallbacks' => false, // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings 'dumperLevelLimit' => 5, // int Maximum dumped vars array or object nested dump level 'dumperItemsCountLimit' => 100, // int Maximum dumped var same level array items or object properties number 'dumperItemSizeLimit' => 5000, // int Maximum length of any string or dumped array item 'dumperDumpSizeLimit' => 500000, // int Maximum approximate size of dumped vars result formatted in JSON 'detectDumpTraceAndSource' => false, // bool Autodetect and append trace data to debug 'dataStorage' => null, // PhpConsole\Storage|null Fixes problem with custom $_SESSION handler(see http://goo.gl/Ne8juJ) ); /** @var Connector */ private $connector; /** * @param array $options See \Monolog\Handler\PHPConsoleHandler::$options for more details * @param Connector|null $connector Instance of \PhpConsole\Connector class (optional) * @param int $level * @param bool $bubble * @throws Exception */ public function __construct(array $options = array(), Connector $connector = null, $level = Logger::DEBUG, $bubble = true) { if (!class_exists('PhpConsole\Connector')) { throw new Exception('PHP Console library not found. See https://github.com/barbushin/php-console#installation'); } parent::__construct($level, $bubble); $this->options = $this->initOptions($options); $this->connector = $this->initConnector($connector); } private function initOptions(array $options) { $wrongOptions = array_diff(array_keys($options), array_keys($this->options)); if ($wrongOptions) { throw new Exception('Unknown options: ' . implode(', ', $wrongOptions)); } return array_replace($this->options, $options); } private function initConnector(Connector $connector = null) { if (!$connector) { if ($this->options['dataStorage']) { Connector::setPostponeStorage($this->options['dataStorage']); } $connector = Connector::getInstance(); } if ($this->options['registerHelper'] && !Helper::isRegistered()) { Helper::register(); } if ($this->options['enabled'] && $connector->isActiveClient()) { if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) { $handler = Handler::getInstance(); $handler->setHandleErrors($this->options['useOwnErrorsHandler']); $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']); $handler->start(); } if ($this->options['sourcesBasePath']) { $connector->setSourcesBasePath($this->options['sourcesBasePath']); } if ($this->options['serverEncoding']) { $connector->setServerEncoding($this->options['serverEncoding']); } if ($this->options['password']) { $connector->setPassword($this->options['password']); } if ($this->options['enableSslOnlyMode']) { $connector->enableSslOnlyMode(); } if ($this->options['ipMasks']) { $connector->setAllowedIpMasks($this->options['ipMasks']); } if ($this->options['headersLimit']) { $connector->setHeadersLimit($this->options['headersLimit']); } if ($this->options['detectDumpTraceAndSource']) { $connector->getDebugDispatcher()->detectTraceAndSource = true; } $dumper = $connector->getDumper(); $dumper->levelLimit = $this->options['dumperLevelLimit']; $dumper->itemsCountLimit = $this->options['dumperItemsCountLimit']; $dumper->itemSizeLimit = $this->options['dumperItemSizeLimit']; $dumper->dumpSizeLimit = $this->options['dumperDumpSizeLimit']; $dumper->detectCallbacks = $this->options['dumperDetectCallbacks']; if ($this->options['enableEvalListener']) { $connector->startEvalRequestsListener(); } } return $connector; } public function getConnector() { return $this->connector; } public function getOptions() { return $this->options; } public function handle(array $record) { if ($this->options['enabled'] && $this->connector->isActiveClient()) { return parent::handle($record); } return !$this->bubble; } /** * Writes the record down to the log of the implementing handler * * @param array $record * @return void */ protected function write(array $record) { if ($record['level'] < Logger::NOTICE) { $this->handleDebugRecord($record); } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) { $this->handleExceptionRecord($record); } else { $this->handleErrorRecord($record); } } private function handleDebugRecord(array $record) { $tags = $this->getRecordTags($record); $message = $record['message']; if ($record['context']) { $message .= ' ' . json_encode($this->connector->getDumper()->dump(array_filter($record['context']))); } $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']); } private function handleExceptionRecord(array $record) { $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']); } private function handleErrorRecord(array $record) { $context = $record['context']; $this->connector->getErrorsDispatcher()->dispatchError( isset($context['code']) ? $context['code'] : null, isset($context['message']) ? $context['message'] : $record['message'], isset($context['file']) ? $context['file'] : null, isset($context['line']) ? $context['line'] : null, $this->options['classesPartialsTraceIgnore'] ); } private function getRecordTags(array &$record) { $tags = null; if (!empty($record['context'])) { $context = & $record['context']; foreach ($this->options['debugTagsKeysInContext'] as $key) { if (!empty($context[$key])) { $tags = $context[$key]; if ($key === 0) { array_shift($context); } else { unset($context[$key]); } break; } } } return $tags ?: strtolower($record['level_name']); } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new LineFormatter('%message%'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Stores to any stream resource * * Can be used to store into php://stderr, remote and local files, etc. * * @author Jordi Boggiano */ class StreamHandler extends AbstractProcessingHandler { protected $stream; protected $url; private $errorMessage; protected $filePermission; protected $useLocking; private $dirCreated; /** * @param resource|string $stream * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) * @param Boolean $useLocking Try to lock log file before doing any writes * * @throws \Exception If a missing directory is not buildable * @throws \InvalidArgumentException If stream is not a resource or string */ public function __construct($stream, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) { parent::__construct($level, $bubble); if (is_resource($stream)) { $this->stream = $stream; } elseif (is_string($stream)) { $this->url = $stream; } else { throw new \InvalidArgumentException('A stream must either be a resource or a string.'); } $this->filePermission = $filePermission; $this->useLocking = $useLocking; } /** * {@inheritdoc} */ public function close() { if ($this->url && is_resource($this->stream)) { fclose($this->stream); } $this->stream = null; } /** * Return the currently active stream if it is open * * @return resource|null */ public function getStream() { return $this->stream; } /** * {@inheritdoc} */ protected function write(array $record) { if (!is_resource($this->stream)) { if (!$this->url) { throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().'); } $this->createDir(); $this->errorMessage = null; set_error_handler(array($this, 'customErrorHandler')); $this->stream = fopen($this->url, 'a'); if ($this->filePermission !== null) { @chmod($this->url, $this->filePermission); } restore_error_handler(); if (!is_resource($this->stream)) { $this->stream = null; throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage, $this->url)); } } if ($this->useLocking) { // ignoring errors here, there's not much we can do about them flock($this->stream, LOCK_EX); } fwrite($this->stream, (string) $record['formatted']); if ($this->useLocking) { flock($this->stream, LOCK_UN); } } private function customErrorHandler($code, $msg) { $this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg); } /** * @param string $stream * * @return null|string */ private function getDirFromStream($stream) { $pos = strpos($stream, '://'); if ($pos === false) { return dirname($stream); } if ('file://' === substr($stream, 0, 7)) { return dirname(substr($stream, 7)); } return; } private function createDir() { // Do not try to create dir if it has already been tried. if ($this->dirCreated) { return; } $dir = $this->getDirFromStream($this->url); if (null !== $dir && !is_dir($dir)) { $this->errorMessage = null; set_error_handler(array($this, 'customErrorHandler')); $status = mkdir($dir, 0777, true); restore_error_handler(); if (false === $status) { throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: '.$this->errorMessage, $dir)); } } $this->dirCreated = true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Logs to syslog service. * * usage example: * * $log = new Logger('application'); * $syslog = new SyslogHandler('myfacility', 'local6'); * $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%"); * $syslog->setFormatter($formatter); * $log->pushHandler($syslog); * * @author Sven Paulus */ class SyslogHandler extends AbstractSyslogHandler { protected $ident; protected $logopts; /** * @param string $ident * @param mixed $facility * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID */ public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID) { parent::__construct($facility, $level, $bubble); $this->ident = $ident; $this->logopts = $logopts; } /** * {@inheritdoc} */ public function close() { closelog(); } /** * {@inheritdoc} */ protected function write(array $record) { if (!openlog($this->ident, $this->logopts, $this->facility)) { throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"'); } syslog($this->logLevels[$record['level']], (string) $record['formatted']); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; use Monolog\Formatter\NormalizerFormatter; /** * Logs to a MongoDB database. * * usage example: * * $log = new Logger('application'); * $mongodb = new MongoDBHandler(new \Mongo("mongodb://localhost:27017"), "logs", "prod"); * $log->pushHandler($mongodb); * * @author Thomas Tourlourat */ class MongoDBHandler extends AbstractProcessingHandler { protected $mongoCollection; public function __construct($mongo, $database, $collection, $level = Logger::DEBUG, $bubble = true) { if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo || $mongo instanceof \MongoDB\Client)) { throw new \InvalidArgumentException('MongoClient, Mongo or MongoDB\Client instance required'); } $this->mongoCollection = $mongo->selectCollection($database, $collection); parent::__construct($level, $bubble); } protected function write(array $record) { if ($this->mongoCollection instanceof \MongoDB\Collection) { $this->mongoCollection->insertOne($record["formatted"]); } else { $this->mongoCollection->save($record["formatted"]); } } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new NormalizerFormatter(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Logger; /** * Logs to a Redis key using rpush * * usage example: * * $log = new Logger('application'); * $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod"); * $log->pushHandler($redis); * * @author Thomas Tourlourat */ class RedisHandler extends AbstractProcessingHandler { private $redisClient; private $redisKey; protected $capSize; /** * @param \Predis\Client|\Redis $redis The redis instance * @param string $key The key name to push records to * @param int $level The minimum logging level at which this handler will be triggered * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * @param int $capSize Number of entries to limit list size to */ public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true, $capSize = false) { if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { throw new \InvalidArgumentException('Predis\Client or Redis instance required'); } $this->redisClient = $redis; $this->redisKey = $key; $this->capSize = $capSize; parent::__construct($level, $bubble); } /** * {@inheritDoc} */ protected function write(array $record) { if ($this->capSize) { $this->writeCapped($record); } else { $this->redisClient->rpush($this->redisKey, $record["formatted"]); } } /** * Write and cap the collection * Writes the record to the redis list and caps its * * @param array $record associative record array * @return void */ protected function writeCapped(array $record) { if ($this->redisClient instanceof \Redis) { $this->redisClient->multi() ->rpush($this->redisKey, $record["formatted"]) ->ltrim($this->redisKey, -$this->capSize, -1) ->exec(); } else { $redisKey = $this->redisKey; $capSize = $this->capSize; $this->redisClient->transaction(function ($tx) use ($record, $redisKey, $capSize) { $tx->rpush($redisKey, $record["formatted"]); $tx->ltrim($redisKey, -$capSize, -1); }); } } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new LineFormatter(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\ElasticaFormatter; use Monolog\Logger; use Elastica\Client; use Elastica\Exception\ExceptionInterface; /** * Elastic Search handler * * Usage example: * * $client = new \Elastica\Client(); * $options = array( * 'index' => 'elastic_index_name', * 'type' => 'elastic_doc_type', * ); * $handler = new ElasticSearchHandler($client, $options); * $log = new Logger('application'); * $log->pushHandler($handler); * * @author Jelle Vink */ class ElasticSearchHandler extends AbstractProcessingHandler { /** * @var Client */ protected $client; /** * @var array Handler config options */ protected $options = array(); /** * @param Client $client Elastica Client object * @param array $options Handler configuration * @param int $level The minimum logging level at which this handler will be triggered * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); $this->client = $client; $this->options = array_merge( array( 'index' => 'monolog', // Elastic index name 'type' => 'record', // Elastic document type 'ignore_error' => false, // Suppress Elastica exceptions ), $options ); } /** * {@inheritDoc} */ protected function write(array $record) { $this->bulkSend(array($record['formatted'])); } /** * {@inheritdoc} */ public function setFormatter(FormatterInterface $formatter) { if ($formatter instanceof ElasticaFormatter) { return parent::setFormatter($formatter); } throw new \InvalidArgumentException('ElasticSearchHandler is only compatible with ElasticaFormatter'); } /** * Getter options * @return array */ public function getOptions() { return $this->options; } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new ElasticaFormatter($this->options['index'], $this->options['type']); } /** * {@inheritdoc} */ public function handleBatch(array $records) { $documents = $this->getFormatter()->formatBatch($records); $this->bulkSend($documents); } /** * Use Elasticsearch bulk API to send list of documents * @param array $documents * @throws \RuntimeException */ protected function bulkSend(array $documents) { try { $this->client->addDocuments($documents); } catch (ExceptionInterface $e) { if (!$this->options['ignore_error']) { throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; /** * This simple wrapper class can be used to extend handlers functionality. * * Example: A filtering handle. Inherit from this class, override isHandling() like this * * public function isHandling(array $record) * { * if ($record meets certain conditions) { * return false; * } * return $this->handler->isHandling($record); * } * * @author Alexey Karapetov */ class HandlerWrapper implements HandlerInterface { /** * @var HandlerInterface */ private $handler; /** * HandlerWrapper constructor. * @param HandlerInterface $handler */ public function __construct(HandlerInterface $handler) { $this->handler = $handler; } /** * {@inheritdoc} */ public function isHandling(array $record) { return $this->handler->isHandling($record); } /** * {@inheritdoc} */ public function handle(array $record) { return $this->handler->handle($record); } /** * {@inheritdoc} */ public function handleBatch(array $records) { return $this->handler->handleBatch($records); } /** * {@inheritdoc} */ public function pushProcessor($callback) { $this->handler->pushProcessor($callback); return $this; } /** * {@inheritdoc} */ public function popProcessor() { return $this->handler->popProcessor(); } /** * {@inheritdoc} */ public function setFormatter(FormatterInterface $formatter) { $this->handler->setFormatter($formatter); return $this; } /** * {@inheritdoc} */ public function getFormatter() { return $this->handler->getFormatter(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Monolog\Logger; /** * Sends notifications through the hipchat api to a hipchat room * * Notes: * API token - HipChat API token * Room - HipChat Room Id or name, where messages are sent * Name - Name used to send the message (from) * notify - Should the message trigger a notification in the clients * version - The API version to use (HipChatHandler::API_V1 | HipChatHandler::API_V2) * * @author Rafael Dohms * @see https://www.hipchat.com/docs/api */ class HipChatHandler extends SocketHandler { /** * Use API version 1 */ const API_V1 = 'v1'; /** * Use API version v2 */ const API_V2 = 'v2'; /** * The maximum allowed length for the name used in the "from" field. */ const MAXIMUM_NAME_LENGTH = 15; /** * The maximum allowed length for the message. */ const MAXIMUM_MESSAGE_LENGTH = 9500; /** * @var string */ private $token; /** * @var string */ private $room; /** * @var string */ private $name; /** * @var bool */ private $notify; /** * @var string */ private $format; /** * @var string */ private $host; /** * @var string */ private $version; /** * @param string $token HipChat API Token * @param string $room The room that should be alerted of the message (Id or Name) * @param string $name Name used in the "from" field. * @param bool $notify Trigger a notification in clients or not * @param int $level The minimum logging level at which this handler will be triggered * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * @param bool $useSSL Whether to connect via SSL. * @param string $format The format of the messages (default to text, can be set to html if you have html in the messages) * @param string $host The HipChat server hostname. * @param string $version The HipChat API version (default HipChatHandler::API_V1) */ public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com', $version = self::API_V1) { if ($version == self::API_V1 && !$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) { throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.'); } $connectionString = $useSSL ? 'ssl://'.$host.':443' : $host.':80'; parent::__construct($connectionString, $level, $bubble); $this->token = $token; $this->name = $name; $this->notify = $notify; $this->room = $room; $this->format = $format; $this->host = $host; $this->version = $version; } /** * {@inheritdoc} * * @param array $record * @return string */ protected function generateDataStream($record) { $content = $this->buildContent($record); return $this->buildHeader($content) . $content; } /** * Builds the body of API call * * @param array $record * @return string */ private function buildContent($record) { $dataArray = array( 'notify' => $this->version == self::API_V1 ? ($this->notify ? 1 : 0) : ($this->notify ? 'true' : 'false'), 'message' => $record['formatted'], 'message_format' => $this->format, 'color' => $this->getAlertColor($record['level']), ); if (!$this->validateStringLength($dataArray['message'], static::MAXIMUM_MESSAGE_LENGTH)) { if (function_exists('mb_substr')) { $dataArray['message'] = mb_substr($dataArray['message'], 0, static::MAXIMUM_MESSAGE_LENGTH).' [truncated]'; } else { $dataArray['message'] = substr($dataArray['message'], 0, static::MAXIMUM_MESSAGE_LENGTH).' [truncated]'; } } // if we are using the legacy API then we need to send some additional information if ($this->version == self::API_V1) { $dataArray['room_id'] = $this->room; } // append the sender name if it is set // always append it if we use the v1 api (it is required in v1) if ($this->version == self::API_V1 || $this->name !== null) { $dataArray['from'] = (string) $this->name; } return http_build_query($dataArray); } /** * Builds the header of the API Call * * @param string $content * @return string */ private function buildHeader($content) { if ($this->version == self::API_V1) { $header = "POST /v1/rooms/message?format=json&auth_token={$this->token} HTTP/1.1\r\n"; } else { // needed for rooms with special (spaces, etc) characters in the name $room = rawurlencode($this->room); $header = "POST /v2/room/{$room}/notification?auth_token={$this->token} HTTP/1.1\r\n"; } $header .= "Host: {$this->host}\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($content) . "\r\n"; $header .= "\r\n"; return $header; } /** * Assigns a color to each level of log records. * * @param int $level * @return string */ protected function getAlertColor($level) { switch (true) { case $level >= Logger::ERROR: return 'red'; case $level >= Logger::WARNING: return 'yellow'; case $level >= Logger::INFO: return 'green'; case $level == Logger::DEBUG: return 'gray'; default: return 'yellow'; } } /** * {@inheritdoc} * * @param array $record */ protected function write(array $record) { parent::write($record); $this->closeSocket(); } /** * {@inheritdoc} */ public function handleBatch(array $records) { if (count($records) == 0) { return true; } $batchRecords = $this->combineRecords($records); $handled = false; foreach ($batchRecords as $batchRecord) { if ($this->isHandling($batchRecord)) { $this->write($batchRecord); $handled = true; } } if (!$handled) { return false; } return false === $this->bubble; } /** * Combines multiple records into one. Error level of the combined record * will be the highest level from the given records. Datetime will be taken * from the first record. * * @param $records * @return array */ private function combineRecords($records) { $batchRecord = null; $batchRecords = array(); $messages = array(); $formattedMessages = array(); $level = 0; $levelName = null; $datetime = null; foreach ($records as $record) { $record = $this->processRecord($record); if ($record['level'] > $level) { $level = $record['level']; $levelName = $record['level_name']; } if (null === $datetime) { $datetime = $record['datetime']; } $messages[] = $record['message']; $messageStr = implode(PHP_EOL, $messages); $formattedMessages[] = $this->getFormatter()->format($record); $formattedMessageStr = implode('', $formattedMessages); $batchRecord = array( 'message' => $messageStr, 'formatted' => $formattedMessageStr, 'context' => array(), 'extra' => array(), ); if (!$this->validateStringLength($batchRecord['formatted'], static::MAXIMUM_MESSAGE_LENGTH)) { // Pop the last message and implode the remaining messages $lastMessage = array_pop($messages); $lastFormattedMessage = array_pop($formattedMessages); $batchRecord['message'] = implode(PHP_EOL, $messages); $batchRecord['formatted'] = implode('', $formattedMessages); $batchRecords[] = $batchRecord; $messages = array($lastMessage); $formattedMessages = array($lastFormattedMessage); $batchRecord = null; } } if (null !== $batchRecord) { $batchRecords[] = $batchRecord; } // Set the max level and datetime for all records foreach ($batchRecords as &$batchRecord) { $batchRecord = array_merge( $batchRecord, array( 'level' => $level, 'level_name' => $levelName, 'datetime' => $datetime, ) ); } return $batchRecords; } /** * Validates the length of a string. * * If the `mb_strlen()` function is available, it will use that, as HipChat * allows UTF-8 characters. Otherwise, it will fall back to `strlen()`. * * Note that this might cause false failures in the specific case of using * a valid name with less than 16 characters, but 16 or more bytes, on a * system where `mb_strlen()` is unavailable. * * @param string $str * @param int $length * * @return bool */ private function validateStringLength($str, $length) { if (function_exists('mb_strlen')) { return (mb_strlen($str) <= $length); } return (strlen($str) <= $length); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; /** * Base class for all mail handlers * * @author Gyula Sallai */ abstract class MailHandler extends AbstractProcessingHandler { /** * {@inheritdoc} */ public function handleBatch(array $records) { $messages = array(); foreach ($records as $record) { if ($record['level'] < $this->level) { continue; } $messages[] = $this->processRecord($record); } if (!empty($messages)) { $this->send((string) $this->getFormatter()->formatBatch($messages), $messages); } } /** * Send a mail with the given content * * @param string $content formatted email body to be sent * @param array $records the array of log records that formed this content */ abstract protected function send($content, array $records); /** * {@inheritdoc} */ protected function write(array $record) { $this->send((string) $record['formatted'], array($record)); } protected function getHighestRecord(array $records) { $highestRecord = null; foreach ($records as $record) { if ($highestRecord === null || $highestRecord['level'] < $record['level']) { $highestRecord = $record; } } return $highestRecord; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Handler; use Gelf\IMessagePublisher; use Gelf\PublisherInterface; use Gelf\Publisher; use InvalidArgumentException; use Monolog\Logger; use Monolog\Formatter\GelfMessageFormatter; /** * Handler to send messages to a Graylog2 (http://www.graylog2.org) server * * @author Matt Lehner * @author Benjamin Zikarsky */ class GelfHandler extends AbstractProcessingHandler { /** * @var Publisher the publisher object that sends the message to the server */ protected $publisher; /** * @param PublisherInterface|IMessagePublisher|Publisher $publisher a publisher object * @param int $level The minimum logging level at which this handler will be triggered * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($publisher, $level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); if (!$publisher instanceof Publisher && !$publisher instanceof IMessagePublisher && !$publisher instanceof PublisherInterface) { throw new InvalidArgumentException('Invalid publisher, expected a Gelf\Publisher, Gelf\IMessagePublisher or Gelf\PublisherInterface instance'); } $this->publisher = $publisher; } /** * {@inheritdoc} */ public function close() { $this->publisher = null; } /** * {@inheritdoc} */ protected function write(array $record) { $this->publisher->publish($record['formatted']); } /** * {@inheritDoc} */ protected function getDefaultFormatter() { return new GelfMessageFormatter(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Monolog\Handler\AbstractHandler; /** * Monolog error handler * * A facility to enable logging of runtime errors, exceptions and fatal errors. * * Quick setup: ErrorHandler::register($logger); * * @author Jordi Boggiano */ class ErrorHandler { private $logger; private $previousExceptionHandler; private $uncaughtExceptionLevel; private $previousErrorHandler; private $errorLevelMap; private $hasFatalErrorHandler; private $fatalLevel; private $reservedMemory; private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR); public function __construct(LoggerInterface $logger) { $this->logger = $logger; } /** * Registers a new ErrorHandler for a given Logger * * By default it will handle errors, exceptions and fatal errors * * @param LoggerInterface $logger * @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling * @param int|false $exceptionLevel a LogLevel::* constant, or false to disable exception handling * @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling * @return ErrorHandler */ public static function register(LoggerInterface $logger, $errorLevelMap = array(), $exceptionLevel = null, $fatalLevel = null) { $handler = new static($logger); if ($errorLevelMap !== false) { $handler->registerErrorHandler($errorLevelMap); } if ($exceptionLevel !== false) { $handler->registerExceptionHandler($exceptionLevel); } if ($fatalLevel !== false) { $handler->registerFatalHandler($fatalLevel); } return $handler; } public function registerExceptionHandler($level = null, $callPrevious = true) { $prev = set_exception_handler(array($this, 'handleException')); $this->uncaughtExceptionLevel = $level; if ($callPrevious && $prev) { $this->previousExceptionHandler = $prev; } } public function registerErrorHandler(array $levelMap = array(), $callPrevious = true, $errorTypes = -1) { $prev = set_error_handler(array($this, 'handleError'), $errorTypes); $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap); if ($callPrevious) { $this->previousErrorHandler = $prev ?: true; } } public function registerFatalHandler($level = null, $reservedMemorySize = 20) { register_shutdown_function(array($this, 'handleFatalError')); $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize); $this->fatalLevel = $level; $this->hasFatalErrorHandler = true; } protected function defaultErrorLevelMap() { return array( E_ERROR => LogLevel::CRITICAL, E_WARNING => LogLevel::WARNING, E_PARSE => LogLevel::ALERT, E_NOTICE => LogLevel::NOTICE, E_CORE_ERROR => LogLevel::CRITICAL, E_CORE_WARNING => LogLevel::WARNING, E_COMPILE_ERROR => LogLevel::ALERT, E_COMPILE_WARNING => LogLevel::WARNING, E_USER_ERROR => LogLevel::ERROR, E_USER_WARNING => LogLevel::WARNING, E_USER_NOTICE => LogLevel::NOTICE, E_STRICT => LogLevel::NOTICE, E_RECOVERABLE_ERROR => LogLevel::ERROR, E_DEPRECATED => LogLevel::NOTICE, E_USER_DEPRECATED => LogLevel::NOTICE, ); } /** * @private */ public function handleException($e) { $this->logger->log( $this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel, sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()), array('exception' => $e) ); if ($this->previousExceptionHandler) { call_user_func($this->previousExceptionHandler, $e); } exit(255); } /** * @private */ public function handleError($code, $message, $file = '', $line = 0, $context = array()) { if (!(error_reporting() & $code)) { return; } // fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) { $level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL; $this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line)); } if ($this->previousErrorHandler === true) { return false; } elseif ($this->previousErrorHandler) { return call_user_func($this->previousErrorHandler, $code, $message, $file, $line, $context); } } /** * @private */ public function handleFatalError() { $this->reservedMemory = null; $lastError = error_get_last(); if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) { $this->logger->log( $this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel, 'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'], array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line']) ); if ($this->logger instanceof Logger) { foreach ($this->logger->getHandlers() as $handler) { if ($handler instanceof AbstractHandler) { $handler->close(); } } } } } private static function codeToString($code) { switch ($code) { case E_ERROR: return 'E_ERROR'; case E_WARNING: return 'E_WARNING'; case E_PARSE: return 'E_PARSE'; case E_NOTICE: return 'E_NOTICE'; case E_CORE_ERROR: return 'E_CORE_ERROR'; case E_CORE_WARNING: return 'E_CORE_WARNING'; case E_COMPILE_ERROR: return 'E_COMPILE_ERROR'; case E_COMPILE_WARNING: return 'E_COMPILE_WARNING'; case E_USER_ERROR: return 'E_USER_ERROR'; case E_USER_WARNING: return 'E_USER_WARNING'; case E_USER_NOTICE: return 'E_USER_NOTICE'; case E_STRICT: return 'E_STRICT'; case E_RECOVERABLE_ERROR: return 'E_RECOVERABLE_ERROR'; case E_DEPRECATED: return 'E_DEPRECATED'; case E_USER_DEPRECATED: return 'E_USER_DEPRECATED'; } return 'Unknown PHP error'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Formats data into an associative array of scalar values. * Objects and arrays will be JSON encoded. * * @author Andrew Lawson */ class ScalarFormatter extends NormalizerFormatter { /** * {@inheritdoc} */ public function format(array $record) { foreach ($record as $key => $value) { $record[$key] = $this->normalizeValue($value); } return $record; } /** * @param mixed $value * @return mixed */ protected function normalizeValue($value) { $normalized = $this->normalize($value); if (is_array($normalized) || is_object($normalized)) { return $this->toJson($normalized, true); } return $normalized; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Formats incoming records into a one-line string * * This is especially useful for logging to files * * @author Jordi Boggiano * @author Christophe Coevoet */ class LineFormatter extends NormalizerFormatter { const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"; protected $format; protected $allowInlineLineBreaks; protected $ignoreEmptyContextAndExtra; protected $includeStacktraces; /** * @param string $format The format of the message * @param string $dateFormat The format of the timestamp: one supported by DateTime::format * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries * @param bool $ignoreEmptyContextAndExtra */ public function __construct($format = null, $dateFormat = null, $allowInlineLineBreaks = false, $ignoreEmptyContextAndExtra = false) { $this->format = $format ?: static::SIMPLE_FORMAT; $this->allowInlineLineBreaks = $allowInlineLineBreaks; $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra; parent::__construct($dateFormat); } public function includeStacktraces($include = true) { $this->includeStacktraces = $include; if ($this->includeStacktraces) { $this->allowInlineLineBreaks = true; } } public function allowInlineLineBreaks($allow = true) { $this->allowInlineLineBreaks = $allow; } public function ignoreEmptyContextAndExtra($ignore = true) { $this->ignoreEmptyContextAndExtra = $ignore; } /** * {@inheritdoc} */ public function format(array $record) { $vars = parent::format($record); $output = $this->format; foreach ($vars['extra'] as $var => $val) { if (false !== strpos($output, '%extra.'.$var.'%')) { $output = str_replace('%extra.'.$var.'%', $this->stringify($val), $output); unset($vars['extra'][$var]); } } foreach ($vars['context'] as $var => $val) { if (false !== strpos($output, '%context.'.$var.'%')) { $output = str_replace('%context.'.$var.'%', $this->stringify($val), $output); unset($vars['context'][$var]); } } if ($this->ignoreEmptyContextAndExtra) { if (empty($vars['context'])) { unset($vars['context']); $output = str_replace('%context%', '', $output); } if (empty($vars['extra'])) { unset($vars['extra']); $output = str_replace('%extra%', '', $output); } } foreach ($vars as $var => $val) { if (false !== strpos($output, '%'.$var.'%')) { $output = str_replace('%'.$var.'%', $this->stringify($val), $output); } } return $output; } public function formatBatch(array $records) { $message = ''; foreach ($records as $record) { $message .= $this->format($record); } return $message; } public function stringify($value) { return $this->replaceNewlines($this->convertToString($value)); } protected function normalizeException($e) { // TODO 2.0 only check for Throwable if (!$e instanceof \Exception && !$e instanceof \Throwable) { throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e)); } $previousText = ''; if ($previous = $e->getPrevious()) { do { $previousText .= ', '.get_class($previous).'(code: '.$previous->getCode().'): '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine(); } while ($previous = $previous->getPrevious()); } $str = '[object] ('.get_class($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')'; if ($this->includeStacktraces) { $str .= "\n[stacktrace]\n".$e->getTraceAsString(); } return $str; } protected function convertToString($data) { if (null === $data || is_bool($data)) { return var_export($data, true); } if (is_scalar($data)) { return (string) $data; } if (version_compare(PHP_VERSION, '5.4.0', '>=')) { return $this->toJson($data, true); } return str_replace('\\/', '/', @json_encode($data)); } protected function replaceNewlines($str) { if ($this->allowInlineLineBreaks) { return $str; } return str_replace(array("\r\n", "\r", "\n"), ' ', $str); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Logger; /** * Serializes a log message according to Wildfire's header requirements * * @author Eric Clemmons (@ericclemmons) * @author Christophe Coevoet * @author Kirill chEbba Chebunin */ class WildfireFormatter extends NormalizerFormatter { const TABLE = 'table'; /** * Translates Monolog log levels to Wildfire levels. */ private $logLevels = array( Logger::DEBUG => 'LOG', Logger::INFO => 'INFO', Logger::NOTICE => 'INFO', Logger::WARNING => 'WARN', Logger::ERROR => 'ERROR', Logger::CRITICAL => 'ERROR', Logger::ALERT => 'ERROR', Logger::EMERGENCY => 'ERROR', ); /** * {@inheritdoc} */ public function format(array $record) { // Retrieve the line and file if set and remove them from the formatted extra $file = $line = ''; if (isset($record['extra']['file'])) { $file = $record['extra']['file']; unset($record['extra']['file']); } if (isset($record['extra']['line'])) { $line = $record['extra']['line']; unset($record['extra']['line']); } $record = $this->normalize($record); $message = array('message' => $record['message']); $handleError = false; if ($record['context']) { $message['context'] = $record['context']; $handleError = true; } if ($record['extra']) { $message['extra'] = $record['extra']; $handleError = true; } if (count($message) === 1) { $message = reset($message); } if (isset($record['context'][self::TABLE])) { $type = 'TABLE'; $label = $record['channel'] .': '. $record['message']; $message = $record['context'][self::TABLE]; } else { $type = $this->logLevels[$record['level']]; $label = $record['channel']; } // Create JSON object describing the appearance of the message in the console $json = $this->toJson(array( array( 'Type' => $type, 'File' => $file, 'Line' => $line, 'Label' => $label, ), $message, ), $handleError); // The message itself is a serialization of the above JSON object + it's length return sprintf( '%s|%s|', strlen($json), $json ); } public function formatBatch(array $records) { throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter'); } protected function normalize($data) { if (is_object($data) && !$data instanceof \DateTime) { return $data; } return parent::normalize($data); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Logger; use Gelf\Message; /** * Serializes a log message to GELF * @see http://www.graylog2.org/about/gelf * * @author Matt Lehner */ class GelfMessageFormatter extends NormalizerFormatter { const MAX_LENGTH = 32766; /** * @var string the name of the system for the Gelf log message */ protected $systemName; /** * @var string a prefix for 'extra' fields from the Monolog record (optional) */ protected $extraPrefix; /** * @var string a prefix for 'context' fields from the Monolog record (optional) */ protected $contextPrefix; /** * Translates Monolog log levels to Graylog2 log priorities. */ private $logLevels = array( Logger::DEBUG => 7, Logger::INFO => 6, Logger::NOTICE => 5, Logger::WARNING => 4, Logger::ERROR => 3, Logger::CRITICAL => 2, Logger::ALERT => 1, Logger::EMERGENCY => 0, ); public function __construct($systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_') { parent::__construct('U.u'); $this->systemName = $systemName ?: gethostname(); $this->extraPrefix = $extraPrefix; $this->contextPrefix = $contextPrefix; } /** * {@inheritdoc} */ public function format(array $record) { $record = parent::format($record); if (!isset($record['datetime'], $record['message'], $record['level'])) { throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, '.var_export($record, true).' given'); } $message = new Message(); $message ->setTimestamp($record['datetime']) ->setShortMessage((string) $record['message']) ->setHost($this->systemName) ->setLevel($this->logLevels[$record['level']]); // start count with message length + system name length + 200 for padding / metadata $len = 200 + strlen((string) $record['message']) + strlen($this->systemName); if ($len > self::MAX_LENGTH) { $message->setShortMessage(substr($record['message'], 0, self::MAX_LENGTH - 200)); return $message; } if (isset($record['channel'])) { $message->setFacility($record['channel']); $len += strlen($record['channel']); } if (isset($record['extra']['line'])) { $message->setLine($record['extra']['line']); $len += 10; unset($record['extra']['line']); } if (isset($record['extra']['file'])) { $message->setFile($record['extra']['file']); $len += strlen($record['extra']['file']); unset($record['extra']['file']); } foreach ($record['extra'] as $key => $val) { $val = is_scalar($val) ? $val : $this->toJson($val); $len += strlen($this->extraPrefix . $key . $val); if ($len > self::MAX_LENGTH) { $message->setAdditional($this->extraPrefix . $key, substr($val, 0, self::MAX_LENGTH - $len)); break; } $message->setAdditional($this->extraPrefix . $key, $val); } foreach ($record['context'] as $key => $val) { $val = is_scalar($val) ? $val : $this->toJson($val); $len += strlen($this->contextPrefix . $key . $val); if ($len > self::MAX_LENGTH) { $message->setAdditional($this->contextPrefix . $key, substr($val, 0, self::MAX_LENGTH - $len)); break; } $message->setAdditional($this->contextPrefix . $key, $val); } if (null === $message->getFile() && isset($record['context']['exception']['file'])) { if (preg_match("/^(.+):([0-9]+)$/", $record['context']['exception']['file'], $matches)) { $message->setFile($matches[1]); $message->setLine($matches[2]); } } return $message; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Encodes message information into JSON in a format compatible with Loggly. * * @author Adam Pancutt */ class LogglyFormatter extends JsonFormatter { /** * Overrides the default batch mode to new lines for compatibility with the * Loggly bulk API. * * @param int $batchMode */ public function __construct($batchMode = self::BATCH_MODE_NEWLINES, $appendNewline = false) { parent::__construct($batchMode, $appendNewline); } /** * Appends the 'timestamp' parameter for indexing by Loggly. * * @see https://www.loggly.com/docs/automated-parsing/#json * @see \Monolog\Formatter\JsonFormatter::format() */ public function format(array $record) { if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTime)) { $record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO"); // TODO 2.0 unset the 'datetime' parameter, retained for BC } return parent::format($record); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Formats a record for use with the MongoDBHandler. * * @author Florian Plattner */ class MongoDBFormatter implements FormatterInterface { private $exceptionTraceAsString; private $maxNestingLevel; /** * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2 * @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings */ public function __construct($maxNestingLevel = 3, $exceptionTraceAsString = true) { $this->maxNestingLevel = max($maxNestingLevel, 0); $this->exceptionTraceAsString = (bool) $exceptionTraceAsString; } /** * {@inheritDoc} */ public function format(array $record) { return $this->formatArray($record); } /** * {@inheritDoc} */ public function formatBatch(array $records) { foreach ($records as $key => $record) { $records[$key] = $this->format($record); } return $records; } protected function formatArray(array $record, $nestingLevel = 0) { if ($this->maxNestingLevel == 0 || $nestingLevel <= $this->maxNestingLevel) { foreach ($record as $name => $value) { if ($value instanceof \DateTime) { $record[$name] = $this->formatDate($value, $nestingLevel + 1); } elseif ($value instanceof \Exception) { $record[$name] = $this->formatException($value, $nestingLevel + 1); } elseif (is_array($value)) { $record[$name] = $this->formatArray($value, $nestingLevel + 1); } elseif (is_object($value)) { $record[$name] = $this->formatObject($value, $nestingLevel + 1); } } } else { $record = '[...]'; } return $record; } protected function formatObject($value, $nestingLevel) { $objectVars = get_object_vars($value); $objectVars['class'] = get_class($value); return $this->formatArray($objectVars, $nestingLevel); } protected function formatException(\Exception $exception, $nestingLevel) { $formattedException = array( 'class' => get_class($exception), 'message' => $exception->getMessage(), 'code' => $exception->getCode(), 'file' => $exception->getFile() . ':' . $exception->getLine(), ); if ($this->exceptionTraceAsString === true) { $formattedException['trace'] = $exception->getTraceAsString(); } else { $formattedException['trace'] = $exception->getTrace(); } return $this->formatArray($formattedException, $nestingLevel); } protected function formatDate(\DateTime $value, $nestingLevel) { return new \MongoDate($value->getTimestamp()); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Class FluentdFormatter * * Serializes a log message to Fluentd unix socket protocol * * Fluentd config: * * * type unix * path /var/run/td-agent/td-agent.sock * * * Monolog setup: * * $logger = new Monolog\Logger('fluent.tag'); * $fluentHandler = new Monolog\Handler\SocketHandler('unix:///var/run/td-agent/td-agent.sock'); * $fluentHandler->setFormatter(new Monolog\Formatter\FluentdFormatter()); * $logger->pushHandler($fluentHandler); * * @author Andrius Putna */ class FluentdFormatter implements FormatterInterface { /** * @var bool $levelTag should message level be a part of the fluentd tag */ protected $levelTag = false; public function __construct($levelTag = false) { if (!function_exists('json_encode')) { throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s FluentdUnixFormatter'); } $this->levelTag = (bool) $levelTag; } public function isUsingLevelsInTag() { return $this->levelTag; } public function format(array $record) { $tag = $record['channel']; if ($this->levelTag) { $tag .= '.' . strtolower($record['level_name']); } $message = array( 'message' => $record['message'], 'extra' => $record['extra'], ); if (!$this->levelTag) { $message['level'] = $record['level']; $message['level_name'] = $record['level_name']; } return json_encode(array($tag, $record['datetime']->getTimestamp(), $message)); } public function formatBatch(array $records) { $message = ''; foreach ($records as $record) { $message .= $this->format($record); } return $message; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Logger; /** * Formats a log message according to the ChromePHP array format * * @author Christophe Coevoet */ class ChromePHPFormatter implements FormatterInterface { /** * Translates Monolog log levels to Wildfire levels. */ private $logLevels = array( Logger::DEBUG => 'log', Logger::INFO => 'info', Logger::NOTICE => 'info', Logger::WARNING => 'warn', Logger::ERROR => 'error', Logger::CRITICAL => 'error', Logger::ALERT => 'error', Logger::EMERGENCY => 'error', ); /** * {@inheritdoc} */ public function format(array $record) { // Retrieve the line and file if set and remove them from the formatted extra $backtrace = 'unknown'; if (isset($record['extra']['file'], $record['extra']['line'])) { $backtrace = $record['extra']['file'].' : '.$record['extra']['line']; unset($record['extra']['file'], $record['extra']['line']); } $message = array('message' => $record['message']); if ($record['context']) { $message['context'] = $record['context']; } if ($record['extra']) { $message['extra'] = $record['extra']; } if (count($message) === 1) { $message = reset($message); } return array( $record['channel'], $message, $backtrace, $this->logLevels[$record['level']], ); } public function formatBatch(array $records) { $formatted = array(); foreach ($records as $record) { $formatted[] = $this->format($record); } return $formatted; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * formats the record to be used in the FlowdockHandler * * @author Dominik Liebler */ class FlowdockFormatter implements FormatterInterface { /** * @var string */ private $source; /** * @var string */ private $sourceEmail; /** * @param string $source * @param string $sourceEmail */ public function __construct($source, $sourceEmail) { $this->source = $source; $this->sourceEmail = $sourceEmail; } /** * {@inheritdoc} */ public function format(array $record) { $tags = array( '#logs', '#' . strtolower($record['level_name']), '#' . $record['channel'], ); foreach ($record['extra'] as $value) { $tags[] = '#' . $value; } $subject = sprintf( 'in %s: %s - %s', $this->source, $record['level_name'], $this->getShortMessage($record['message']) ); $record['flowdock'] = array( 'source' => $this->source, 'from_address' => $this->sourceEmail, 'subject' => $subject, 'content' => $record['message'], 'tags' => $tags, 'project' => $this->source, ); return $record; } /** * {@inheritdoc} */ public function formatBatch(array $records) { $formatted = array(); foreach ($records as $record) { $formatted[] = $this->format($record); } return $formatted; } /** * @param string $message * * @return string */ public function getShortMessage($message) { static $hasMbString; if (null === $hasMbString) { $hasMbString = function_exists('mb_strlen'); } $maxLength = 45; if ($hasMbString) { if (mb_strlen($message, 'UTF-8') > $maxLength) { $message = mb_substr($message, 0, $maxLength - 4, 'UTF-8') . ' ...'; } } else { if (strlen($message) > $maxLength) { $message = substr($message, 0, $maxLength - 4) . ' ...'; } } return $message; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Interface for formatters * * @author Jordi Boggiano */ interface FormatterInterface { /** * Formats a log record. * * @param array $record A record to format * @return mixed The formatted record */ public function format(array $record); /** * Formats a set of log records. * * @param array $records A set of records to format * @return mixed The formatted set of records */ public function formatBatch(array $records); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Exception; /** * Encodes whatever record data is passed to it as json * * This can be useful to log to databases or remote APIs * * @author Jordi Boggiano */ class JsonFormatter extends NormalizerFormatter { const BATCH_MODE_JSON = 1; const BATCH_MODE_NEWLINES = 2; protected $batchMode; protected $appendNewline; /** * @var bool */ protected $includeStacktraces = false; /** * @param int $batchMode */ public function __construct($batchMode = self::BATCH_MODE_JSON, $appendNewline = true) { $this->batchMode = $batchMode; $this->appendNewline = $appendNewline; } /** * The batch mode option configures the formatting style for * multiple records. By default, multiple records will be * formatted as a JSON-encoded array. However, for * compatibility with some API endpoints, alternative styles * are available. * * @return int */ public function getBatchMode() { return $this->batchMode; } /** * True if newlines are appended to every formatted record * * @return bool */ public function isAppendingNewlines() { return $this->appendNewline; } /** * {@inheritdoc} */ public function format(array $record) { return $this->toJson($this->normalize($record), true) . ($this->appendNewline ? "\n" : ''); } /** * {@inheritdoc} */ public function formatBatch(array $records) { switch ($this->batchMode) { case static::BATCH_MODE_NEWLINES: return $this->formatBatchNewlines($records); case static::BATCH_MODE_JSON: default: return $this->formatBatchJson($records); } } /** * @param bool $include */ public function includeStacktraces($include = true) { $this->includeStacktraces = $include; } /** * Return a JSON-encoded array of records. * * @param array $records * @return string */ protected function formatBatchJson(array $records) { return $this->toJson($this->normalize($records), true); } /** * Use new lines to separate records instead of a * JSON-encoded array. * * @param array $records * @return string */ protected function formatBatchNewlines(array $records) { $instance = $this; $oldNewline = $this->appendNewline; $this->appendNewline = false; array_walk($records, function (&$value, $key) use ($instance) { $value = $instance->format($value); }); $this->appendNewline = $oldNewline; return implode("\n", $records); } /** * Normalizes given $data. * * @param mixed $data * * @return mixed */ protected function normalize($data) { if (is_array($data) || $data instanceof \Traversable) { $normalized = array(); $count = 1; foreach ($data as $key => $value) { if ($count++ >= 1000) { $normalized['...'] = 'Over 1000 items, aborting normalization'; break; } $normalized[$key] = $this->normalize($value); } return $normalized; } if ($data instanceof Exception) { return $this->normalizeException($data); } return $data; } /** * Normalizes given exception with or without its own stack trace based on * `includeStacktraces` property. * * @param Exception|Throwable $e * * @return array */ protected function normalizeException($e) { // TODO 2.0 only check for Throwable if (!$e instanceof Exception && !$e instanceof \Throwable) { throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e)); } $data = array( 'class' => get_class($e), 'message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile().':'.$e->getLine(), ); if ($this->includeStacktraces) { $trace = $e->getTrace(); foreach ($trace as $frame) { if (isset($frame['file'])) { $data['trace'][] = $frame['file'].':'.$frame['line']; } else { // We should again normalize the frames, because it might contain invalid items $data['trace'][] = $this->normalize($frame); } } } if ($previous = $e->getPrevious()) { $data['previous'] = $this->normalizeException($previous); } return $data; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; /** * Serializes a log message to Logstash Event Format * * @see http://logstash.net/ * @see https://github.com/logstash/logstash/blob/master/lib/logstash/event.rb * * @author Tim Mower */ class LogstashFormatter extends NormalizerFormatter { const V0 = 0; const V1 = 1; /** * @var string the name of the system for the Logstash log message, used to fill the @source field */ protected $systemName; /** * @var string an application name for the Logstash log message, used to fill the @type field */ protected $applicationName; /** * @var string a prefix for 'extra' fields from the Monolog record (optional) */ protected $extraPrefix; /** * @var string a prefix for 'context' fields from the Monolog record (optional) */ protected $contextPrefix; /** * @var int logstash format version to use */ protected $version; /** * @param string $applicationName the application that sends the data, used as the "type" field of logstash * @param string $systemName the system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine * @param string $extraPrefix prefix for extra keys inside logstash "fields" * @param string $contextPrefix prefix for context keys inside logstash "fields", defaults to ctxt_ * @param int $version the logstash format version to use, defaults to 0 */ public function __construct($applicationName, $systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_', $version = self::V0) { // logstash requires a ISO 8601 format date with optional millisecond precision. parent::__construct('Y-m-d\TH:i:s.uP'); $this->systemName = $systemName ?: gethostname(); $this->applicationName = $applicationName; $this->extraPrefix = $extraPrefix; $this->contextPrefix = $contextPrefix; $this->version = $version; } /** * {@inheritdoc} */ public function format(array $record) { $record = parent::format($record); if ($this->version === self::V1) { $message = $this->formatV1($record); } else { $message = $this->formatV0($record); } return $this->toJson($message) . "\n"; } protected function formatV0(array $record) { if (empty($record['datetime'])) { $record['datetime'] = gmdate('c'); } $message = array( '@timestamp' => $record['datetime'], '@source' => $this->systemName, '@fields' => array(), ); if (isset($record['message'])) { $message['@message'] = $record['message']; } if (isset($record['channel'])) { $message['@tags'] = array($record['channel']); $message['@fields']['channel'] = $record['channel']; } if (isset($record['level'])) { $message['@fields']['level'] = $record['level']; } if ($this->applicationName) { $message['@type'] = $this->applicationName; } if (isset($record['extra']['server'])) { $message['@source_host'] = $record['extra']['server']; } if (isset($record['extra']['url'])) { $message['@source_path'] = $record['extra']['url']; } if (!empty($record['extra'])) { foreach ($record['extra'] as $key => $val) { $message['@fields'][$this->extraPrefix . $key] = $val; } } if (!empty($record['context'])) { foreach ($record['context'] as $key => $val) { $message['@fields'][$this->contextPrefix . $key] = $val; } } return $message; } protected function formatV1(array $record) { if (empty($record['datetime'])) { $record['datetime'] = gmdate('c'); } $message = array( '@timestamp' => $record['datetime'], '@version' => 1, 'host' => $this->systemName, ); if (isset($record['message'])) { $message['message'] = $record['message']; } if (isset($record['channel'])) { $message['type'] = $record['channel']; $message['channel'] = $record['channel']; } if (isset($record['level_name'])) { $message['level'] = $record['level_name']; } if ($this->applicationName) { $message['type'] = $this->applicationName; } if (!empty($record['extra'])) { foreach ($record['extra'] as $key => $val) { $message[$this->extraPrefix . $key] = $val; } } if (!empty($record['context'])) { foreach ($record['context'] as $key => $val) { $message[$this->contextPrefix . $key] = $val; } } return $message; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Exception; /** * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets * * @author Jordi Boggiano */ class NormalizerFormatter implements FormatterInterface { const SIMPLE_DATE = "Y-m-d H:i:s"; protected $dateFormat; /** * @param string $dateFormat The format of the timestamp: one supported by DateTime::format */ public function __construct($dateFormat = null) { $this->dateFormat = $dateFormat ?: static::SIMPLE_DATE; if (!function_exists('json_encode')) { throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter'); } } /** * {@inheritdoc} */ public function format(array $record) { return $this->normalize($record); } /** * {@inheritdoc} */ public function formatBatch(array $records) { foreach ($records as $key => $record) { $records[$key] = $this->format($record); } return $records; } protected function normalize($data) { if (null === $data || is_scalar($data)) { if (is_float($data)) { if (is_infinite($data)) { return ($data > 0 ? '' : '-') . 'INF'; } if (is_nan($data)) { return 'NaN'; } } return $data; } if (is_array($data) || $data instanceof \Traversable) { $normalized = array(); $count = 1; foreach ($data as $key => $value) { if ($count++ >= 1000) { $normalized['...'] = 'Over 1000 items, aborting normalization'; break; } $normalized[$key] = $this->normalize($value); } return $normalized; } if ($data instanceof \DateTime) { return $data->format($this->dateFormat); } if (is_object($data)) { // TODO 2.0 only check for Throwable if ($data instanceof Exception || (PHP_VERSION_ID > 70000 && $data instanceof \Throwable)) { return $this->normalizeException($data); } // non-serializable objects that implement __toString stringified if (method_exists($data, '__toString') && !$data instanceof \JsonSerializable) { $value = $data->__toString(); } else { // the rest is json-serialized in some way $value = $this->toJson($data, true); } return sprintf("[object] (%s: %s)", get_class($data), $value); } if (is_resource($data)) { return sprintf('[resource] (%s)', get_resource_type($data)); } return '[unknown('.gettype($data).')]'; } protected function normalizeException($e) { // TODO 2.0 only check for Throwable if (!$e instanceof Exception && !$e instanceof \Throwable) { throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e)); } $data = array( 'class' => get_class($e), 'message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile().':'.$e->getLine(), ); $trace = $e->getTrace(); foreach ($trace as $frame) { if (isset($frame['file'])) { $data['trace'][] = $frame['file'].':'.$frame['line']; } else { // We should again normalize the frames, because it might contain invalid items $data['trace'][] = $this->toJson($this->normalize($frame), true); } } if ($previous = $e->getPrevious()) { $data['previous'] = $this->normalizeException($previous); } return $data; } /** * Return the JSON representation of a value * * @param mixed $data * @param bool $ignoreErrors * @throws \RuntimeException if encoding fails and errors are not ignored * @return string */ protected function toJson($data, $ignoreErrors = false) { // suppress json_encode errors since it's twitchy with some inputs if ($ignoreErrors) { return @$this->jsonEncode($data); } $json = $this->jsonEncode($data); if ($json === false) { $json = $this->handleJsonError(json_last_error(), $data); } return $json; } /** * @param mixed $data * @return string JSON encoded data or null on failure */ private function jsonEncode($data) { if (version_compare(PHP_VERSION, '5.4.0', '>=')) { return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } return json_encode($data); } /** * Handle a json_encode failure. * * If the failure is due to invalid string encoding, try to clean the * input and encode again. If the second encoding iattempt fails, the * inital error is not encoding related or the input can't be cleaned then * raise a descriptive exception. * * @param int $code return code of json_last_error function * @param mixed $data data that was meant to be encoded * @throws \RuntimeException if failure can't be corrected * @return string JSON encoded data after error correction */ private function handleJsonError($code, $data) { if ($code !== JSON_ERROR_UTF8) { $this->throwEncodeError($code, $data); } if (is_string($data)) { $this->detectAndCleanUtf8($data); } elseif (is_array($data)) { array_walk_recursive($data, array($this, 'detectAndCleanUtf8')); } else { $this->throwEncodeError($code, $data); } $json = $this->jsonEncode($data); if ($json === false) { $this->throwEncodeError(json_last_error(), $data); } return $json; } /** * Throws an exception according to a given code with a customized message * * @param int $code return code of json_last_error function * @param mixed $data data that was meant to be encoded * @throws \RuntimeException */ private function throwEncodeError($code, $data) { switch ($code) { case JSON_ERROR_DEPTH: $msg = 'Maximum stack depth exceeded'; break; case JSON_ERROR_STATE_MISMATCH: $msg = 'Underflow or the modes mismatch'; break; case JSON_ERROR_CTRL_CHAR: $msg = 'Unexpected control character found'; break; case JSON_ERROR_UTF8: $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; break; default: $msg = 'Unknown error'; } throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($data, true)); } /** * Detect invalid UTF-8 string characters and convert to valid UTF-8. * * Valid UTF-8 input will be left unmodified, but strings containing * invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed * original encoding of ISO-8859-15. This conversion may result in * incorrect output if the actual encoding was not ISO-8859-15, but it * will be clean UTF-8 output and will not rely on expensive and fragile * detection algorithms. * * Function converts the input in place in the passed variable so that it * can be used as a callback for array_walk_recursive. * * @param mixed &$data Input to check and convert if needed * @private */ public function detectAndCleanUtf8(&$data) { if (is_string($data) && !preg_match('//u', $data)) { $data = preg_replace_callback( '/[\x80-\xFF]+/', function ($m) { return utf8_encode($m[0]); }, $data ); $data = str_replace( array('¤', '¦', '¨', '´', '¸', '¼', '½', '¾'), array('€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'), $data ); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Monolog\Logger; /** * Formats incoming records into an HTML table * * This is especially useful for html email logging * * @author Tiago Brito */ class HtmlFormatter extends NormalizerFormatter { /** * Translates Monolog log levels to html color priorities. */ protected $logLevels = array( Logger::DEBUG => '#cccccc', Logger::INFO => '#468847', Logger::NOTICE => '#3a87ad', Logger::WARNING => '#c09853', Logger::ERROR => '#f0ad4e', Logger::CRITICAL => '#FF7708', Logger::ALERT => '#C12A19', Logger::EMERGENCY => '#000000', ); /** * @param string $dateFormat The format of the timestamp: one supported by DateTime::format */ public function __construct($dateFormat = null) { parent::__construct($dateFormat); } /** * Creates an HTML table row * * @param string $th Row header content * @param string $td Row standard cell content * @param bool $escapeTd false if td content must not be html escaped * @return string */ private function addRow($th, $td = ' ', $escapeTd = true) { $th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8'); if ($escapeTd) { $td = '
'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'
'; } return "\n$th:\n".$td."\n"; } /** * Create a HTML h1 tag * * @param string $title Text to be in the h1 * @param int $level Error level * @return string */ private function addTitle($title, $level) { $title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8'); return '

'.$title.'

'; } /** * Formats a log record. * * @param array $record A record to format * @return mixed The formatted record */ public function format(array $record) { $output = $this->addTitle($record['level_name'], $record['level']); $output .= ''; $output .= $this->addRow('Message', (string) $record['message']); $output .= $this->addRow('Time', $record['datetime']->format($this->dateFormat)); $output .= $this->addRow('Channel', $record['channel']); if ($record['context']) { $embeddedTable = '
'; foreach ($record['context'] as $key => $value) { $embeddedTable .= $this->addRow($key, $this->convertToString($value)); } $embeddedTable .= '
'; $output .= $this->addRow('Context', $embeddedTable, false); } if ($record['extra']) { $embeddedTable = ''; foreach ($record['extra'] as $key => $value) { $embeddedTable .= $this->addRow($key, $this->convertToString($value)); } $embeddedTable .= '
'; $output .= $this->addRow('Extra', $embeddedTable, false); } return $output.''; } /** * Formats a set of log records. * * @param array $records A set of records to format * @return mixed The formatted set of records */ public function formatBatch(array $records) { $message = ''; foreach ($records as $record) { $message .= $this->format($record); } return $message; } protected function convertToString($data) { if (null === $data || is_scalar($data)) { return (string) $data; } $data = $this->normalize($data); if (version_compare(PHP_VERSION, '5.4.0', '>=')) { return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } return str_replace('\\/', '/', json_encode($data)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog\Formatter; use Elastica\Document; /** * Format a log message into an Elastica Document * * @author Jelle Vink */ class ElasticaFormatter extends NormalizerFormatter { /** * @var string Elastic search index name */ protected $index; /** * @var string Elastic search document type */ protected $type; /** * @param string $index Elastic Search index name * @param string $type Elastic Search document type */ public function __construct($index, $type) { // elasticsearch requires a ISO 8601 format date with optional millisecond precision. parent::__construct('Y-m-d\TH:i:s.uP'); $this->index = $index; $this->type = $type; } /** * {@inheritdoc} */ public function format(array $record) { $record = parent::format($record); return $this->getDocument($record); } /** * Getter index * @return string */ public function getIndex() { return $this->index; } /** * Getter type * @return string */ public function getType() { return $this->type; } /** * Convert a log message into an Elastica Document * * @param array $record Log message * @return Document */ protected function getDocument($record) { $document = new Document(); $document->setData($record); $document->setType($this->type); $document->setIndex($this->index); return $document; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Monolog; use InvalidArgumentException; /** * Monolog log registry * * Allows to get `Logger` instances in the global scope * via static method calls on this class. * * * $application = new Monolog\Logger('application'); * $api = new Monolog\Logger('api'); * * Monolog\Registry::addLogger($application); * Monolog\Registry::addLogger($api); * * function testLogger() * { * Monolog\Registry::api()->addError('Sent to $api Logger instance'); * Monolog\Registry::application()->addError('Sent to $application Logger instance'); * } * * * @author Tomas Tatarko */ class Registry { /** * List of all loggers in the registry (by named indexes) * * @var Logger[] */ private static $loggers = array(); /** * Adds new logging channel to the registry * * @param Logger $logger Instance of the logging channel * @param string|null $name Name of the logging channel ($logger->getName() by default) * @param bool $overwrite Overwrite instance in the registry if the given name already exists? * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists */ public static function addLogger(Logger $logger, $name = null, $overwrite = false) { $name = $name ?: $logger->getName(); if (isset(self::$loggers[$name]) && !$overwrite) { throw new InvalidArgumentException('Logger with the given name already exists'); } self::$loggers[$name] = $logger; } /** * Checks if such logging channel exists by name or instance * * @param string|Logger $logger Name or logger instance */ public static function hasLogger($logger) { if ($logger instanceof Logger) { $index = array_search($logger, self::$loggers, true); return false !== $index; } else { return isset(self::$loggers[$logger]); } } /** * Removes instance from registry by name or instance * * @param string|Logger $logger Name or logger instance */ public static function removeLogger($logger) { if ($logger instanceof Logger) { if (false !== ($idx = array_search($logger, self::$loggers, true))) { unset(self::$loggers[$idx]); } } else { unset(self::$loggers[$logger]); } } /** * Clears the registry */ public static function clear() { self::$loggers = array(); } /** * Gets Logger instance from the registry * * @param string $name Name of the requested Logger instance * @throws \InvalidArgumentException If named Logger instance is not in the registry * @return Logger Requested instance of Logger */ public static function getInstance($name) { if (!isset(self::$loggers[$name])) { throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name)); } return self::$loggers[$name]; } /** * Gets Logger instance from the registry via static method call * * @param string $name Name of the requested Logger instance * @param array $arguments Arguments passed to static method call * @throws \InvalidArgumentException If named Logger instance is not in the registry * @return Logger Requested instance of Logger */ public static function __callStatic($name, $arguments) { return self::getInstance($name); } } name = $name; $this->value = $value; } public function getSubNodeNames() { return array('name', 'value'); } } type = $type; $this->byRef = $byRef; $this->variadic = $variadic; $this->name = $name; $this->default = $default; if ($variadic && null !== $default) { throw new Error('Variadic parameter cannot have a default value', $default->getAttributes()); } } public function getSubNodeNames() { return array('type', 'byRef', 'variadic', 'name', 'default'); } } var = $var; } public function getSubNodeNames() { return array('var'); } } cond = $cond; $this->if = $if; $this->else = $else; } public function getSubNodeNames() { return array('cond', 'if', 'else'); } } expr = $expr; $this->class = $class; } public function getSubNodeNames() { return array('expr', 'class'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } var = $var; $this->name = $name; $this->args = $args; } public function getSubNodeNames() { return array('var', 'name', 'args'); } } class = $class; $this->name = $name; } public function getSubNodeNames() { return array('class', 'name'); } } name = $name; } public function getSubNodeNames() { return array('name'); } } left = $left; $this->right = $right; } public function getSubNodeNames() { return array('left', 'right'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } var = $var; } public function getSubNodeNames() { return array('var'); } } class = $class; $this->name = $name; } public function getSubNodeNames() { return array('class', 'name'); } } var = $var; } public function getSubNodeNames() { return array('var'); } } class = $class; $this->args = $args; } public function getSubNodeNames() { return array('class', 'args'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } class = $class; $this->name = $name; $this->args = $args; } public function getSubNodeNames() { return array('class', 'name', 'args'); } } expr = $expr; $this->type = $type; } public function getSubNodeNames() { return array('expr', 'type'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } vars = $vars; } public function getSubNodeNames() { return array('vars'); } } key = $key; $this->value = $value; $this->byRef = $byRef; } public function getSubNodeNames() { return array('key', 'value', 'byRef'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } var = $var; $this->name = $name; } public function getSubNodeNames() { return array('var', 'name'); } } parts = $parts; } public function getSubNodeNames() { return array('parts'); } } key = $key; $this->value = $value; } public function getSubNodeNames() { return array('key', 'value'); } } items = $items; } public function getSubNodeNames() { return array('items'); } } var = $var; $this->expr = $expr; } public function getSubNodeNames() { return array('var', 'expr'); } } name = $name; } public function getSubNodeNames() { return array('name'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } var = $var; $this->dim = $dim; } public function getSubnodeNames() { return array('var', 'dim'); } } var = $var; } public function getSubNodeNames() { return array('var'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } var = $var; $this->expr = $expr; } public function getSubNodeNames() { return array('var', 'expr'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } var = $var; $this->byRef = $byRef; } public function getSubNodeNames() { return array('var', 'byRef'); } } vars = $vars; } public function getSubNodeNames() { return array('vars'); } } false : Whether the closure is static * 'byRef' => false : Whether to return by reference * 'params' => array(): Parameters * 'uses' => array(): use()s * 'returnType' => null : Return type * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct(array $subNodes = array(), array $attributes = array()) { parent::__construct(null, $attributes); $this->static = isset($subNodes['static']) ? $subNodes['static'] : false; $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false; $this->params = isset($subNodes['params']) ? $subNodes['params'] : array(); $this->uses = isset($subNodes['uses']) ? $subNodes['uses'] : array(); $this->returnType = isset($subNodes['returnType']) ? $subNodes['returnType'] : null; $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); } public function getSubNodeNames() { return array('static', 'byRef', 'params', 'uses', 'returnType', 'stmts'); } public function returnsByRef() { return $this->byRef; } public function getParams() { return $this->params; } public function getReturnType() { return $this->returnType; } public function getStmts() { return $this->stmts; } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } var = $var; $this->expr = $expr; } public function getSubNodeNames() { return array('var', 'expr'); } } name = $name; $this->args = $args; } public function getSubNodeNames() { return array('name', 'args'); } } array(): Statements * 'elseifs' => array(): Elseif clauses * 'else' => null : Else clause * @param array $attributes Additional attributes */ public function __construct(Node\Expr $cond, array $subNodes = array(), array $attributes = array()) { parent::__construct(null, $attributes); $this->cond = $cond; $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); $this->elseifs = isset($subNodes['elseifs']) ? $subNodes['elseifs'] : array(); $this->else = isset($subNodes['else']) ? $subNodes['else'] : null; } public function getSubNodeNames() { return array('cond', 'stmts', 'elseifs', 'else'); } } vars = $vars; } public function getSubNodeNames() { return array('vars'); } } vars = $vars; } public function getSubNodeNames() { return array('vars'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } true, 'parent' => true, 'static' => true, ); /** * Constructs a class node. * * @param string|null $name Name * @param array $subNodes Array of the following optional subnodes: * 'type' => 0 : Type * 'extends' => null : Name of extended class * 'implements' => array(): Names of implemented interfaces * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = array(), array $attributes = array()) { parent::__construct(null, $attributes); $this->type = isset($subNodes['type']) ? $subNodes['type'] : 0; $this->name = $name; $this->extends = isset($subNodes['extends']) ? $subNodes['extends'] : null; $this->implements = isset($subNodes['implements']) ? $subNodes['implements'] : array(); $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); if (null !== $this->name && isset(self::$specialNames[strtolower($this->name)])) { throw new Error(sprintf('Cannot use \'%s\' as class name as it is reserved', $this->name)); } if (isset(self::$specialNames[strtolower($this->extends)])) { throw new Error( sprintf('Cannot use \'%s\' as class name as it is reserved', $this->extends), $this->extends->getAttributes() ); } foreach ($this->implements as $interface) { if (isset(self::$specialNames[strtolower($interface)])) { throw new Error( sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), $interface->getAttributes() ); } } } public function getSubNodeNames() { return array('type', 'name', 'extends', 'implements', 'stmts'); } public function isAbstract() { return (bool) ($this->type & self::MODIFIER_ABSTRACT); } public function isFinal() { return (bool) ($this->type & self::MODIFIER_FINAL); } public function isAnonymous() { return null === $this->name; } /** * @internal */ public static function verifyModifier($a, $b) { if ($a & self::VISIBILITY_MODIFER_MASK && $b & self::VISIBILITY_MODIFER_MASK) { throw new Error('Multiple access type modifiers are not allowed'); } if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { throw new Error('Multiple abstract modifiers are not allowed'); } if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) { throw new Error('Multiple static modifiers are not allowed'); } if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { throw new Error('Multiple final modifiers are not allowed'); } if ($a & 48 && $b & 48) { throw new Error('Cannot use the final modifier on an abstract class member'); } } } false : Whether to return by reference * 'params' => array(): Parameters * 'returnType' => null : Return type * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = array(), array $attributes = array()) { parent::__construct(null, $attributes); $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false; $this->name = $name; $this->params = isset($subNodes['params']) ? $subNodes['params'] : array(); $this->returnType = isset($subNodes['returnType']) ? $subNodes['returnType'] : null; $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); } public function getSubNodeNames() { return array('byRef', 'name', 'params', 'returnType', 'stmts'); } public function returnsByRef() { return $this->byRef; } public function getParams() { return $this->params; } public function getReturnType() { return $this->returnType; } public function getStmts() { return $this->stmts; } } MODIFIER_PUBLIC: Type * 'byRef' => false : Whether to return by reference * 'params' => array() : Parameters * 'returnType' => null : Return type * 'stmts' => array() : Statements * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = array(), array $attributes = array()) { parent::__construct(null, $attributes); $this->type = isset($subNodes['type']) ? $subNodes['type'] : 0; $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false; $this->name = $name; $this->params = isset($subNodes['params']) ? $subNodes['params'] : array(); $this->returnType = isset($subNodes['returnType']) ? $subNodes['returnType'] : null; $this->stmts = array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : array(); if ($this->type & Class_::MODIFIER_STATIC) { switch (strtolower($this->name)) { case '__construct': throw new Error(sprintf('Constructor %s() cannot be static', $this->name)); case '__destruct': throw new Error(sprintf('Destructor %s() cannot be static', $this->name)); case '__clone': throw new Error(sprintf('Clone method %s() cannot be static', $this->name)); } } } public function getSubNodeNames() { return array('type', 'byRef', 'name', 'params', 'returnType', 'stmts'); } public function returnsByRef() { return $this->byRef; } public function getParams() { return $this->params; } public function getReturnType() { return $this->returnType; } public function getStmts() { return $this->stmts; } public function isPublic() { return ($this->type & Class_::MODIFIER_PUBLIC) !== 0 || ($this->type & Class_::VISIBILITY_MODIFER_MASK) === 0; } public function isProtected() { return (bool) ($this->type & Class_::MODIFIER_PROTECTED); } public function isPrivate() { return (bool) ($this->type & Class_::MODIFIER_PRIVATE); } public function isAbstract() { return (bool) ($this->type & Class_::MODIFIER_ABSTRACT); } public function isFinal() { return (bool) ($this->type & Class_::MODIFIER_FINAL); } public function isStatic() { return (bool) ($this->type & Class_::MODIFIER_STATIC); } } array(): Init expressions * 'cond' => array(): Loop conditions * 'loop' => array(): Loop expressions * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct(array $subNodes = array(), array $attributes = array()) { parent::__construct(null, $attributes); $this->init = isset($subNodes['init']) ? $subNodes['init'] : array(); $this->cond = isset($subNodes['cond']) ? $subNodes['cond'] : array(); $this->loop = isset($subNodes['loop']) ? $subNodes['loop'] : array(); $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); } public function getSubNodeNames() { return array('init', 'cond', 'loop', 'stmts'); } } type = $type; $this->uses = $uses; } public function getSubNodeNames() { return array('type', 'uses'); } } name = $name; $this->default = $default; } public function getSubNodeNames() { return array('name', 'default'); } } null : Variable to assign key to * 'byRef' => false : Whether to assign value by reference * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = array(), array $attributes = array()) { parent::__construct(null, $attributes); $this->expr = $expr; $this->keyVar = isset($subNodes['keyVar']) ? $subNodes['keyVar'] : null; $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false; $this->valueVar = $valueVar; $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); } public function getSubNodeNames() { return array('expr', 'keyVar', 'byRef', 'valueVar', 'stmts'); } } stmts = $stmts; } public function getSubNodeNames() { return array('stmts'); } } cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() { return array('cond', 'stmts'); } } exprs = $exprs; } public function getSubNodeNames() { return array('exprs'); } } cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() { return array('cond', 'stmts'); } } declares = $declares; $this->stmts = $stmts; } public function getSubNodeNames() { return array('declares', 'stmts'); } } vars = $vars; } public function getSubNodeNames() { return array('vars'); } } type = $type; $this->props = $props; } public function getSubNodeNames() { return array('type', 'props'); } public function isPublic() { return ($this->type & Class_::MODIFIER_PUBLIC) !== 0 || ($this->type & Class_::VISIBILITY_MODIFER_MASK) === 0; } public function isProtected() { return (bool) ($this->type & Class_::MODIFIER_PROTECTED); } public function isPrivate() { return (bool) ($this->type & Class_::MODIFIER_PRIVATE); } public function isStatic() { return (bool) ($this->type & Class_::MODIFIER_STATIC); } } stmts as $stmt) { if ($stmt instanceof ClassMethod) { $methods[] = $stmt; } } return $methods; } /** * Gets method with the given name defined directly in this class/interface/trait. * * @param string $name Name of the method (compared case-insensitively) * * @return ClassMethod|null Method node or null if the method does not exist */ public function getMethod($name) { $lowerName = strtolower($name); foreach ($this->stmts as $stmt) { if ($stmt instanceof ClassMethod && $lowerName === strtolower($stmt->name)) { return $stmt; } } return null; } } consts = $consts; } public function getSubNodeNames() { return array('consts'); } } num = $num; } public function getSubNodeNames() { return array('num'); } } traits = $traits; $this->adaptations = $adaptations; } public function getSubNodeNames() { return array('traits', 'adaptations'); } } type = $type; $this->var = $var; $this->stmts = $stmts; } public function getSubNodeNames() { return array('type', 'var', 'stmts'); } } consts = $consts; } public function getSubNodeNames() { return array('consts'); } } name = $name; $this->stmts = $stmts; } public function getSubNodeNames() { return array('name', 'stmts'); } } cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() { return array('cond', 'stmts'); } } true, 'parent' => true, 'static' => true, ); /** * Constructs a class node. * * @param string $name Name * @param array $subNodes Array of the following optional subnodes: * 'extends' => array(): Name of extended interfaces * 'stmts' => array(): Statements * @param array $attributes Additional attributes */ public function __construct($name, array $subNodes = array(), array $attributes = array()) { parent::__construct(null, $attributes); $this->name = $name; $this->extends = isset($subNodes['extends']) ? $subNodes['extends'] : array(); $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); if (isset(self::$specialNames[strtolower($this->name)])) { throw new Error(sprintf('Cannot use \'%s\' as class name as it is reserved', $this->name)); } foreach ($this->extends as $interface) { if (isset(self::$specialNames[strtolower($interface)])) { throw new Error( sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), $interface->getAttributes() ); } } } public function getSubNodeNames() { return array('name', 'extends', 'stmts'); } } name = $name; $this->default = $default; } public function getSubNodeNames() { return array('name', 'default'); } } cond = $cond; $this->cases = $cases; } public function getSubNodeNames() { return array('cond', 'cases'); } } expr = $expr; } public function getSubNodeNames() { return array('expr'); } } remaining = $remaining; } public function getSubNodeNames() { return array('remaining'); } } getLast(); } if ('self' == strtolower($alias) || 'parent' == strtolower($alias)) { throw new Error(sprintf( 'Cannot use %s as %s because \'%2$s\' is a special class name', $name, $alias )); } parent::__construct(null, $attributes); $this->name = $name; $this->alias = $alias; } public function getSubNodeNames() { return array('name', 'alias'); } } value = $value; } public function getSubNodeNames() { return array('value'); } } value pair node. * * @param string $key Key * @param Node\Expr $value Value * @param array $attributes Additional attributes */ public function __construct($key, Node\Expr $value, array $attributes = array()) { parent::__construct(null, $attributes); $this->key = $key; $this->value = $value; } public function getSubNodeNames() { return array('key', 'value'); } } true, 'parent' => true, 'static' => true, ); /** * Constructs a namespace node. * * @param null|Node\Name $name Name * @param null|Node[] $stmts Statements * @param array $attributes Additional attributes */ public function __construct(Node\Name $name = null, $stmts = array(), array $attributes = array()) { parent::__construct(null, $attributes); $this->name = $name; $this->stmts = $stmts; if (isset(self::$specialNames[strtolower($this->name)])) { throw new Error( sprintf('Cannot use \'%s\' as namespace name', $this->name), $this->name->getAttributes() ); } if (null !== $this->stmts) { foreach ($this->stmts as $stmt) { if ($stmt instanceof self) { throw new Error('Namespace declarations cannot be nested', $stmt->getAttributes()); } } } } public function getSubNodeNames() { return array('name', 'stmts'); } } num = $num; } public function getSubNodeNames() { return array('num'); } } name = $name; } public function getSubNodeNames() { return array('name'); } } stmts = $stmts; $this->catches = $catches; $this->finallyStmts = $finallyStmts; } public function getSubNodeNames() { return array('stmts', 'catches', 'finallyStmts'); } } name = $name; } public function getSubNodeNames() { return array('name'); } } trait = $trait; $this->method = $method; $this->insteadof = $insteadof; } public function getSubNodeNames() { return array('trait', 'method', 'insteadof'); } } trait = $trait; $this->method = $method; $this->newModifier = $newModifier; $this->newName = $newName; } public function getSubNodeNames() { return array('trait', 'method', 'newModifier', 'newName'); } } cond = $cond; $this->stmts = $stmts; } public function getSubNodeNames() { return array('cond', 'stmts'); } } '\\', '$' => '$', 'n' => "\n", 'r' => "\r", 't' => "\t", 'f' => "\f", 'v' => "\v", 'e' => "\x1B", ); /** * Constructs a string scalar node. * * @param string $value Value of the string * @param array $attributes Additional attributes */ public function __construct($value = '', array $attributes = array()) { parent::__construct(null, $attributes); $this->value = $value; } public function getSubNodeNames() { return array('value'); } /** * @internal * * Parses a string token. * * @param string $str String token content * * @return string The parsed string */ public static function parse($str) { $bLength = 0; if ('b' === $str[0]) { $bLength = 1; } if ('\'' === $str[$bLength]) { return str_replace( array('\\\\', '\\\''), array( '\\', '\''), substr($str, $bLength + 1, -1) ); } else { return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"'); } } /** * @internal * * Parses escape sequences in strings (all string types apart from single quoted). * * @param string $str String without quotes * @param null|string $quote Quote type * * @return string String with escape sequences parsed */ public static function parseEscapeSequences($str, $quote) { if (null !== $quote) { $str = str_replace('\\' . $quote, $quote, $str); } return preg_replace_callback( '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~', array(__CLASS__, 'parseCallback'), $str ); } private static function parseCallback($matches) { $str = $matches[1]; if (isset(self::$replacements[$str])) { return self::$replacements[$str]; } elseif ('x' === $str[0] || 'X' === $str[0]) { return chr(hexdec($str)); } else { return chr(octdec($str)); } } /** * @internal * * Parses a constant doc string. * * @param string $startToken Doc string start token content (<<value = $value; } public function getSubNodeNames() { return array('value'); } /** * @internal * * Parses a DNUMBER token like PHP would. * * @param string $str A string number * * @return float The parsed number */ public static function parse($str) { // if string contains any of .eE just cast it to float if (false !== strpbrk($str, '.eE')) { return (float) $str; } // otherwise it's an integer notation that overflowed into a float // if it starts with 0 it's one of the special integer notations if ('0' === $str[0]) { // hex if ('x' === $str[1] || 'X' === $str[1]) { return hexdec($str); } // bin if ('b' === $str[1] || 'B' === $str[1]) { return bindec($str); } // oct // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit (8 or 9) // so that only the digits before that are used return octdec(substr($str, 0, strcspn($str, '89'))); } // dec return (float) $str; } } parts = $parts; } public function getSubNodeNames() { return array('parts'); } } value = $value; } public function getSubNodeNames() { return array('value'); } /** * @internal * * Parses an LNUMBER token (dec, hex, oct and bin notations) like PHP would. * * @param string $str A string number * * @return int The parsed number */ public static function parse($str) { // handle plain 0 specially if ('0' === $str) { return 0; } // if first char is 0 (and number isn't 0) it's a special syntax if ('0' === $str[0]) { // hex if ('x' === $str[1] || 'X' === $str[1]) { return hexdec($str); } // bin if ('b' === $str[1] || 'B' === $str[1]) { return bindec($str); } // oct (intval instead of octdec to get proper cutting behavior with malformed numbers) return intval($str, 8); } // dec return (int) $str; } } value = $value; $this->byRef = $byRef; $this->unpack = $unpack; } public function getSubNodeNames() { return array('value', 'byRef', 'unpack'); } } parts = $parts; } public function getSubNodeNames() { return array('parts'); } /** * Gets the first part of the name, i.e. everything before the first namespace separator. * * @return string First part of the name */ public function getFirst() { return $this->parts[0]; } /** * Gets the last part of the name, i.e. everything after the last namespace separator. * * @return string Last part of the name */ public function getLast() { return $this->parts[count($this->parts) - 1]; } /** * Checks whether the name is unqualified. (E.g. Name) * * @return bool Whether the name is unqualified */ public function isUnqualified() { return 1 == count($this->parts); } /** * Checks whether the name is qualified. (E.g. Name\Name) * * @return bool Whether the name is qualified */ public function isQualified() { return 1 < count($this->parts); } /** * Checks whether the name is fully qualified. (E.g. \Name) * * @return bool Whether the name is fully qualified */ public function isFullyQualified() { return false; } /** * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) * * @return bool Whether the name is relative */ public function isRelative() { return false; } /** * Returns a string representation of the name by imploding the namespace parts with a separator. * * @param string $separator The separator to use (defaults to the namespace separator \) * * @return string String representation */ public function toString($separator = '\\') { return implode($separator, $this->parts); } /** * Returns a string representation of the name by imploding the namespace parts with the * namespace separator. * * @return string String representation */ public function __toString() { return implode('\\', $this->parts); } /** * Sets the whole name. * * @param string|array|self $name The name to set the whole name to */ public function set($name) { $this->parts = $this->prepareName($name); } /** * Prepends a name to this name. * * @param string|array|self $name Name to prepend */ public function prepend($name) { $this->parts = array_merge($this->prepareName($name), $this->parts); } /** * Appends a name to this name. * * @param string|array|self $name Name to append */ public function append($name) { $this->parts = array_merge($this->parts, $this->prepareName($name)); } /** * Sets the first part of the name. * * @param string|array|self $name The name to set the first part to */ public function setFirst($name) { array_splice($this->parts, 0, 1, $this->prepareName($name)); } /** * Sets the last part of the name. * * @param string|array|self $name The name to set the last part to */ public function setLast($name) { array_splice($this->parts, -1, 1, $this->prepareName($name)); } /** * Prepares a (string, array or Name node) name for use in name changing methods by converting * it to an array. * * @param string|array|self $name Name to prepare * * @return array Prepared name */ protected function prepareName($name) { if (is_string($name)) { return explode('\\', $name); } elseif (is_array($name)) { return $name; } elseif ($name instanceof self) { return $name->parts; } throw new \InvalidArgumentException( 'When changing a name you need to pass either a string, an array or a Name node' ); } } getNode(); } elseif ($node instanceof Node) { return $node; } throw new \LogicException('Expected node or builder object'); } /** * Normalizes a name: Converts plain string names to PhpParser\Node\Name. * * @param Name|string $name The name to normalize * * @return Name The normalized name */ protected function normalizeName($name) { if ($name instanceof Name) { return $name; } elseif (is_string($name)) { if (!$name) { throw new \LogicException('Name cannot be empty'); } if ($name[0] == '\\') { return new Name\FullyQualified(substr($name, 1)); } elseif (0 === strpos($name, 'namespace\\')) { return new Name\Relative(substr($name, strlen('namespace\\'))); } else { return new Name($name); } } throw new \LogicException('Name must be a string or an instance of PhpParser\Node\Name'); } /** * Normalizes a value: Converts nulls, booleans, integers, * floats, strings and arrays into their respective nodes * * @param mixed $value The value to normalize * * @return Expr The normalized value */ protected function normalizeValue($value) { if ($value instanceof Node) { return $value; } elseif (is_null($value)) { return new Expr\ConstFetch( new Name('null') ); } elseif (is_bool($value)) { return new Expr\ConstFetch( new Name($value ? 'true' : 'false') ); } elseif (is_int($value)) { return new Scalar\LNumber($value); } elseif (is_float($value)) { return new Scalar\DNumber($value); } elseif (is_string($value)) { return new Scalar\String_($value); } elseif (is_array($value)) { $items = array(); $lastKey = -1; foreach ($value as $itemKey => $itemValue) { // for consecutive, numeric keys don't generate keys if (null !== $lastKey && ++$lastKey === $itemKey) { $items[] = new Expr\ArrayItem( $this->normalizeValue($itemValue) ); } else { $lastKey = null; $items[] = new Expr\ArrayItem( $this->normalizeValue($itemValue), $this->normalizeValue($itemKey) ); } } return new Expr\Array_($items); } else { throw new \LogicException('Invalid value'); } } /** * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc. * * @param Comment\Doc|string $docComment The doc comment to normalize * * @return Comment\Doc The normalized doc comment */ protected function normalizeDocComment($docComment) { if ($docComment instanceof Comment\Doc) { return $docComment; } else if (is_string($docComment)) { return new Comment\Doc($docComment); } else { throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc'); } } /** * Sets a modifier in the $this->type property. * * @param int $modifier Modifier to set */ protected function setModifier($modifier) { Stmt\Class_::verifyModifier($this->type, $modifier); $this->type |= $modifier; } } rawMessage = (string) $message; if (is_array($attributes)) { $this->attributes = $attributes; } else { $this->attributes = array('startLine' => $attributes); } $this->updateMessage(); } /** * Gets the error message * * @return string Error message */ public function getRawMessage() { return $this->rawMessage; } /** * Gets the line the error starts in. * * @return int Error start line */ public function getStartLine() { return isset($this->attributes['startLine']) ? $this->attributes['startLine'] : -1; } /** * Gets the line the error ends in. * * @return int Error end line */ public function getEndLine() { return isset($this->attributes['endLine']) ? $this->attributes['endLine'] : -1; } /** * Gets the attributes of the node/token the error occurred at. * * @return array */ public function getAttributes() { return $this->attributes; } /** * Sets the line of the PHP file the error occurred in. * * @param string $message Error message */ public function setRawMessage($message) { $this->rawMessage = (string) $message; $this->updateMessage(); } /** * Sets the line the error starts in. * * @param int $line Error start line */ public function setStartLine($line) { $this->attributes['startLine'] = (int) $line; $this->updateMessage(); } /** * Returns whether the error has start and end column information. * * For column information enable the startFilePos and endFilePos in the lexer options. * * @return bool */ public function hasColumnInfo() { return isset($this->attributes['startFilePos']) && isset($this->attributes['endFilePos']); } /** * Gets the start column (1-based) into the line where the error started. * * @param string $code Source code of the file * @return int */ public function getStartColumn($code) { if (!$this->hasColumnInfo()) { throw new \RuntimeException('Error does not have column information'); } return $this->toColumn($code, $this->attributes['startFilePos']); } /** * Gets the end column (1-based) into the line where the error ended. * * @param string $code Source code of the file * @return int */ public function getEndColumn($code) { if (!$this->hasColumnInfo()) { throw new \RuntimeException('Error does not have column information'); } return $this->toColumn($code, $this->attributes['endFilePos']); } private function toColumn($code, $pos) { if ($pos > strlen($code)) { throw new \RuntimeException('Invalid position information'); } $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); if (false === $lineStartPos) { $lineStartPos = -1; } return $pos - $lineStartPos; } /** * Updates the exception message after a change to rawMessage or rawLine. */ protected function updateMessage() { $this->message = $this->rawMessage; if (-1 === $this->getStartLine()) { $this->message .= ' on unknown line'; } else { $this->message .= ' on line ' . $this->getStartLine(); } } /** @deprecated Use getStartLine() instead */ public function getRawLine() { return $this->getStartLine(); } /** @deprecated Use setStartLine() instead */ public function setRawLine($line) { $this->setStartLine($line); } } tokenMap = $this->createTokenMap(); // map of tokens to drop while lexing (the map is only used for isset lookup, // that's why the value is simply set to 1; the value is never actually used.) $this->dropTokens = array_fill_keys(array(T_WHITESPACE, T_OPEN_TAG), 1); // the usedAttributes member is a map of the used attribute names to a dummy // value (here "true") $options += array( 'usedAttributes' => array('comments', 'startLine', 'endLine'), ); $this->usedAttributes = array_fill_keys($options['usedAttributes'], true); } /** * Initializes the lexer for lexing the provided source code. * * @param string $code The source code to lex * * @throws Error on lexing errors (unterminated comment or unexpected character) */ public function startLexing($code) { $scream = ini_set('xdebug.scream', '0'); $this->resetErrors(); $this->tokens = @token_get_all($code); $this->handleErrors(); if (false !== $scream) { ini_set('xdebug.scream', $scream); } $this->code = $code; // keep the code around for __halt_compiler() handling $this->pos = -1; $this->line = 1; $this->filePos = 0; } protected function resetErrors() { // set error_get_last() to defined state by forcing an undefined variable error set_error_handler(function() { return false; }, 0); @$undefinedVariable; restore_error_handler(); } protected function handleErrors() { $error = error_get_last(); if (preg_match( '~^Unterminated comment starting line ([0-9]+)$~', $error['message'], $matches )) { throw new Error('Unterminated comment', (int) $matches[1]); } if (preg_match( '~^Unexpected character in input: \'(.)\' \(ASCII=([0-9]+)\)~s', $error['message'], $matches )) { throw new Error(sprintf( 'Unexpected character "%s" (ASCII %d)', $matches[1], $matches[2] )); } // PHP cuts error message after null byte, so need special case if (preg_match('~^Unexpected character in input: \'$~', $error['message'])) { throw new Error('Unexpected null byte'); } } /** * Fetches the next token. * * The available attributes are determined by the 'usedAttributes' option, which can * be specified in the constructor. The following attributes are supported: * * * 'comments' => Array of PhpParser\Comment or PhpParser\Comment\Doc instances, * representing all comments that occurred between the previous * non-discarded token and the current one. * * 'startLine' => Line in which the node starts. * * 'endLine' => Line in which the node ends. * * 'startTokenPos' => Offset into the token array of the first token in the node. * * 'endTokenPos' => Offset into the token array of the last token in the node. * * 'startFilePos' => Offset into the code string of the first character that is part of the node. * * 'endFilePos' => Offset into the code string of the last character that is part of the node * * @param mixed $value Variable to store token content in * @param mixed $startAttributes Variable to store start attributes in * @param mixed $endAttributes Variable to store end attributes in * * @return int Token id */ public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) { $startAttributes = array(); $endAttributes = array(); while (1) { if (isset($this->tokens[++$this->pos])) { $token = $this->tokens[$this->pos]; } else { // EOF token with ID 0 $token = "\0"; } if (isset($this->usedAttributes['startTokenPos'])) { $startAttributes['startTokenPos'] = $this->pos; } if (isset($this->usedAttributes['startFilePos'])) { $startAttributes['startFilePos'] = $this->filePos; } if (is_string($token)) { // bug in token_get_all if ('b"' === $token) { $value = 'b"'; $this->filePos += 2; $id = ord('"'); } else { $value = $token; $this->filePos += 1; $id = ord($token); } if (isset($this->usedAttributes['startLine'])) { $startAttributes['startLine'] = $this->line; } if (isset($this->usedAttributes['endLine'])) { $endAttributes['endLine'] = $this->line; } if (isset($this->usedAttributes['endTokenPos'])) { $endAttributes['endTokenPos'] = $this->pos; } if (isset($this->usedAttributes['endFilePos'])) { $endAttributes['endFilePos'] = $this->filePos - 1; } return $id; } else { $this->line += substr_count($token[1], "\n"); $this->filePos += strlen($token[1]); if (T_COMMENT === $token[0]) { if (isset($this->usedAttributes['comments'])) { $startAttributes['comments'][] = new Comment($token[1], $token[2]); } } elseif (T_DOC_COMMENT === $token[0]) { if (isset($this->usedAttributes['comments'])) { $startAttributes['comments'][] = new Comment\Doc($token[1], $token[2]); } } elseif (!isset($this->dropTokens[$token[0]])) { $value = $token[1]; if (isset($this->usedAttributes['startLine'])) { $startAttributes['startLine'] = $token[2]; } if (isset($this->usedAttributes['endLine'])) { $endAttributes['endLine'] = $this->line; } if (isset($this->usedAttributes['endTokenPos'])) { $endAttributes['endTokenPos'] = $this->pos; } if (isset($this->usedAttributes['endFilePos'])) { $endAttributes['endFilePos'] = $this->filePos - 1; } return $this->tokenMap[$token[0]]; } } } throw new \RuntimeException('Reached end of lexer loop'); } /** * Returns the token array for current code. * * The token array is in the same format as provided by the * token_get_all() function and does not discard tokens (i.e. * whitespace and comments are included). The token position * attributes are against this token array. * * @return array Array of tokens in token_get_all() format */ public function getTokens() { return $this->tokens; } /** * Handles __halt_compiler() by returning the text after it. * * @return string Remaining text */ public function handleHaltCompiler() { // text after T_HALT_COMPILER, still including (); $textAfter = substr($this->code, $this->filePos); // ensure that it is followed by (); // this simplifies the situation, by not allowing any comments // in between of the tokens. if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) { throw new Error('__HALT_COMPILER must be followed by "();"'); } // prevent the lexer from returning any further tokens $this->pos = count($this->tokens); // return with (); removed return (string) substr($textAfter, strlen($matches[0])); // (string) converts false to '' } /** * Creates the token map. * * The token map maps the PHP internal token identifiers * to the identifiers used by the Parser. Additionally it * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'. * * @return array The token map */ protected function createTokenMap() { $tokenMap = array(); // 256 is the minimum possible token number, as everything below // it is an ASCII value for ($i = 256; $i < 1000; ++$i) { if (T_DOUBLE_COLON === $i) { // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM $tokenMap[$i] = Parser::T_PAAMAYIM_NEKUDOTAYIM; } elseif(T_OPEN_TAG_WITH_ECHO === $i) { // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO $tokenMap[$i] = Parser::T_ECHO; } elseif(T_CLOSE_TAG === $i) { // T_CLOSE_TAG is equivalent to ';' $tokenMap[$i] = ord(';'); } elseif ('UNKNOWN' !== $name = token_name($i)) { if ('T_HASHBANG' === $name) { // HHVM uses a special token for #! hashbang lines $tokenMap[$i] = Parser::T_INLINE_HTML; } else if (defined($name = 'PhpParser\Parser::' . $name)) { // Other tokens can be mapped directly $tokenMap[$i] = constant($name); } } } // HHVM uses a special token for numbers that overflow to double if (defined('T_ONUMBER')) { $tokenMap[T_ONUMBER] = Parser::T_DNUMBER; } // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant if (defined('T_COMPILER_HALT_OFFSET')) { $tokenMap[T_COMPILER_HALT_OFFSET] = Parser::T_STRING; } return $tokenMap; } } [aliasName => originalName]] */ protected $aliases; public function beforeTraverse(array $nodes) { $this->resetState(); } public function enterNode(Node $node) { if ($node instanceof Stmt\Namespace_) { $this->resetState($node->name); } elseif ($node instanceof Stmt\Use_) { foreach ($node->uses as $use) { $this->addAlias($use, $node->type); } } elseif ($node instanceof Stmt\Class_) { if (null !== $node->extends) { $node->extends = $this->resolveClassName($node->extends); } foreach ($node->implements as &$interface) { $interface = $this->resolveClassName($interface); } if (null !== $node->name) { $this->addNamespacedName($node); } } elseif ($node instanceof Stmt\Interface_) { foreach ($node->extends as &$interface) { $interface = $this->resolveClassName($interface); } $this->addNamespacedName($node); } elseif ($node instanceof Stmt\Trait_) { $this->addNamespacedName($node); } elseif ($node instanceof Stmt\Function_) { $this->addNamespacedName($node); $this->resolveSignature($node); } elseif ($node instanceof Stmt\ClassMethod || $node instanceof Expr\Closure ) { $this->resolveSignature($node); } elseif ($node instanceof Stmt\Const_) { foreach ($node->consts as $const) { $this->addNamespacedName($const); } } elseif ($node instanceof Expr\StaticCall || $node instanceof Expr\StaticPropertyFetch || $node instanceof Expr\ClassConstFetch || $node instanceof Expr\New_ || $node instanceof Expr\Instanceof_ ) { if ($node->class instanceof Name) { $node->class = $this->resolveClassName($node->class); } } elseif ($node instanceof Stmt\Catch_) { $node->type = $this->resolveClassName($node->type); } elseif ($node instanceof Expr\FuncCall) { if ($node->name instanceof Name) { $node->name = $this->resolveOtherName($node->name, Stmt\Use_::TYPE_FUNCTION); } } elseif ($node instanceof Expr\ConstFetch) { $node->name = $this->resolveOtherName($node->name, Stmt\Use_::TYPE_CONSTANT); } elseif ($node instanceof Stmt\TraitUse) { foreach ($node->traits as &$trait) { $trait = $this->resolveClassName($trait); } foreach ($node->adaptations as $adaptation) { if (null !== $adaptation->trait) { $adaptation->trait = $this->resolveClassName($adaptation->trait); } if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) { foreach ($adaptation->insteadof as &$insteadof) { $insteadof = $this->resolveClassName($insteadof); } } } } } protected function resetState(Name $namespace = null) { $this->namespace = $namespace; $this->aliases = array( Stmt\Use_::TYPE_NORMAL => array(), Stmt\Use_::TYPE_FUNCTION => array(), Stmt\Use_::TYPE_CONSTANT => array(), ); } protected function addAlias(Stmt\UseUse $use, $type) { // Constant names are case sensitive, everything else case insensitive if ($type === Stmt\Use_::TYPE_CONSTANT) { $aliasName = $use->alias; } else { $aliasName = strtolower($use->alias); } if (isset($this->aliases[$type][$aliasName])) { $typeStringMap = array( Stmt\Use_::TYPE_NORMAL => '', Stmt\Use_::TYPE_FUNCTION => 'function ', Stmt\Use_::TYPE_CONSTANT => 'const ', ); throw new Error( sprintf( 'Cannot use %s%s as %s because the name is already in use', $typeStringMap[$type], $use->name, $use->alias ), $use->getLine() ); } $this->aliases[$type][$aliasName] = $use->name; } /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */ private function resolveSignature($node) { foreach ($node->params as $param) { if ($param->type instanceof Name) { $param->type = $this->resolveClassName($param->type); } } if ($node->returnType instanceof Name) { $node->returnType = $this->resolveClassName($node->returnType); } } protected function resolveClassName(Name $name) { // don't resolve special class names if (in_array(strtolower($name->toString()), array('self', 'parent', 'static'))) { if (!$name->isUnqualified()) { throw new Error( sprintf("'\\%s' is an invalid class name", $name->toString()), $name->getLine() ); } return $name; } // fully qualified names are already resolved if ($name->isFullyQualified()) { return $name; } $aliasName = strtolower($name->getFirst()); if (!$name->isRelative() && isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName])) { // resolve aliases (for non-relative names) $name->setFirst($this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName]); } elseif (null !== $this->namespace) { // if no alias exists prepend current namespace $name->prepend($this->namespace); } return new Name\FullyQualified($name->parts, $name->getAttributes()); } protected function resolveOtherName(Name $name, $type) { // fully qualified names are already resolved if ($name->isFullyQualified()) { return $name; } // resolve aliases for qualified names $aliasName = strtolower($name->getFirst()); if ($name->isQualified() && isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName])) { $name->setFirst($this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName]); } elseif ($name->isUnqualified()) { if ($type === Stmt\Use_::TYPE_CONSTANT) { // constant aliases are case-sensitive, function aliases case-insensitive $aliasName = $name->getFirst(); } if (isset($this->aliases[$type][$aliasName])) { // resolve unqualified aliases $name->set($this->aliases[$type][$aliasName]); } else { // unqualified, unaliased names cannot be resolved at compile-time return $name; } } elseif (null !== $this->namespace) { // if no alias exists prepend current namespace $name->prepend($this->namespace); } return new Name\FullyQualified($name->parts, $name->getAttributes()); } protected function addNamespacedName(Node $node) { if (null !== $this->namespace) { $node->namespacedName = clone $this->namespace; $node->namespacedName->append($node->name); } else { $node->namespacedName = new Name($node->name, $node->getAttributes()); } } } visitors = array(); $this->cloneNodes = $cloneNodes; } /** * Adds a visitor. * * @param NodeVisitor $visitor Visitor to add */ public function addVisitor(NodeVisitor $visitor) { $this->visitors[] = $visitor; } /** * Removes an added visitor. * * @param NodeVisitor $visitor */ public function removeVisitor(NodeVisitor $visitor) { foreach ($this->visitors as $index => $storedVisitor) { if ($storedVisitor === $visitor) { unset($this->visitors[$index]); break; } } } /** * Traverses an array of nodes using the registered visitors. * * @param Node[] $nodes Array of nodes * * @return Node[] Traversed array of nodes */ public function traverse(array $nodes) { foreach ($this->visitors as $visitor) { if (null !== $return = $visitor->beforeTraverse($nodes)) { $nodes = $return; } } $nodes = $this->traverseArray($nodes); foreach ($this->visitors as $visitor) { if (null !== $return = $visitor->afterTraverse($nodes)) { $nodes = $return; } } return $nodes; } protected function traverseNode(Node $node) { if ($this->cloneNodes) { $node = clone $node; } foreach ($node->getSubNodeNames() as $name) { $subNode =& $node->$name; if (is_array($subNode)) { $subNode = $this->traverseArray($subNode); } elseif ($subNode instanceof Node) { $traverseChildren = true; foreach ($this->visitors as $visitor) { $return = $visitor->enterNode($subNode); if (self::DONT_TRAVERSE_CHILDREN === $return) { $traverseChildren = false; } else if (null !== $return) { $subNode = $return; } } if ($traverseChildren) { $subNode = $this->traverseNode($subNode); } foreach ($this->visitors as $visitor) { if (null !== $return = $visitor->leaveNode($subNode)) { $subNode = $return; } } } } return $node; } protected function traverseArray(array $nodes) { $doNodes = array(); foreach ($nodes as $i => &$node) { if (is_array($node)) { $node = $this->traverseArray($node); } elseif ($node instanceof Node) { $traverseChildren = true; foreach ($this->visitors as $visitor) { $return = $visitor->enterNode($node); if (self::DONT_TRAVERSE_CHILDREN === $return) { $traverseChildren = false; } else if (null !== $return) { $node = $return; } } if ($traverseChildren) { $node = $this->traverseNode($node); } foreach ($this->visitors as $visitor) { $return = $visitor->leaveNode($node); if (self::REMOVE_NODE === $return) { $doNodes[] = array($i, array()); break; } elseif (is_array($return)) { $doNodes[] = array($i, $return); break; } elseif (null !== $return) { $node = $return; } } } } if (!empty($doNodes)) { while (list($i, $replace) = array_pop($doNodes)) { array_splice($nodes, $i, 1, $replace); } } return $nodes; } } name = $name; } /** * Extends a class. * * @param Name|string $class Name of class to extend * * @return $this The builder instance (for fluid interface) */ public function extend($class) { $this->extends = $this->normalizeName($class); return $this; } /** * Implements one or more interfaces. * * @param Name|string $interface Name of interface to implement * @param Name|string $... More interfaces to implement * * @return $this The builder instance (for fluid interface) */ public function implement() { foreach (func_get_args() as $interface) { $this->implements[] = $this->normalizeName($interface); } return $this; } /** * Makes the class abstract. * * @return $this The builder instance (for fluid interface) */ public function makeAbstract() { $this->setModifier(Stmt\Class_::MODIFIER_ABSTRACT); return $this; } /** * Makes the class final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->setModifier(Stmt\Class_::MODIFIER_FINAL); return $this; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = $this->normalizeNode($stmt); $targets = array( 'Stmt_TraitUse' => &$this->uses, 'Stmt_ClassConst' => &$this->constants, 'Stmt_Property' => &$this->properties, 'Stmt_ClassMethod' => &$this->methods, ); $type = $stmt->getType(); if (!isset($targets[$type])) { throw new \LogicException(sprintf('Unexpected node of type "%s"', $type)); } $targets[$type][] = $stmt; return $this; } /** * Returns the built class node. * * @return Stmt\Class_ The built class node */ public function getNode() { return new Stmt\Class_($this->name, array( 'type' => $this->type, 'extends' => $this->extends, 'implements' => $this->implements, 'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods), ), $this->attributes); } }name = $name; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $this->stmts[] = $this->normalizeNode($stmt); return $this; } /** * Returns the built function node. * * @return Stmt\Function_ The built function node */ public function getNode() { return new Stmt\Function_($this->name, array( 'byRef' => $this->returnByRef, 'params' => $this->params, 'stmts' => $this->stmts, ), $this->attributes); } }name = $this->normalizeName($name); $this->type = $type; } /** * Sets alias for used name. * * @param string $alias Alias to use (last component of full name by default) * * @return $this The builder instance (for fluid interface) */ protected function as_($alias) { $this->alias = $alias; return $this; } public function __call($name, $args) { if (method_exists($this, $name . '_')) { return call_user_func_array(array($this, $name . '_'), $args); } throw new \LogicException(sprintf('Method "%s" does not exist', $name)); } /** * Returns the built node. * * @return Node The built node */ public function getNode() { $alias = null !== $this->alias ? $this->alias : $this->name->getLast(); return new Stmt\Use_(array( new Stmt\UseUse($this->name, $alias) ), $this->type); } } name = $name; } /** * Makes the property public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC); return $this; } /** * Makes the property protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED); return $this; } /** * Makes the property private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE); return $this; } /** * Makes the property static. * * @return $this The builder instance (for fluid interface) */ public function makeStatic() { $this->setModifier(Stmt\Class_::MODIFIER_STATIC); return $this; } /** * Sets default value for the property. * * @param mixed $value Default value to use * * @return $this The builder instance (for fluid interface) */ public function setDefault($value) { $this->default = $this->normalizeValue($value); return $this; } /** * Sets doc comment for the property. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes = array( 'comments' => array($this->normalizeDocComment($docComment)) ); return $this; } /** * Returns the built class node. * * @return Stmt\Property The built property node */ public function getNode() { return new Stmt\Property( $this->type !== 0 ? $this->type : Stmt\Class_::MODIFIER_PUBLIC, array( new Stmt\PropertyProperty($this->name, $this->default) ), $this->attributes ); } }name = $name; } /** * Makes the method public. * * @return $this The builder instance (for fluid interface) */ public function makePublic() { $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC); return $this; } /** * Makes the method protected. * * @return $this The builder instance (for fluid interface) */ public function makeProtected() { $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED); return $this; } /** * Makes the method private. * * @return $this The builder instance (for fluid interface) */ public function makePrivate() { $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE); return $this; } /** * Makes the method static. * * @return $this The builder instance (for fluid interface) */ public function makeStatic() { $this->setModifier(Stmt\Class_::MODIFIER_STATIC); return $this; } /** * Makes the method abstract. * * @return $this The builder instance (for fluid interface) */ public function makeAbstract() { if (!empty($this->stmts)) { throw new \LogicException('Cannot make method with statements abstract'); } $this->setModifier(Stmt\Class_::MODIFIER_ABSTRACT); $this->stmts = null; // abstract methods don't have statements return $this; } /** * Makes the method final. * * @return $this The builder instance (for fluid interface) */ public function makeFinal() { $this->setModifier(Stmt\Class_::MODIFIER_FINAL); return $this; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { if (null === $this->stmts) { throw new \LogicException('Cannot add statements to an abstract method'); } $this->stmts[] = $this->normalizeNode($stmt); return $this; } /** * Returns the built method node. * * @return Stmt\ClassMethod The built method node */ public function getNode() { return new Stmt\ClassMethod($this->name, array( 'type' => $this->type, 'byRef' => $this->returnByRef, 'params' => $this->params, 'stmts' => $this->stmts, ), $this->attributes); } } returnByRef = true; return $this; } /** * Adds a parameter. * * @param Node\Param|Param $param The parameter to add * * @return $this The builder instance (for fluid interface) */ public function addParam($param) { $param = $this->normalizeNode($param); if (!$param instanceof Node\Param) { throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType())); } $this->params[] = $param; return $this; } /** * Adds multiple parameters. * * @param array $params The parameters to add * * @return $this The builder instance (for fluid interface) */ public function addParams(array $params) { foreach ($params as $param) { $this->addParam($param); } return $this; } }name = $name; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = $this->normalizeNode($stmt); if ($stmt instanceof Stmt\Property) { $this->properties[] = $stmt; } else if ($stmt instanceof Stmt\ClassMethod) { $this->methods[] = $stmt; } else { throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); } return $this; } /** * Returns the built trait node. * * @return Stmt\Trait_ The built interface node */ public function getNode() { return new Stmt\Trait_( $this->name, array_merge($this->properties, $this->methods), $this->attributes ); } } name = $name; } /** * Extends one or more interfaces. * * @param Name|string $interface Name of interface to extend * @param Name|string $... More interfaces to extend * * @return $this The builder instance (for fluid interface) */ public function extend() { foreach (func_get_args() as $interface) { $this->extends[] = $this->normalizeName($interface); } return $this; } /** * Adds a statement. * * @param Stmt|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $stmt = $this->normalizeNode($stmt); $type = $stmt->getType(); switch ($type) { case 'Stmt_ClassConst': $this->constants[] = $stmt; break; case 'Stmt_ClassMethod': // we erase all statements in the body of an interface method $stmt->stmts = null; $this->methods[] = $stmt; break; default: throw new \LogicException(sprintf('Unexpected node of type "%s"', $type)); } return $this; } /** * Returns the built interface node. * * @return Stmt\Interface_ The built interface node */ public function getNode() { return new Stmt\Interface_($this->name, array( 'extends' => $this->extends, 'stmts' => array_merge($this->constants, $this->methods), ), $this->attributes); } }addStmt($stmt); } return $this; } /** * Sets doc comment for the declaration. * * @param PhpParser\Comment\Doc|string $docComment Doc comment to set * * @return $this The builder instance (for fluid interface) */ public function setDocComment($docComment) { $this->attributes['comments'] = array( $this->normalizeDocComment($docComment) ); return $this; } }name = $name; } /** * Sets default value for the parameter. * * @param mixed $value Default value to use * * @return $this The builder instance (for fluid interface) */ public function setDefault($value) { $this->default = $this->normalizeValue($value); return $this; } /** * Sets type hint for the parameter. * * @param string|Node\Name $type Type hint to use * * @return $this The builder instance (for fluid interface) */ public function setTypeHint($type) { if ($type === 'array' || $type === 'callable') { $this->type = $type; } else { $this->type = $this->normalizeName($type); } return $this; } /** * Make the parameter accept the value by reference. * * @return $this The builder instance (for fluid interface) */ public function makeByRef() { $this->byRef = true; return $this; } /** * Returns the built parameter node. * * @return Node\Param The built parameter node */ public function getNode() { return new Node\Param( $this->name, $this->default, $this->type, $this->byRef ); } }name = null !== $name ? $this->normalizeName($name) : null; } /** * Adds a statement. * * @param Node|PhpParser\Builder $stmt The statement to add * * @return $this The builder instance (for fluid interface) */ public function addStmt($stmt) { $this->stmts[] = $this->normalizeNode($stmt); return $this; } /** * Adds multiple statements. * * @param array $stmts The statements to add * * @return $this The builder instance (for fluid interface) */ public function addStmts(array $stmts) { foreach ($stmts as $stmt) { $this->addStmt($stmt); } return $this; } /** * Returns the built node. * * @return Node The built node */ public function getNode() { return new Stmt\Namespace_($this->name, $this->stmts); } } '", "T_IS_GREATER_OR_EQUAL", "T_SL", "T_SR", "'+'", "'-'", "'.'", "'*'", "'/'", "'%'", "'!'", "T_INSTANCEOF", "'~'", "T_INC", "T_DEC", "T_INT_CAST", "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST", "T_BOOL_CAST", "T_UNSET_CAST", "'@'", "T_POW", "'['", "T_NEW", "T_CLONE", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE", "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME", "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING", "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH", "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_ENDSWITCH", "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_GOTO", "T_FUNCTION", "T_CONST", "T_RETURN", "T_TRY", "T_CATCH", "T_FINALLY", "T_THROW", "T_USE", "T_INSTEADOF", "T_GLOBAL", "T_STATIC", "T_ABSTRACT", "T_FINAL", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC", "T_VAR", "T_UNSET", "T_ISSET", "T_EMPTY", "T_HALT_COMPILER", "T_CLASS", "T_TRAIT", "T_INTERFACE", "T_EXTENDS", "T_IMPLEMENTS", "T_OBJECT_OPERATOR", "T_DOUBLE_ARROW", "T_LIST", "T_ARRAY", "T_CALLABLE", "T_CLASS_C", "T_TRAIT_C", "T_METHOD_C", "T_FUNC_C", "T_LINE", "T_FILE", "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES", "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_NAMESPACE", "T_NS_C", "T_DIR", "T_NS_SEPARATOR", "T_ELLIPSIS", "';'", "'{'", "'}'", "'('", "')'", "'$'", "'`'", "']'", "'\"'" ); protected $tokenToSymbol = array( 0, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 52, 156, 157, 153, 51, 34, 157, 151, 152, 49, 46, 7, 47, 48, 50, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 28, 148, 40, 14, 42, 27, 64, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 66, 157, 155, 33, 157, 154, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 149, 32, 150, 54, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 30, 31, 35, 36, 37, 38, 39, 41, 43, 44, 45, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 65, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 157, 157, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 157, 157, 157, 157, 157, 157, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147 ); protected $action = array( 707, 60, 61, 420, 62, 63,-32766,-32766,-32766,-32766, 64, 65, 66, 223, 224, 225, 226, 227, 228, 229, 230, 231, 0, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,-32766,-32766,-32766,-32766,-32766, -32767,-32767,-32767,-32767, 650, 67, 68, 58, 244, 245, 129, 69, 460, 70, 297, 298, 71, 72, 73, 74, 75, 76, 77, 78,-32766, 32, 305, 79, 411, 421, -32766,-32766,-32766, 968, 969, 463, -118, 1061, 413, 696, 447, 464, 46, 27, 422, 366, 465, 438, 466,-32766, 467,-32766,-32766, 423, 220, 221, 222, 36, 37, 468, 424, 441, 38, 469, 221, 222, 80,-32766, 329, 359, 360, 491, 751, 207, 425, 470, 471, 472, 473, 474, 608,-32766, 207, 55, 678, 723, 475, 476, 477, 478, 128, 974, 975, 976, 977, 971, 972, 315, 84, 85, 86, 419, 491, 978, 973, 425, 440, 702, 618, 635, 47, 135, 340, 327, 301, 331, 443, 40, 313, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 31, 308,-32766,-32766,-32766,-32766,-32766, 288, -32766, 775, 776, 800, 805, 110, 650, 220, 221, 222, -32766,-32766, 1027,-32766,-32766,-32766, 125,-32766, 439,-32766, 569,-32766, 917, -123,-32766, 286, 207, 35,-32766,-32766, -32766, 428, 428,-32766,-32766, 22, 693,-32766, 211, 133, -32766, 490, 752,-32766, 301, 1090, 470, 471,-32766, -119, 342, 1018, 694, 378, 917, 678, 723, 475, 476, 616, 791, 41, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,-32766,-32766,-32766, 132,-32766,-32766, -32766, 1093, 781, 1095, 1094,-32766, 650, 220, 221, 222, -32766,-32766, 57,-32766,-32766,-32766, 935,-32766, 54,-32766, -32766,-32766, 856, 858,-32766, 358, 207, 248,-32766,-32766, -32766, 428,-32766,-32766,-32766, 39, 300,-32766, 650, 388, -32766, 490,-32766,-32766, 304,-32766,-32766,-32766,-32766,-32766, 630,-32766, 617,-32766, 917, 290,-32766, 782, 356, 357, -32766,-32766,-32766, 428, 1068,-32766,-32766, 434, 207,-32766, 620, 1019,-32766, 490, 621,-32766, 302, 132,-32766,-32766, -32766, 212, 606, 241, 242, 243, 917, 412,-32766,-32766, -32766, 642, 1055, 326, -401, 126, 623, 470, 471, 244, 245, 124, 131, 416, 470, 471, 656, 723, 475, 476, -32766,-32766,-32766, 678, 723, 475, 476, 222, 650,-32766, -32766,-32766,-32766, 428, 810,-32766,-32766,-32766, 339,-32766, 303,-32766, -171,-32766, 207, 659,-32766, 1026,-32766, 477, -32766,-32766,-32766, 428,-32766,-32766,-32766, 428, 445,-32766, 650, 213,-32766, 490,-32766,-32766,-32766,-32766,-32766,-32766, -32766,-32766,-32766,-32766, 428,-32766, 917, 348,-32766, 428, 1083,-32766,-32766,-32766,-32766, 428, 1061,-32766,-32766,-32766, -32766,-32766,-32766, 1027,-32766, 490, 1065,-32766, 289, 332, -32766,-32766,-32766, 1083, 214,-32766,-32766,-32766, 917,-32766, -32766,-32766,-32766,-32766,-32766,-32766,-32766,-32766, 249,-32767, -32767,-32767,-32767, 347,-32766, 123,-32766,-32766,-32766,-32766, 299, 133,-32766,-32766,-32766, 220, 221, 222, 1025, 250, 650, 220, 221, 222,-32766,-32766,-32766,-32766,-32766,-32766, -32766,-32766, 137,-32766, 207,-32766, 566, 980,-32766, 634, 207, 340,-32766,-32766,-32766, 428,-32766,-32766,-32766, 134, 575,-32766, 650, 314,-32766, 490,-32766, 716, 1024,-32766, -32766,-32766,-32766,-32766, 538,-32766, 706,-32766, 244, 245, -32766, 454, 581,-32766,-32766,-32766,-32766, 428, 639,-32766, -32766, 449, 28,-32766, 917, 136,-32766, 490, 238, 239, 240, 110,-32766,-32766,-32766, 104, 105, 106, 308,-32766, 138, 367, 588, 589, 593, 650, 804, 638, 980,-32766, 615, 305,-32766,-32766,-32766, 346,-32766, 52,-32766, 650, -32766, 1061, 50,-32766,-32766,-32766,-32766,-32766,-32766,-32766, 428, 59,-32766,-32766, 470, 471,-32766, 917, 605,-32766, 490, 246,-32766, 678, 723, 475, 476,-32766, 650, 107, 108, 109,-32766, 308, 945,-32766,-32766,-32766,-32766,-32766, 56,-32766, 49,-32766, 51, 110,-32766, 775, 776, 917, -32766,-32766,-32766, 428, 53,-32766,-32766,-32766,-32766,-32766, 529, 961,-32766, 490, 657, 625, 491, 815, 645, 425, -32766, 528, 516, 512, 429,-32766, 340, 511, 435, 651, 433, 650, 667, 650, 1088,-32766, 669, 812,-32766,-32766, -32766,-32766,-32766, 600,-32766, 938,-32766, 515, 607,-32766, 686,-32766, 917,-32766,-32766,-32766, 428,-32766,-32766,-32766, 590, 345,-32766, 650, 1083,-32766, 490,-32766, 559, 437, -32766,-32766,-32766,-32766,-32766, 458,-32766,-32766,-32766, -168, 584,-32766, 307, 285, 531,-32766,-32766,-32766, 428, 572, -32766,-32766, 336, 432,-32766, 725, 428,-32766, 490, 724, 42, 585, 979, 688,-32766,-32766, 338, 127, 330, 718, -32766, 23, 811, 341, 521, 0, 650, 434, -308, 0, -32766, 335, 0,-32766,-32766,-32766, -402,-32766, -401,-32766, 328,-32766, 915, 477,-32766, 690,-32766, 0,-32766,-32766, -32766, 428, 318,-32766,-32766, 0,-32766,-32766, -300, 613, -32766, 490, 650, -309, 381, 368,-32766, 334,-32766,-32766, -32766,-32766, 416,-32766, 1056,-32766, 247,-32766, 809, 745, -32766, 735, 746, 698,-32766,-32766,-32766, 428, 801,-32766, -32766, 683, 663,-32766, 215, 216,-32766, 490,-32766,-32766, 217, 662, 218, 681,-32766,-32767,-32767,-32767,-32767, 102, 103, 104, 105, 106, 209, 754, 661, -1, 660, 215, 216, 705, 968, 969, 692, 217,-32766, 218, 808, 627, 970,-32766,-32766,-32766,-32766,-32766, 626, 737, 739, 209, -32766,-32766,-32766, 704, 691, 695, 689, 968, 969, 687, -32766,-32766,-32766,-32766,-32766, 970, 697, 44, 45,-32766, 643,-32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767,-32767, -32767,-32767, 644, 640, 637, 632, 631, 629, 556, 624, 974, 975, 976, 977, 971, 972, 394, 619, 83, 130, 641, 591, 978, 973, 1066, 793, 959, 1058, 1040, 219, 1046,-32766, 1060, 556, 1062, 974, 975, 976, 977, 971, 972, 394, 1089, 453, 722, 985, 720, 978, 973, 412, 721, 1092, 931, 1087, 219, 326,-32766, 1091, 744, 470, 471, 743, 921, 470, 471, -104, -104, -104, 656, 723, 475, 476, 678, 723, 475, 476, 470, 471, -103, -103, -103, 43, 470, 471, 34, 678, 723, 475, 476, 415, 339, 678, 723, 475, 476, 470, 471, 30, 958, 33, -32766, 719, 412, 410, 678, 723, 475, 476, 326, 343, 312, 311, 470, 471, 816,-32766,-32766,-32766, 310, 309, -104, 656, 723, 475, 476, -112, -112, -112, 296, -114, -114, -114, 295, -103,-32766, 287,-32766,-32766,-32766,-32766, -32766,-32766, 417, 339, 210, 82, 81, 48, 337, 896, 658, 826, 827, 828, 825, 824, 823, 818, 560, 984, 783, 925, 922, 612, 551, 461, 470, 471, 457, 455, 470, 471,-32766,-32766,-32766, 678, 723, 475, 476, 678, 723, 475, 476, 897, 450, 389, 25, 24, -120, 470, 471,-32766, 1057,-32766,-32766,-32766,-32766,-32766, 678, 723, 475, 476, 470, 471, -119, 1041, 470, 471, 1045, 0, 1059, 678, 723, 475, 476, 678, 723, 475, 476, 944, 470, 471, 597, 929, 470, 471, 930, 710, 927, 678, 723, 475, 476, 678, 723, 475, 476, 470, 471, 928, 628, 926, 470, 471, 679, 0, 678, 723, 475, 476, 0, 678, 723, 475, 476, 0, 0, 0, 712, 0, 0, 0, 919, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 920 ); protected $actionCheck = array( 1, 2, 3, 4, 5, 6, 30, 31, 32, 33, 11, 12, 13, 30, 31, 32, 33, 34, 35, 36, 37, 38, 0, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 30, 31, 32, 33, 34, 35, 36, 37, 38, 76, 46, 47, 66, 65, 66, 7, 52, 7, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 8, 66, 67, 68, 69, 70, 8, 9, 10, 74, 75, 76, 73, 78, 122, 80, 7, 82, 83, 84, 85, 7, 87, 28, 89, 27, 91, 29, 30, 94, 8, 9, 10, 98, 99, 100, 101, 7, 103, 104, 9, 10, 107, 151, 127, 110, 111, 143, 28, 27, 146, 112, 113, 118, 119, 120, 76, 1, 27, 66, 121, 122, 123, 124, 129, 130, 149, 132, 133, 134, 135, 136, 137, 138, 8, 9, 10, 7, 143, 144, 145, 146, 7, 148, 149, 28, 151, 66, 153, 154, 34, 156, 76, 27, 7, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 7, 53, 30, 31, 32, 33, 34, 7, 70, 130, 131, 148, 150, 65, 76, 8, 9, 10, 80, 1, 122, 83, 84, 85, 149, 87, 149, 89, 86, 91, 12, 152, 94, 128, 27, 7, 98, 99, 100, 101, 101, 103, 104, 152, 148, 107, 7, 149, 110, 111, 148, 1, 34, 150, 112, 113, 118, 152, 7, 155, 148, 78, 12, 121, 122, 123, 124, 76, 78, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 8, 9, 10, 147, 148, 149, 70, 76, 152, 78, 79, 102, 76, 8, 9, 10, 80, 108, 66, 83, 84, 85, 152, 87, 66, 89, 117, 91, 55, 56, 94, 7, 27, 28, 98, 99, 100, 101, 70, 103, 104, 140, 141, 107, 76, 77, 110, 111, 80, 1, 34, 83, 84, 85, 118, 87, 28, 89, 76, 91, 12, 153, 94, 152, 101, 102, 98, 99, 100, 101, 152, 103, 104, 146, 27, 107, 149, 152, 110, 111, 28, 1, 34, 147, 148, 149, 118, 14, 90, 49, 50, 51, 12, 102, 30, 31, 32, 28, 78, 108, 127, 149, 28, 112, 113, 65, 66, 149, 28, 146, 112, 113, 121, 122, 123, 124, 148, 149, 70, 121, 122, 123, 124, 10, 76, 8, 9, 10, 80, 101, 148, 83, 84, 85, 143, 87, 7, 89, 78, 91, 27, 150, 94, 76, 27, 129, 98, 99, 100, 101, 70, 103, 104, 101, 76, 107, 76, 14, 110, 111, 80, 1, 102, 83, 84, 85, 118, 87, 108, 89, 101, 91, 12, 153, 94, 101, 81, 117, 98, 99, 100, 101, 78, 103, 104, 8, 9, 107, 30, 122, 110, 111, 76, 1, 34, 81, 148, 149, 118, 81, 14, 8, 9, 10, 12, 30, 31, 32, 33, 34, 35, 36, 37, 38, 14, 40, 41, 42, 43, 66, 27, 14, 29, 30, 31, 32, 34, 149, 148, 149, 70, 8, 9, 10, 139, 14, 76, 8, 9, 10, 80, 30, 31, 83, 84, 85, 1, 87, 149, 89, 27, 91, 153, 139, 94, 28, 27, 153, 98, 99, 100, 101, 70, 103, 104, 149, 81, 107, 76, 28, 110, 111, 80, 34, 156, 83, 84, 85, 118, 87, 127, 89, 28, 91, 65, 66, 94, 71, 72, 1, 98, 99, 100, 101, 28, 103, 104, 71, 72, 107, 12, 28, 110, 111, 46, 47, 48, 65, 148, 149, 118, 46, 47, 48, 53, 70, 96, 97, 105, 106, 73, 76, 148, 149, 139, 80, 88, 67, 83, 84, 85, 81, 87, 66, 89, 76, 91, 78, 66, 94, 148, 149, 1, 98, 99, 100, 101, 66, 103, 104, 112, 113, 107, 12, 76, 110, 111, 128, 70, 121, 122, 123, 124, 118, 76, 49, 50, 51, 80, 53, 111, 83, 84, 85, 1, 87, 66, 89, 66, 91, 66, 65, 94, 130, 131, 12, 98, 99, 100, 101, 66, 103, 104, 148, 149, 107, 76, 152, 110, 111, 148, 149, 143, 148, 149, 146, 118, 76, 76, 76, 151, 70, 153, 76, 76, 76, 76, 76, 76, 76, 76, 80, 76, 76, 83, 84, 85, 1, 87, 78, 89, 78, 91, 78, 78, 94, 148, 149, 12, 98, 99, 100, 101, 70, 103, 104, 78, 81, 107, 76, 81, 110, 111, 80, 93, 85, 83, 84, 85, 118, 87, 101, 89, 1, 91, 93, 95, 94, 93, 93, 93, 98, 99, 100, 101, 95, 103, 104, 126, 101, 107, 122, 101, 110, 111, 122, 128, 108, 139, 148, 149, 118, 109, 128, 127, 147, 70, 152, 148, 125, 146, -1, 76, 146, 142, -1, 80, 125, -1, 83, 84, 85, 127, 87, 127, 89, 127, 91, 154, 129, 94, 148, 149, -1, 98, 99, 100, 101, 142, 103, 104, -1, 70, 107, 142, 142, 110, 111, 76, 142, 142, 142, 80, 142, 118, 83, 84, 85, 146, 87, 150, 89, 28, 91, 148, 148, 94, 148, 148, 148, 98, 99, 100, 101, 148, 103, 104, 148, 148, 107, 46, 47, 110, 111, 148, 149, 52, 148, 54, 148, 118, 40, 41, 42, 43, 44, 45, 46, 47, 48, 66, 148, 148, 0, 148, 46, 47, 148, 74, 75, 148, 52, 78, 54, 148, 148, 82, 8, 9, 10, 148, 149, 148, 148, 148, 66, 8, 9, 10, 148, 148, 148, 148, 74, 75, 148, 27, 78, 29, 30, 31, 82, 148, 148, 148, 27, 149, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 149, 149, 149, 149, 149, 149, 130, 149, 132, 133, 134, 135, 136, 137, 138, 149, 149, 149, 149, 155, 144, 145, 150, 150, 150, 150, 155, 151, 150, 153, 150, 130, 150, 132, 133, 134, 135, 136, 137, 138, 150, 150, 150, 155, 150, 144, 145, 102, 150, 150, 150, 155, 151, 108, 153, 150, 150, 112, 113, 150, 152, 112, 113, 95, 96, 97, 121, 122, 123, 124, 121, 122, 123, 124, 112, 113, 95, 96, 97, 151, 112, 113, 151, 121, 122, 123, 124, 151, 143, 121, 122, 123, 124, 112, 113, 151, 155, 151, 151, 150, 102, 151, 121, 122, 123, 124, 108, 151, 151, 151, 112, 113, 150, 8, 9, 10, 151, 151, 150, 121, 122, 123, 124, 71, 72, 73, 151, 71, 72, 73, 151, 150, 27, 151, 29, 30, 31, 32, 33, 34, 102, 143, 151, 151, 151, 151, 108, 152, 150, 111, 112, 113, 114, 115, 116, 117, 152, 152, 152, 152, 152, 152, 152, 152, 112, 113, 152, 152, 112, 113, 8, 9, 10, 121, 122, 123, 124, 121, 122, 123, 124, 152, 152, 152, 152, 152, 152, 112, 113, 27, 155, 29, 30, 31, 32, 33, 121, 122, 123, 124, 112, 113, 152, 155, 112, 113, 155, -1, 155, 121, 122, 123, 124, 121, 122, 123, 124, 155, 112, 113, 92, 155, 112, 113, 155, 150, 155, 121, 122, 123, 124, 121, 122, 123, 124, 112, 113, 155, 150, 155, 112, 113, 150, -1, 121, 122, 123, 124, -1, 121, 122, 123, 124, -1, -1, -1, 150, -1, -1, -1, 150, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 150 ); protected $actionBase = array( 0, 880, 893, 964, 857, 255, 910, 968, 1004, 1000, 124, 1040, 3, 262, 1018, 861, 1022, 502, 1035, 987, 874, 338, 292, 121, 333, 121, 316, 645, 645, 645, 120, 200, 456, 456, 509, 456, 552, 605, 637, 232, 344, 424, 312, 690, 690, 690, 690, 726, 726, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 690, 84, 748, 629, 622, 741, 738, 736, 735, 820, 640, 941, 802, 794, 537, 792, 790, 787, 786, 785, 803, 784, 776, 664, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 56, 493, 189, 269, 86, 441, 487, 487, 487, 487, 487, 487, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 95, 381, 381, 381, 377, 788, 311, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 813, 62, -17, -17, 863, 422, 457, 475, 1074, 328, 1017, 872, 872, 872, 872, 872, -24, 154, 5, 5, 5, 5, 237, 805, 805, 805, 805, 439, 439, 439, 439, 804, 810, 806, 812, 280, 280, 654, 654, 524, 780, 529, 529, 522, 522, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, -44, 324, 173, 859, 61, 61, 61, 61, 517, 517, 378, 359, 382, 80, 580, 580, 580, 304, 304, 304, 44, 227, 630, 380, 380, 380, 514, 613, 633, 342, -32, -32, -32, -32, 191, 779, -32, -32, -32, 57, 165, 165, 195, 363, 644, 821, 635, 818, 438, 661, -19, 666, 666, 666, 172, 642, 490, 480, 477, 656, 59, 172, 84, 331, 519, 216, 525, 737, 584, 684, 710, 78, 94, 417, 516, 222, 284, 73, 708, 693, 916, 907, 182, 85, 649, 525, 525, 525, 175, 449, 222, 87, 483, 483, 483, 483, 483, 483, 483, 483, 680, 45, 134, 720, 246, 503, 843, 597, 856, 856, 595, 607, 597, 632, 503, 906, 906, 906, 906, 503, 607, 856, 856, 503, 524, 856, 210, 503, 646, 607, 638, 638, 906, 728, 721, 597, 619, 616, 856, 856, 856, 616, 595, 503, 906, 643, 612, 221, 856, 906, 505, 505, 643, 503, 505, 632, 505, 22, 518, 576, 840, 905, 848, 601, 778, 627, 623, 891, 887, 904, 596, 604, 894, 858, 618, 716, 602, 471, 536, 578, 531, 588, 650, 574, 653, 642, 621, 506, 506, 506, 651, 665, 651, 506, 506, 506, 506, 506, 506, 506, 506, 996, 662, 626, 631, 634, 713, 337, 618, 641, 407, 770, 618, 920, 943, 628, 603, 878, 922, 651, 994, 749, 43, 450, 877, 625, 606, 651, 870, 651, 768, 651, 919, 608, 811, 618, 506, 918, 983, 981, 978, 974, 965, 963, 960, 947, 545, 853, 683, 942, 151, 903, 656, 663, 610, 675, 233, 808, 651, 651, 767, 779, 651, 766, 707, 750, 609, 671, 927, 800, 613, 926, 651, 624, 783, 233, 491, 511, 946, 674, 862, 615, 917, 868, 765, 464, 817, 530, 695, 945, 944, 962, 730, 764, 781, 485, 542, 617, 620, 751, 869, 729, 921, 636, 657, 647, 639, 763, 611, 923, 673, 614, 670, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, -17, -17, -17, -17, 130, -17, -17, -17, -17, -17, -17, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, -17, 130, 130, 130, -17, 523, -17, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 523, 130, 0, 0, 130, -17, 130, -17, 130, -17, 130, 130, 130, 130, 130, 130, -17, -17, -17, -17, -17, -17, 0, 580, 580, 580, 580, -17, -17, -17, -17, 950, 950, 950, 950, 523, 523, 523, 523, 523, 523, 580, 580, 304, 304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 523, 950, 950, 523, -32, -32, -32, -32, -32, -32, 165, 165, 165, 284, 0, 0, 0, 0, 0, 0, -32, 607, 165, 368, 368, 368, 165, 165, 165, 284, 0, 0, 0, 0, 607, 368, 0, 0, 0, 856, 0, 0, 0, 368, 484, 484, 484, 484, 233, 222, 0, 607, 607, 607, 0, 619, 0, 0, 0, 856, 0, 0, 0, 0, 0, 0, 506, 43, 878, 139, 288, 0, 0, 0, 0, 0, 0, 0, 288, 288, 393, 393, 0, 0, 545, 506, 506, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 233 ); protected $actionDefault = array( 3,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767, 428, 428,32767, 385,32767,32767,32767,32767, 32767,32767,32767, 189, 189, 189,32767,32767,32767, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 417, 32767,32767,32767,32767,32767, 271,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767, 277, 433,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767, 252, 253, 255, 256, 188, 418, 140, 278, 432, 187, 142, 216, 389,32767,32767,32767, 218, 26, 151, 96, 388, 186, 127, 270, 272, 217, 193, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 192, 343, 249, 248, 247, 345,32767, 344, 382, 382, 385,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767, 214, 371, 370, 215, 341, 219, 342, 221, 346, 220, 237, 238, 235, 236, 239, 348, 347, 364, 365, 362, 363, 191, 240, 241, 242, 243, 366, 367, 368, 369, 173, 173, 173, 173,32767,32767, 427, 427,32767, 32767, 228, 229, 355, 356,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767, 174,32767,32767, 131, 131, 131, 131, 131,32767,32767,32767,32767,32767, 223, 224, 222, 350, 351, 349,32767,32767, 317,32767,32767, 32767,32767,32767, 319,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767, 390, 318,32767,32767,32767,32767, 32767,32767,32767,32767, 403, 306,32767,32767,32767,32767, 299, 115, 117, 65, 374,32767,32767,32767,32767,32767, 408, 233,32767,32767,32767,32767,32767,32767, 440,32767, 403,32767,32767,32767,32767,32767,32767,32767,32767, 246, 225, 226, 227,32767,32767, 407, 401, 358, 359, 360, 361, 352, 353, 354, 357,32767,32767,32767,32767,32767, 69, 314,32767, 320, 320,32767,32767,32767,32767, 69, 32767,32767,32767,32767, 69,32767, 406, 405, 69,32767, 300, 384, 69, 82,32767, 80, 80,32767, 101, 101, 32767,32767, 84, 380, 396,32767, 84,32767, 69,32767, 288, 71, 384,32767,32767, 133, 133, 288, 69, 133, 32767, 133,32767, 4, 324,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767, 301, 32767,32767,32767, 267, 268, 377, 392,32767, 393,32767, 299,32767, 231, 232, 234, 211,32767, 213, 257, 258, 259, 260, 261, 262, 263, 265,32767,32767, 304, 307, 32767,32767,32767, 6, 20, 150,32767, 302,32767, 196, 32767,32767,32767,32767, 435,32767,32767, 190,32767,32767, 22,32767, 146,32767, 67,32767, 425,32767,32767, 401, 303, 230,32767,32767,32767,32767,32767,32767,32767,32767, 32767, 402,32767,32767,32767, 122,32767, 337,32767,32767, 32767, 83,32767, 194, 141,32767,32767, 434,32767,32767, 32767,32767,32767,32767,32767,32767,32767, 68,32767,32767, 85,32767,32767, 401,32767,32767,32767,32767,32767,32767, 185,32767,32767,32767,32767,32767, 401,32767,32767,32767, 126,32767,32767,32767,32767,32767,32767,32767, 4,32767, 167,32767,32767,32767,32767,32767,32767,32767, 28, 28, 3, 28, 109, 28, 153, 3, 101, 101, 62, 153, 28, 153, 153, 28, 28, 28, 28, 28, 160, 28, 28, 28, 28, 28, 28, 28 ); protected $goto = array( 168, 168, 142, 142, 147, 142, 143, 144, 145, 150, 152, 188, 170, 166, 166, 166, 166, 147, 147, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 162, 163, 164, 165, 185, 141, 186, 492, 493, 371, 494, 498, 499, 500, 501, 502, 503, 504, 505, 843, 146, 148, 149, 151, 173, 178, 187, 203, 251, 254, 256, 258, 260, 261, 262, 263, 264, 265, 273, 274, 275, 276, 291, 292, 319, 320, 321, 390, 391, 392, 541, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 153, 154, 155, 169, 156, 171, 157, 204, 172, 158, 159, 160, 205, 161, 139, 557, 700, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 496, 496, 496, 496, 496, 496, 379, 653, 653, 653, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 507, 570, 594, 507, 753, 738, 736, 734, 736, 622, 510, 762, 757, 785, 430, 430, 430, 430, 430, 430, 767, 767, 1072, 1072, 430, 430, 430, 430, 430, 430, 430, 430, 430, 430, 946, 519, 350, 946, 774, 774, 774, 774, 774, 774, 543, 544, 545, 546, 547, 548, 549, 550, 552, 579, 609, 599, 822, 409, 604, 282, 369, 283, 284, 530, 732, 732, 732, 732, 537, 5, 727, 733, 603, 558, 6, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 981, 1076, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 981, 654, 654, 654, 655, 655, 655, 573, 576, 614, 176, 508, 957, 956, 508, 179, 180, 181, 397, 398, 399, 400, 175, 202, 206, 208, 255, 257, 259, 266, 267, 268, 269, 270, 271, 277, 278, 279, 280, 293, 294, 322, 323, 324, 401, 402, 403, 404, 177, 182, 252, 253, 183, 184, 9, 333, 3, 372, 10, 317, 580, 353, 408, 351, 352, 11, 587, 1044, 1, 12, 13, 2, 14, 1032, 7, 15, 16, 17, 18, 19, 20, 396, 596, 536, 536, 563, 532, 939, 513, 383, 384, 534, 534, 495, 497, 524, 539, 564, 567, 577, 583, 513, 962, 1069, 595, 386, 1051, 1082, 1082, 1051, 890, 900, 26, 21, 365, 664, 633, 841, 513, 513, 513, 771, 509, 1085, 1082, 509, 780, 789, 553, 1067, 1067, 1067, 380, 380, 380, 373, 1085, 1085, 542, 522, 29, 1050, 518, 533, 380, 592, 982, 405, 1052, 942, 943, 1052, 395, 939, 932, 518, 518, 937, 446, 451, 670, 568, 794, 741, 1029, 459, 940, 1043, 940, 601, 830, 0, 0, 0, 0, 0, 941, 0, 513, 0, 0, 0, 0, 0, 0, 0, 0, 517, 0, 0, 0, 0, 0, 0, 0, 0, 540, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 523 ); protected $gotoCheck = array( 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 39, 32, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 95, 95, 95, 95, 95, 95, 5, 6, 6, 6, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 22, 22, 95, 6, 6, 6, 6, 6, 6, 6, 6, 6, 63, 39, 39, 39, 39, 39, 39, 56, 56, 56, 56, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 79, 51, 39, 39, 39, 39, 39, 39, 39, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 39, 43, 76, 76, 43, 47, 43, 47, 47, 5, 39, 39, 39, 39, 87, 2, 39, 39, 39, 98, 2, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 105, 119, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 7, 7, 7, 8, 8, 8, 42, 42, 42, 13, 98, 103, 103, 98, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 104, 14, 29, 14, 104, 49, 49, 49, 51, 51, 14, 107, 61, 14, 14, 14, 14, 14, 111, 14, 14, 14, 14, 14, 14, 14, 33, 33, 33, 33, 33, 33, 61, 4, 9, 9, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 4, 16, 117, 31, 30, 97, 120, 120, 97, 80, 16, 16, 16, 16, 11, 53, 79, 4, 4, 4, 58, 101, 120, 120, 101, 60, 64, 16, 97, 97, 97, 102, 102, 102, 40, 120, 120, 26, 40, 16, 97, 26, 40, 102, 16, 106, 10, 96, 61, 61, 96, 102, 61, 91, 26, 26, 93, 45, 40, 12, 46, 65, 50, 110, 86, 61, 61, 61, 40, 78, -1, -1, -1, -1, -1, 61, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 79 ); protected $gotoBase = array( 0, 0, -378, 0, 95, -180, 156, 330, 333, 66, 63, 90, 53, 136, -232, 0, 24, 0, 0, 0, 0, 0, 130, 0, 0, -30, 441, 0, 0, 344, 142, 151, 85, 129, 0, 0, 0, 0, 0, -98, 44, 0, 30, -228, 0, 55, 48, -397, 0, 57, 49, -230, 0, 82, 0, 0, -92, 0, 141, 0, 145, 56, 0, 155, 94, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -77, 0, 43, 161, 135, 0, 0, 0, 0, 0, 41, 208, 167, 0, 0, 73, 0, 71, 0, -132, 176, 134, 39, 0, 0, 150, 137, 16, 61, 83, 111, 189, 0, 0, 45, 195, 0, 0, 0, 0, 0, 148, 0, 256, 124, 0 ); protected $gotoDefault = array( -32768, 462, 4, 648, 479, 514, 675, 676, 677, 375, 374, 665, 671, 174, 8, 673, 891, 361, 680, 362, 582, 682, 526, 684, 685, 140, 480, 376, 377, 527, 385, 571, 699, 272, 382, 701, 363, 703, 709, 364, 602, 586, 554, 598, 481, 442, 565, 281, 535, 561, 740, 349, 748, 636, 756, 759, 482, 555, 770, 448, 778, 967, 393, 784, 790, 795, 798, 418, 406, 578, 802, 803, 325, 807, 610, 611, 821, 306, 829, 842, 414, 910, 912, 483, 484, 520, 456, 506, 525, 485, 933, 436, 407, 936, 486, 487, 426, 427, 954, 951, 355, 1037, 354, 444, 316, 1022, 1021, 574, 986, 452, 1075, 1033, 344, 488, 489, 370, 387, 1070, 431, 1077, 1084, 562 ); protected $ruleToNonTerminal = array( 0, 1, 2, 2, 4, 4, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 9, 9, 11, 11, 11, 11, 10, 10, 12, 14, 14, 15, 15, 15, 15, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 36, 36, 38, 37, 37, 30, 30, 40, 40, 41, 41, 7, 8, 8, 8, 44, 44, 44, 45, 45, 48, 48, 46, 46, 49, 49, 23, 23, 32, 32, 35, 35, 34, 34, 50, 24, 24, 24, 24, 51, 51, 52, 52, 53, 53, 21, 21, 17, 17, 54, 19, 19, 55, 18, 18, 20, 20, 31, 31, 31, 42, 42, 57, 57, 58, 58, 60, 60, 60, 59, 59, 43, 43, 61, 61, 61, 62, 62, 63, 63, 63, 27, 27, 64, 64, 64, 28, 28, 65, 65, 47, 47, 66, 66, 66, 66, 71, 71, 72, 72, 73, 73, 73, 73, 74, 75, 75, 70, 70, 67, 67, 69, 69, 77, 77, 76, 76, 76, 76, 76, 76, 68, 68, 78, 78, 29, 29, 22, 22, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 16, 16, 26, 26, 83, 83, 84, 84, 84, 84, 90, 79, 79, 86, 86, 92, 92, 93, 94, 94, 94, 94, 94, 94, 98, 98, 39, 39, 39, 80, 80, 99, 99, 95, 95, 100, 100, 100, 100, 81, 81, 81, 85, 85, 85, 91, 91, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 13, 13, 13, 13, 13, 13, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 89, 89, 82, 82, 82, 82, 106, 106, 107, 107, 110, 110, 109, 109, 111, 111, 33, 33, 33, 33, 113, 113, 112, 112, 112, 112, 112, 114, 114, 97, 97, 101, 101, 96, 96, 115, 115, 115, 115, 102, 102, 102, 102, 88, 88, 103, 103, 103, 56, 116, 116, 117, 117, 117, 87, 87, 118, 118, 119, 119, 119, 119, 104, 104, 104, 104, 120, 120, 120, 120, 120, 120, 120, 121, 121, 121 ); protected $ruleToLength = array( 1, 1, 2, 0, 1, 3, 1, 1, 1, 1, 1, 3, 5, 4, 3, 4, 4, 3, 3, 1, 1, 3, 2, 4, 3, 1, 3, 2, 0, 1, 1, 1, 1, 3, 5, 8, 3, 5, 9, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 1, 2, 5, 7, 9, 5, 1, 6, 3, 3, 2, 1, 0, 2, 8, 0, 4, 1, 3, 0, 1, 0, 1, 10, 7, 6, 5, 1, 2, 2, 0, 2, 0, 2, 0, 2, 1, 3, 1, 4, 1, 4, 1, 4, 1, 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, 1, 1, 1, 4, 0, 2, 3, 0, 2, 4, 0, 2, 0, 3, 1, 2, 1, 1, 0, 1, 3, 4, 6, 1, 1, 1, 0, 1, 0, 2, 2, 3, 3, 1, 3, 1, 2, 2, 3, 1, 1, 2, 4, 3, 1, 1, 3, 2, 0, 3, 3, 9, 3, 1, 3, 0, 2, 4, 5, 4, 4, 3, 1, 1, 1, 3, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 3, 1, 0, 1, 1, 3, 3, 4, 4, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 5, 4, 3, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 2, 1, 2, 10, 11, 3, 3, 2, 4, 4, 3, 4, 4, 4, 4, 7, 3, 2, 0, 4, 1, 3, 2, 2, 4, 6, 2, 2, 4, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 3, 3, 4, 4, 0, 2, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 3, 1, 4, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 1, 3, 1, 1, 3, 3, 1, 1, 0, 2, 0, 1, 3, 1, 3, 1, 1, 1, 1, 1, 6, 4, 3, 4, 2, 4, 4, 1, 3, 1, 2, 1, 1, 4, 1, 3, 6, 4, 4, 4, 4, 1, 4, 0, 1, 1, 3, 1, 4, 3, 1, 1, 1, 0, 0, 2, 3, 1, 3, 1, 4, 2, 2, 2, 1, 2, 1, 4, 3, 3, 3, 6, 3, 1, 1, 1 ); protected function reduceRule0() { $this->semValue = $this->semStack[$this->stackPos]; } protected function reduceRule1() { $this->semValue = $this->handleNamespaces($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule2() { if (is_array($this->semStack[$this->stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } else { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; }; } protected function reduceRule3() { $this->semValue = array(); } protected function reduceRule4() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule5() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule6() { $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule7() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule8() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule9() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule10() { $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule11() { $this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(3-2)], null, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule12() { $this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(5-2)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); } protected function reduceRule13() { $this->semValue = new Stmt\Namespace_(null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule14() { $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule15() { $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(4-3)], Stmt\Use_::TYPE_FUNCTION, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule16() { $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(4-3)], Stmt\Use_::TYPE_CONSTANT, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule17() { $this->semValue = new Stmt\Const_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule18() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule19() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule20() { $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(1-1)], null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule21() { $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule22() { $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(2-2)], null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule23() { $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule24() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule25() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule26() { $this->semValue = new Node\Const_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule27() { if (is_array($this->semStack[$this->stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } else { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; }; } protected function reduceRule28() { $this->semValue = array(); } protected function reduceRule29() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule30() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule31() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule32() { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule33() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule34() { $this->semValue = new Stmt\If_($this->semStack[$this->stackPos-(5-2)], array('stmts' => is_array($this->semStack[$this->stackPos-(5-3)]) ? $this->semStack[$this->stackPos-(5-3)] : array($this->semStack[$this->stackPos-(5-3)]), 'elseifs' => $this->semStack[$this->stackPos-(5-4)], 'else' => $this->semStack[$this->stackPos-(5-5)]), $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); } protected function reduceRule35() { $this->semValue = new Stmt\If_($this->semStack[$this->stackPos-(8-2)], array('stmts' => $this->semStack[$this->stackPos-(8-4)], 'elseifs' => $this->semStack[$this->stackPos-(8-5)], 'else' => $this->semStack[$this->stackPos-(8-6)]), $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes); } protected function reduceRule36() { $this->semValue = new Stmt\While_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule37() { $this->semValue = new Stmt\Do_($this->semStack[$this->stackPos-(5-4)], is_array($this->semStack[$this->stackPos-(5-2)]) ? $this->semStack[$this->stackPos-(5-2)] : array($this->semStack[$this->stackPos-(5-2)]), $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); } protected function reduceRule38() { $this->semValue = new Stmt\For_(array('init' => $this->semStack[$this->stackPos-(9-3)], 'cond' => $this->semStack[$this->stackPos-(9-5)], 'loop' => $this->semStack[$this->stackPos-(9-7)], 'stmts' => $this->semStack[$this->stackPos-(9-9)]), $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes); } protected function reduceRule39() { $this->semValue = new Stmt\Switch_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule40() { $this->semValue = new Stmt\Break_(null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule41() { $this->semValue = new Stmt\Break_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule42() { $this->semValue = new Stmt\Continue_(null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule43() { $this->semValue = new Stmt\Continue_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule44() { $this->semValue = new Stmt\Return_(null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule45() { $this->semValue = new Stmt\Return_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule46() { $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule47() { $this->semValue = new Stmt\Global_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule48() { $this->semValue = new Stmt\Static_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule49() { $this->semValue = new Stmt\Echo_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule50() { $this->semValue = new Stmt\InlineHTML($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule51() { $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule52() { $this->semValue = new Stmt\Unset_($this->semStack[$this->stackPos-(5-3)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); } protected function reduceRule53() { $this->semValue = new Stmt\Foreach_($this->semStack[$this->stackPos-(7-3)], $this->semStack[$this->stackPos-(7-5)][0], array('keyVar' => null, 'byRef' => $this->semStack[$this->stackPos-(7-5)][1], 'stmts' => $this->semStack[$this->stackPos-(7-7)]), $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); } protected function reduceRule54() { $this->semValue = new Stmt\Foreach_($this->semStack[$this->stackPos-(9-3)], $this->semStack[$this->stackPos-(9-7)][0], array('keyVar' => $this->semStack[$this->stackPos-(9-5)], 'byRef' => $this->semStack[$this->stackPos-(9-7)][1], 'stmts' => $this->semStack[$this->stackPos-(9-9)]), $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes); } protected function reduceRule55() { $this->semValue = new Stmt\Declare_($this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); } protected function reduceRule56() { $this->semValue = array(); /* means: no statement */ } protected function reduceRule57() { $this->semValue = new Stmt\TryCatch($this->semStack[$this->stackPos-(6-3)], $this->semStack[$this->stackPos-(6-5)], $this->semStack[$this->stackPos-(6-6)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); } protected function reduceRule58() { $this->semValue = new Stmt\Throw_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule59() { $this->semValue = new Stmt\Goto_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule60() { $this->semValue = new Stmt\Label($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule61() { $this->semValue = array(); /* means: no statement */ } protected function reduceRule62() { $this->semValue = array(); } protected function reduceRule63() { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule64() { $this->semValue = new Stmt\Catch_($this->semStack[$this->stackPos-(8-3)], substr($this->semStack[$this->stackPos-(8-4)], 1), $this->semStack[$this->stackPos-(8-7)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes); } protected function reduceRule65() { $this->semValue = null; } protected function reduceRule66() { $this->semValue = $this->semStack[$this->stackPos-(4-3)]; } protected function reduceRule67() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule68() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule69() { $this->semValue = false; } protected function reduceRule70() { $this->semValue = true; } protected function reduceRule71() { $this->semValue = false; } protected function reduceRule72() { $this->semValue = true; } protected function reduceRule73() { $this->semValue = new Stmt\Function_($this->semStack[$this->stackPos-(10-3)], array('byRef' => $this->semStack[$this->stackPos-(10-2)], 'params' => $this->semStack[$this->stackPos-(10-5)], 'returnType' => $this->semStack[$this->stackPos-(10-7)], 'stmts' => $this->semStack[$this->stackPos-(10-9)]), $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes); } protected function reduceRule74() { $this->semValue = new Stmt\Class_($this->semStack[$this->stackPos-(7-2)], array('type' => $this->semStack[$this->stackPos-(7-1)], 'extends' => $this->semStack[$this->stackPos-(7-3)], 'implements' => $this->semStack[$this->stackPos-(7-4)], 'stmts' => $this->semStack[$this->stackPos-(7-6)]), $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); } protected function reduceRule75() { $this->semValue = new Stmt\Interface_($this->semStack[$this->stackPos-(6-2)], array('extends' => $this->semStack[$this->stackPos-(6-3)], 'stmts' => $this->semStack[$this->stackPos-(6-5)]), $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); } protected function reduceRule76() { $this->semValue = new Stmt\Trait_($this->semStack[$this->stackPos-(5-2)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); } protected function reduceRule77() { $this->semValue = 0; } protected function reduceRule78() { $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; } protected function reduceRule79() { $this->semValue = Stmt\Class_::MODIFIER_FINAL; } protected function reduceRule80() { $this->semValue = null; } protected function reduceRule81() { $this->semValue = $this->semStack[$this->stackPos-(2-2)]; } protected function reduceRule82() { $this->semValue = array(); } protected function reduceRule83() { $this->semValue = $this->semStack[$this->stackPos-(2-2)]; } protected function reduceRule84() { $this->semValue = array(); } protected function reduceRule85() { $this->semValue = $this->semStack[$this->stackPos-(2-2)]; } protected function reduceRule86() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule87() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule88() { $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule89() { $this->semValue = $this->semStack[$this->stackPos-(4-2)]; } protected function reduceRule90() { $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule91() { $this->semValue = $this->semStack[$this->stackPos-(4-2)]; } protected function reduceRule92() { $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule93() { $this->semValue = $this->semStack[$this->stackPos-(4-2)]; } protected function reduceRule94() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule95() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule96() { $this->semValue = new Stmt\DeclareDeclare($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule97() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule98() { $this->semValue = $this->semStack[$this->stackPos-(4-3)]; } protected function reduceRule99() { $this->semValue = $this->semStack[$this->stackPos-(4-2)]; } protected function reduceRule100() { $this->semValue = $this->semStack[$this->stackPos-(5-3)]; } protected function reduceRule101() { $this->semValue = array(); } protected function reduceRule102() { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule103() { $this->semValue = new Stmt\Case_($this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule104() { $this->semValue = new Stmt\Case_(null, $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule105() { $this->semValue = $this->semStack[$this->stackPos]; } protected function reduceRule106() { $this->semValue = $this->semStack[$this->stackPos]; } protected function reduceRule107() { $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule108() { $this->semValue = $this->semStack[$this->stackPos-(4-2)]; } protected function reduceRule109() { $this->semValue = array(); } protected function reduceRule110() { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule111() { $this->semValue = new Stmt\ElseIf_($this->semStack[$this->stackPos-(3-2)], is_array($this->semStack[$this->stackPos-(3-3)]) ? $this->semStack[$this->stackPos-(3-3)] : array($this->semStack[$this->stackPos-(3-3)]), $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule112() { $this->semValue = array(); } protected function reduceRule113() { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule114() { $this->semValue = new Stmt\ElseIf_($this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule115() { $this->semValue = null; } protected function reduceRule116() { $this->semValue = new Stmt\Else_(is_array($this->semStack[$this->stackPos-(2-2)]) ? $this->semStack[$this->stackPos-(2-2)] : array($this->semStack[$this->stackPos-(2-2)]), $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule117() { $this->semValue = null; } protected function reduceRule118() { $this->semValue = new Stmt\Else_($this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule119() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false); } protected function reduceRule120() { $this->semValue = array($this->semStack[$this->stackPos-(2-2)], true); } protected function reduceRule121() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false); } protected function reduceRule122() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule123() { $this->semValue = array(); } protected function reduceRule124() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule125() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule126() { $this->semValue = new Node\Param(substr($this->semStack[$this->stackPos-(4-4)], 1), null, $this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule127() { $this->semValue = new Node\Param(substr($this->semStack[$this->stackPos-(6-4)], 1), $this->semStack[$this->stackPos-(6-6)], $this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-2)], $this->semStack[$this->stackPos-(6-3)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); } protected function reduceRule128() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule129() { $this->semValue = 'array'; } protected function reduceRule130() { $this->semValue = 'callable'; } protected function reduceRule131() { $this->semValue = null; } protected function reduceRule132() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule133() { $this->semValue = null; } protected function reduceRule134() { $this->semValue = $this->semStack[$this->stackPos-(2-2)]; } protected function reduceRule135() { $this->semValue = array(); } protected function reduceRule136() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule137() { $this->semValue = array(new Node\Arg($this->semStack[$this->stackPos-(3-2)], false, false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes)); } protected function reduceRule138() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule139() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule140() { $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(1-1)], false, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule141() { $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(2-2)], true, false, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule142() { $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(2-2)], false, true, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule143() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule144() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule145() { $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule146() { $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule147() { $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule148() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule149() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule150() { $this->semValue = new Stmt\StaticVar(substr($this->semStack[$this->stackPos-(1-1)], 1), null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule151() { $this->semValue = new Stmt\StaticVar(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule152() { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule153() { $this->semValue = array(); } protected function reduceRule154() { $this->semValue = new Stmt\Property($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule155() { $this->semValue = new Stmt\ClassConst($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule156() { $this->semValue = new Stmt\ClassMethod($this->semStack[$this->stackPos-(9-4)], array('type' => $this->semStack[$this->stackPos-(9-1)], 'byRef' => $this->semStack[$this->stackPos-(9-3)], 'params' => $this->semStack[$this->stackPos-(9-6)], 'returnType' => $this->semStack[$this->stackPos-(9-8)], 'stmts' => $this->semStack[$this->stackPos-(9-9)]), $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes); } protected function reduceRule157() { $this->semValue = new Stmt\TraitUse($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule158() { $this->semValue = array(); } protected function reduceRule159() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule160() { $this->semValue = array(); } protected function reduceRule161() { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule162() { $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule163() { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(5-1)][0], $this->semStack[$this->stackPos-(5-1)][1], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); } protected function reduceRule164() { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], $this->semStack[$this->stackPos-(4-3)], null, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule165() { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule166() { $this->semValue = array($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)]); } protected function reduceRule167() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule168() { $this->semValue = array(null, $this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule169() { $this->semValue = null; } protected function reduceRule170() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule171() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule172() { $this->semValue = 0; } protected function reduceRule173() { $this->semValue = 0; } protected function reduceRule174() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule175() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule176() { Stmt\Class_::verifyModifier($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); $this->semValue = $this->semStack[$this->stackPos-(2-1)] | $this->semStack[$this->stackPos-(2-2)]; } protected function reduceRule177() { $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; } protected function reduceRule178() { $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; } protected function reduceRule179() { $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; } protected function reduceRule180() { $this->semValue = Stmt\Class_::MODIFIER_STATIC; } protected function reduceRule181() { $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; } protected function reduceRule182() { $this->semValue = Stmt\Class_::MODIFIER_FINAL; } protected function reduceRule183() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule184() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule185() { $this->semValue = new Stmt\PropertyProperty(substr($this->semStack[$this->stackPos-(1-1)], 1), null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule186() { $this->semValue = new Stmt\PropertyProperty(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule187() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule188() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule189() { $this->semValue = array(); } protected function reduceRule190() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule191() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule192() { $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule193() { $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule194() { $this->semValue = new Expr\AssignRef($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule195() { $this->semValue = new Expr\AssignRef($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule196() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule197() { $this->semValue = new Expr\Clone_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule198() { $this->semValue = new Expr\AssignOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule199() { $this->semValue = new Expr\AssignOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule200() { $this->semValue = new Expr\AssignOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule201() { $this->semValue = new Expr\AssignOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule202() { $this->semValue = new Expr\AssignOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule203() { $this->semValue = new Expr\AssignOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule204() { $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule205() { $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule206() { $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule207() { $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule208() { $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule209() { $this->semValue = new Expr\AssignOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule210() { $this->semValue = new Expr\PostInc($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule211() { $this->semValue = new Expr\PreInc($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule212() { $this->semValue = new Expr\PostDec($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule213() { $this->semValue = new Expr\PreDec($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule214() { $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule215() { $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule216() { $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule217() { $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule218() { $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule219() { $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule220() { $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule221() { $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule222() { $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule223() { $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule224() { $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule225() { $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule226() { $this->semValue = new Expr\BinaryOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule227() { $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule228() { $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule229() { $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule230() { $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule231() { $this->semValue = new Expr\UnaryPlus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule232() { $this->semValue = new Expr\UnaryMinus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule233() { $this->semValue = new Expr\BooleanNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule234() { $this->semValue = new Expr\BitwiseNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule235() { $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule236() { $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule237() { $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule238() { $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule239() { $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule240() { $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule241() { $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule242() { $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule243() { $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule244() { $this->semValue = new Expr\Instanceof_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule245() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule246() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule247() { $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(5-1)], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); } protected function reduceRule248() { $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(4-1)], null, $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule249() { $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule250() { $this->semValue = new Expr\Isset_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule251() { $this->semValue = new Expr\Empty_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule252() { $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule253() { $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule254() { $this->semValue = new Expr\Eval_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule255() { $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule256() { $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule257() { $this->semValue = new Expr\Cast\Int_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule258() { $this->semValue = new Expr\Cast\Double($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule259() { $this->semValue = new Expr\Cast\String_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule260() { $this->semValue = new Expr\Cast\Array_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule261() { $this->semValue = new Expr\Cast\Object_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule262() { $this->semValue = new Expr\Cast\Bool_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule263() { $this->semValue = new Expr\Cast\Unset_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule264() { $this->semValue = new Expr\Exit_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule265() { $this->semValue = new Expr\ErrorSuppress($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule266() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule267() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule268() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule269() { $this->semValue = new Expr\ShellExec($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule270() { $this->semValue = new Expr\Print_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule271() { $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule272() { $this->semValue = new Expr\YieldFrom($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule273() { $this->semValue = new Expr\Closure(array('static' => false, 'byRef' => $this->semStack[$this->stackPos-(10-2)], 'params' => $this->semStack[$this->stackPos-(10-4)], 'uses' => $this->semStack[$this->stackPos-(10-6)], 'returnType' => $this->semStack[$this->stackPos-(10-7)], 'stmts' => $this->semStack[$this->stackPos-(10-9)]), $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes); } protected function reduceRule274() { $this->semValue = new Expr\Closure(array('static' => true, 'byRef' => $this->semStack[$this->stackPos-(11-3)], 'params' => $this->semStack[$this->stackPos-(11-5)], 'uses' => $this->semStack[$this->stackPos-(11-7)], 'returnType' => $this->semStack[$this->stackPos-(11-8)], 'stmts' => $this->semStack[$this->stackPos-(11-10)]), $this->startAttributeStack[$this->stackPos-(11-1)] + $this->endAttributes); } protected function reduceRule275() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule276() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule277() { $this->semValue = new Expr\Yield_($this->semStack[$this->stackPos-(2-2)], null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule278() { $this->semValue = new Expr\Yield_($this->semStack[$this->stackPos-(4-4)], $this->semStack[$this->stackPos-(4-2)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule279() { $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule280() { $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule281() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule282() { $this->semValue = new Expr\ArrayDimFetch(new Scalar\String_(Scalar\String_::parse($this->semStack[$this->stackPos-(4-1)]), $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule283() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule284() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule285() { $this->semValue = array(new Stmt\Class_(null, array('type' => 0, 'extends' => $this->semStack[$this->stackPos-(7-3)], 'implements' => $this->semStack[$this->stackPos-(7-4)], 'stmts' => $this->semStack[$this->stackPos-(7-6)]), $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(7-2)]); } protected function reduceRule286() { $this->semValue = new Expr\New_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule287() { list($class, $ctorArgs) = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule288() { $this->semValue = array(); } protected function reduceRule289() { $this->semValue = $this->semStack[$this->stackPos-(4-3)]; } protected function reduceRule290() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule291() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule292() { $this->semValue = new Expr\ClosureUse(substr($this->semStack[$this->stackPos-(2-2)], 1), $this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule293() { $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule294() { $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule295() { $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-4)], $this->semStack[$this->stackPos-(6-6)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); } protected function reduceRule296() { if ($this->semStack[$this->stackPos-(2-1)] instanceof Node\Expr\StaticPropertyFetch) { $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(2-1)]->class, new Expr\Variable($this->semStack[$this->stackPos-(2-1)]->name, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } elseif ($this->semStack[$this->stackPos-(2-1)] instanceof Node\Expr\ArrayDimFetch) { $tmp = $this->semStack[$this->stackPos-(2-1)]; while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { $tmp = $tmp->var; } $this->semValue = new Expr\StaticCall($tmp->var->class, $this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); $tmp->var = new Expr\Variable($tmp->var->name, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } else { throw new \Exception; } } protected function reduceRule297() { $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule298() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule299() { $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule300() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule301() { $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule302() { $this->semValue = new Name\FullyQualified($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule303() { $this->semValue = new Name\Relative($this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule304() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule305() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule306() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule307() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule308() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule309() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule310() { $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule311() { $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule312() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule313() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule314() { $this->semValue = null; } protected function reduceRule315() { $this->semValue = null; } protected function reduceRule316() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule317() { $this->semValue = array(); } protected function reduceRule318() { $this->semValue = array(Scalar\String_::parseEscapeSequences($this->semStack[$this->stackPos-(1-1)], '`')); } protected function reduceRule319() { foreach ($this->semStack[$this->stackPos-(1-1)] as &$s) { if (is_string($s)) { $s = Node\Scalar\String_::parseEscapeSequences($s, '`'); } }; $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule320() { $this->semValue = array(); } protected function reduceRule321() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule322() { $this->semValue = new Scalar\LNumber(Scalar\LNumber::parse($this->semStack[$this->stackPos-(1-1)]), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule323() { $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$this->stackPos-(1-1)]), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule324() { $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$this->stackPos-(1-1)]), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule325() { $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule326() { $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule327() { $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule328() { $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule329() { $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule330() { $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule331() { $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule332() { $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule333() { $this->semValue = new Scalar\String_(Scalar\String_::parseDocString($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-2)]), $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule334() { $this->semValue = new Scalar\String_('', $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule335() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule336() { $this->semValue = new Expr\ClassConstFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule337() { $this->semValue = new Expr\ConstFetch($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule338() { $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule339() { $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule340() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule341() { $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule342() { $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule343() { $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule344() { $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule345() { $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule346() { $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule347() { $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule348() { $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule349() { $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule350() { $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule351() { $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule352() { $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule353() { $this->semValue = new Expr\BinaryOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule354() { $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule355() { $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule356() { $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule357() { $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule358() { $this->semValue = new Expr\UnaryPlus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule359() { $this->semValue = new Expr\UnaryMinus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule360() { $this->semValue = new Expr\BooleanNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule361() { $this->semValue = new Expr\BitwiseNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule362() { $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule363() { $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule364() { $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule365() { $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule366() { $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule367() { $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule368() { $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule369() { $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule370() { $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(5-1)], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); } protected function reduceRule371() { $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(4-1)], null, $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule372() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule373() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule374() { $this->semValue = new Expr\ConstFetch($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule375() { $this->semValue = new Expr\ClassConstFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule376() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule377() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule378() { foreach ($this->semStack[$this->stackPos-(3-2)] as &$s) { if (is_string($s)) { $s = Node\Scalar\String_::parseEscapeSequences($s, '"'); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule379() { foreach ($this->semStack[$this->stackPos-(3-2)] as &$s) { if (is_string($s)) { $s = Node\Scalar\String_::parseEscapeSequences($s, null); } } $s = preg_replace('~(\r\n|\n|\r)\z~', '', $s); if ('' === $s) array_pop($this->semStack[$this->stackPos-(3-2)]);; $this->semValue = new Scalar\Encapsed($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule380() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule381() { $this->semValue = 'class'; } protected function reduceRule382() { $this->semValue = array(); } protected function reduceRule383() { $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule384() { $this->semValue = $this->semStack[$this->stackPos]; } protected function reduceRule385() { $this->semValue = $this->semStack[$this->stackPos]; } protected function reduceRule386() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule387() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule388() { $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule389() { $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule390() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule391() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule392() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule393() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule394() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(6-2)], $this->semStack[$this->stackPos-(6-5)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); } protected function reduceRule395() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule396() { $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule397() { $this->semValue = new Expr\MethodCall($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule398() { $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule399() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule400() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule401() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule402() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule403() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule404() { $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule405() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule406() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule407() { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule408() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule409() { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(3-1)], substr($this->semStack[$this->stackPos-(3-3)], 1), $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule410() { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-5)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); } protected function reduceRule411() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule412() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule413() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule414() { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule415() { $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule416() { $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule417() { $this->semValue = null; } protected function reduceRule418() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule419() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule420() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule421() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule422() { $this->semValue = new Expr\List_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule423() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule424() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule425() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule426() { $this->semValue = $this->semStack[$this->stackPos-(1-1)]; } protected function reduceRule427() { $this->semValue = null; } protected function reduceRule428() { $this->semValue = array(); } protected function reduceRule429() { $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule430() { $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; } protected function reduceRule431() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule432() { $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule433() { $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule434() { $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(4-4)], $this->semStack[$this->stackPos-(4-1)], true, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule435() { $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(2-2)], null, true, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); } protected function reduceRule436() { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule437() { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; } protected function reduceRule438() { $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); } protected function reduceRule439() { $this->semValue = array($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } protected function reduceRule440() { $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule441() { $this->semValue = new Expr\ArrayDimFetch(new Expr\Variable(substr($this->semStack[$this->stackPos-(4-1)], 1), $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); } protected function reduceRule442() { $this->semValue = new Expr\PropertyFetch(new Expr\Variable(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule443() { $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule444() { $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); } protected function reduceRule445() { $this->semValue = new Expr\ArrayDimFetch(new Expr\Variable($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(6-4)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); } protected function reduceRule446() { $this->semValue = $this->semStack[$this->stackPos-(3-2)]; } protected function reduceRule447() { $this->semValue = new Scalar\String_($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule448() { $this->semValue = new Scalar\String_($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } protected function reduceRule449() { $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); } } ='); } /** * Handles autoloading of classes. * * @param string $class A class name. */ static public function autoload($class) { if (0 === strpos($class, 'PhpParser\\')) { if (isset(self::$php7AliasesOldToNew[$class])) { if (self::$runningOnPhp7) { return; } // Load the new class, alias will be registered afterwards $class = self::$php7AliasesOldToNew[$class]; } $fileName = dirname(__DIR__) . '/' . strtr($class, '\\', '/') . '.php'; if (file_exists($fileName)) { require $fileName; } if (isset(self::$php7AliasesNewToOld[$class])) { // New class name was used, register alias for old one, otherwise // it won't be usable in "instanceof" and other non-autoloading places. if (!self::$runningOnPhp7) { class_alias($class, self::$php7AliasesNewToOld[$class]); } } } else if (0 === strpos($class, 'PHPParser_')) { if (isset(self::$nonNamespacedAliases[$class])) { // Register all aliases at once to avoid dependency issues self::registerNonNamespacedAliases(); } } } private static function registerNonNamespacedAliases() { foreach (self::$nonNamespacedAliases as $old => $new) { class_alias($new, $old); } } private static $php7AliasesOldToNew = array( 'PhpParser\Node\Expr\Cast\Bool' => 'PhpParser\Node\Expr\Cast\Bool_', 'PhpParser\Node\Expr\Cast\Int' => 'PhpParser\Node\Expr\Cast\Int_', 'PhpParser\Node\Expr\Cast\Object' => 'PhpParser\Node\Expr\Cast\Object_', 'PhpParser\Node\Expr\Cast\String' => 'PhpParser\Node\Expr\Cast\String_', 'PhpParser\Node\Scalar\String' => 'PhpParser\Node\Scalar\String_', ); private static $php7AliasesNewToOld = array( 'PhpParser\Node\Expr\Cast\Bool_' => 'PhpParser\Node\Expr\Cast\Bool', 'PhpParser\Node\Expr\Cast\Int_' => 'PhpParser\Node\Expr\Cast\Int', 'PhpParser\Node\Expr\Cast\Object_' => 'PhpParser\Node\Expr\Cast\Object', 'PhpParser\Node\Expr\Cast\String_' => 'PhpParser\Node\Expr\Cast\String', 'PhpParser\Node\Scalar\String_' => 'PhpParser\Node\Scalar\String', ); private static $nonNamespacedAliases = array( 'PHPParser_Builder' => 'PhpParser\Builder', 'PHPParser_BuilderAbstract' => 'PhpParser\BuilderAbstract', 'PHPParser_BuilderFactory' => 'PhpParser\BuilderFactory', 'PHPParser_Comment' => 'PhpParser\Comment', 'PHPParser_Comment_Doc' => 'PhpParser\Comment\Doc', 'PHPParser_Error' => 'PhpParser\Error', 'PHPParser_Lexer' => 'PhpParser\Lexer', 'PHPParser_Lexer_Emulative' => 'PhpParser\Lexer\Emulative', 'PHPParser_Node' => 'PhpParser\Node', 'PHPParser_NodeAbstract' => 'PhpParser\NodeAbstract', 'PHPParser_NodeDumper' => 'PhpParser\NodeDumper', 'PHPParser_NodeTraverser' => 'PhpParser\NodeTraverser', 'PHPParser_NodeTraverserInterface' => 'PhpParser\NodeTraverserInterface', 'PHPParser_NodeVisitor' => 'PhpParser\NodeVisitor', 'PHPParser_NodeVisitor_NameResolver' => 'PhpParser\NodeVisitor\NameResolver', 'PHPParser_NodeVisitorAbstract' => 'PhpParser\NodeVisitorAbstract', 'PHPParser_Parser' => 'PhpParser\Parser', 'PHPParser_PrettyPrinterAbstract' => 'PhpParser\PrettyPrinterAbstract', 'PHPParser_PrettyPrinter_Default' => 'PhpParser\PrettyPrinter\Standard', 'PHPParser_PrettyPrinter_Zend' => 'PhpParser\PrettyPrinter\Standard', 'PHPParser_Serializer' => 'PhpParser\Serializer', 'PHPParser_Serializer_XML' => 'PhpParser\Serializer\XML', 'PHPParser_Unserializer' => 'PhpParser\Unserializer', 'PHPParser_Unserializer_XML' => 'PhpParser\Unserializer\XML', 'PHPParser_Builder_Class' => 'PhpParser\Builder\Class_', 'PHPParser_Builder_Function' => 'PhpParser\Builder\Function_', 'PHPParser_Builder_Interface' => 'PhpParser\Builder\Interface_', 'PHPParser_Builder_Method' => 'PhpParser\Builder\Method', 'PHPParser_Builder_Param' => 'PhpParser\Builder\Param', 'PHPParser_Builder_Property' => 'PhpParser\Builder\Property', 'PHPParser_Node_Arg' => 'PhpParser\Node\Arg', 'PHPParser_Node_Const' => 'PhpParser\Node\Const_', 'PHPParser_Node_Expr' => 'PhpParser\Node\Expr', 'PHPParser_Node_Name' => 'PhpParser\Node\Name', 'PHPParser_Node_Name_FullyQualified' => 'PhpParser\Node\Name\FullyQualified', 'PHPParser_Node_Name_Relative' => 'PhpParser\Node\Name\Relative', 'PHPParser_Node_Param' => 'PhpParser\Node\Param', 'PHPParser_Node_Scalar' => 'PhpParser\Node\Scalar', 'PHPParser_Node_Stmt' => 'PhpParser\Node\Stmt', 'PHPParser_Node_Stmt_Break' => 'PhpParser\Node\Stmt\Break_', 'PHPParser_Node_Stmt_Case' => 'PhpParser\Node\Stmt\Case_', 'PHPParser_Node_Stmt_Catch' => 'PhpParser\Node\Stmt\Catch_', 'PHPParser_Node_Stmt_Class' => 'PhpParser\Node\Stmt\Class_', 'PHPParser_Node_Stmt_ClassConst' => 'PhpParser\Node\Stmt\ClassConst', 'PHPParser_Node_Stmt_ClassMethod' => 'PhpParser\Node\Stmt\ClassMethod', 'PHPParser_Node_Stmt_Const' => 'PhpParser\Node\Stmt\Const_', 'PHPParser_Node_Stmt_Continue' => 'PhpParser\Node\Stmt\Continue_', 'PHPParser_Node_Stmt_Declare' => 'PhpParser\Node\Stmt\Declare_', 'PHPParser_Node_Stmt_DeclareDeclare' => 'PhpParser\Node\Stmt\DeclareDeclare', 'PHPParser_Node_Stmt_Do' => 'PhpParser\Node\Stmt\Do_', 'PHPParser_Node_Stmt_Echo' => 'PhpParser\Node\Stmt\Echo_', 'PHPParser_Node_Stmt_Else' => 'PhpParser\Node\Stmt\Else_', 'PHPParser_Node_Stmt_ElseIf' => 'PhpParser\Node\Stmt\ElseIf_', 'PHPParser_Node_Stmt_For' => 'PhpParser\Node\Stmt\For_', 'PHPParser_Node_Stmt_Foreach' => 'PhpParser\Node\Stmt\Foreach_', 'PHPParser_Node_Stmt_Function' => 'PhpParser\Node\Stmt\Function_', 'PHPParser_Node_Stmt_Global' => 'PhpParser\Node\Stmt\Global_', 'PHPParser_Node_Stmt_Goto' => 'PhpParser\Node\Stmt\Goto_', 'PHPParser_Node_Stmt_HaltCompiler' => 'PhpParser\Node\Stmt\HaltCompiler', 'PHPParser_Node_Stmt_If' => 'PhpParser\Node\Stmt\If_', 'PHPParser_Node_Stmt_InlineHTML' => 'PhpParser\Node\Stmt\InlineHTML', 'PHPParser_Node_Stmt_Interface' => 'PhpParser\Node\Stmt\Interface_', 'PHPParser_Node_Stmt_Label' => 'PhpParser\Node\Stmt\Label', 'PHPParser_Node_Stmt_Namespace' => 'PhpParser\Node\Stmt\Namespace_', 'PHPParser_Node_Stmt_Property' => 'PhpParser\Node\Stmt\Property', 'PHPParser_Node_Stmt_PropertyProperty' => 'PhpParser\Node\Stmt\PropertyProperty', 'PHPParser_Node_Stmt_Return' => 'PhpParser\Node\Stmt\Return_', 'PHPParser_Node_Stmt_Static' => 'PhpParser\Node\Stmt\Static_', 'PHPParser_Node_Stmt_StaticVar' => 'PhpParser\Node\Stmt\StaticVar', 'PHPParser_Node_Stmt_Switch' => 'PhpParser\Node\Stmt\Switch_', 'PHPParser_Node_Stmt_Throw' => 'PhpParser\Node\Stmt\Throw_', 'PHPParser_Node_Stmt_Trait' => 'PhpParser\Node\Stmt\Trait_', 'PHPParser_Node_Stmt_TraitUse' => 'PhpParser\Node\Stmt\TraitUse', 'PHPParser_Node_Stmt_TraitUseAdaptation' => 'PhpParser\Node\Stmt\TraitUseAdaptation', 'PHPParser_Node_Stmt_TraitUseAdaptation_Alias' => 'PhpParser\Node\Stmt\TraitUseAdaptation\Alias', 'PHPParser_Node_Stmt_TraitUseAdaptation_Precedence' => 'PhpParser\Node\Stmt\TraitUseAdaptation\Precedence', 'PHPParser_Node_Stmt_TryCatch' => 'PhpParser\Node\Stmt\TryCatch', 'PHPParser_Node_Stmt_Unset' => 'PhpParser\Node\Stmt\Unset_', 'PHPParser_Node_Stmt_UseUse' => 'PhpParser\Node\Stmt\UseUse', 'PHPParser_Node_Stmt_Use' => 'PhpParser\Node\Stmt\Use_', 'PHPParser_Node_Stmt_While' => 'PhpParser\Node\Stmt\While_', 'PHPParser_Node_Expr_AssignBitwiseAnd' => 'PhpParser\Node\Expr\AssignOp\BitwiseAnd', 'PHPParser_Node_Expr_AssignBitwiseOr' => 'PhpParser\Node\Expr\AssignOp\BitwiseOr', 'PHPParser_Node_Expr_AssignBitwiseXor' => 'PhpParser\Node\Expr\AssignOp\BitwiseXor', 'PHPParser_Node_Expr_AssignConcat' => 'PhpParser\Node\Expr\AssignOp\Concat', 'PHPParser_Node_Expr_AssignDiv' => 'PhpParser\Node\Expr\AssignOp\Div', 'PHPParser_Node_Expr_AssignMinus' => 'PhpParser\Node\Expr\AssignOp\Minus', 'PHPParser_Node_Expr_AssignMod' => 'PhpParser\Node\Expr\AssignOp\Mod', 'PHPParser_Node_Expr_AssignMul' => 'PhpParser\Node\Expr\AssignOp\Mul', 'PHPParser_Node_Expr_AssignPlus' => 'PhpParser\Node\Expr\AssignOp\Plus', 'PHPParser_Node_Expr_AssignShiftLeft' => 'PhpParser\Node\Expr\AssignOp\ShiftLeft', 'PHPParser_Node_Expr_AssignShiftRight' => 'PhpParser\Node\Expr\AssignOp\ShiftRight', 'PHPParser_Node_Expr_Cast' => 'PhpParser\Node\Expr\Cast', 'PHPParser_Node_Expr_Cast_Array' => 'PhpParser\Node\Expr\Cast\Array_', 'PHPParser_Node_Expr_Cast_Bool' => 'PhpParser\Node\Expr\Cast\Bool_', 'PHPParser_Node_Expr_Cast_Double' => 'PhpParser\Node\Expr\Cast\Double', 'PHPParser_Node_Expr_Cast_Int' => 'PhpParser\Node\Expr\Cast\Int_', 'PHPParser_Node_Expr_Cast_Object' => 'PhpParser\Node\Expr\Cast\Object_', 'PHPParser_Node_Expr_Cast_String' => 'PhpParser\Node\Expr\Cast\String_', 'PHPParser_Node_Expr_Cast_Unset' => 'PhpParser\Node\Expr\Cast\Unset_', 'PHPParser_Node_Expr_BitwiseAnd' => 'PhpParser\Node\Expr\BinaryOp\BitwiseAnd', 'PHPParser_Node_Expr_BitwiseOr' => 'PhpParser\Node\Expr\BinaryOp\BitwiseOr', 'PHPParser_Node_Expr_BitwiseXor' => 'PhpParser\Node\Expr\BinaryOp\BitwiseXor', 'PHPParser_Node_Expr_BooleanAnd' => 'PhpParser\Node\Expr\BinaryOp\BooleanAnd', 'PHPParser_Node_Expr_BooleanOr' => 'PhpParser\Node\Expr\BinaryOp\BooleanOr', 'PHPParser_Node_Expr_Concat' => 'PhpParser\Node\Expr\BinaryOp\Concat', 'PHPParser_Node_Expr_Div' => 'PhpParser\Node\Expr\BinaryOp\Div', 'PHPParser_Node_Expr_Equal' => 'PhpParser\Node\Expr\BinaryOp\Equal', 'PHPParser_Node_Expr_Greater' => 'PhpParser\Node\Expr\BinaryOp\Greater', 'PHPParser_Node_Expr_GreaterOrEqual' => 'PhpParser\Node\Expr\BinaryOp\GreaterOrEqual', 'PHPParser_Node_Expr_Identical' => 'PhpParser\Node\Expr\BinaryOp\Identical', 'PHPParser_Node_Expr_LogicalAnd' => 'PhpParser\Node\Expr\BinaryOp\LogicalAnd', 'PHPParser_Node_Expr_LogicalOr' => 'PhpParser\Node\Expr\BinaryOp\LogicalOr', 'PHPParser_Node_Expr_LogicalXor' => 'PhpParser\Node\Expr\BinaryOp\LogicalXor', 'PHPParser_Node_Expr_Minus' => 'PhpParser\Node\Expr\BinaryOp\Minus', 'PHPParser_Node_Expr_Mod' => 'PhpParser\Node\Expr\BinaryOp\Mod', 'PHPParser_Node_Expr_Mul' => 'PhpParser\Node\Expr\BinaryOp\Mul', 'PHPParser_Node_Expr_NotEqual' => 'PhpParser\Node\Expr\BinaryOp\NotEqual', 'PHPParser_Node_Expr_NotIdentical' => 'PhpParser\Node\Expr\BinaryOp\NotIdentical', 'PHPParser_Node_Expr_Plus' => 'PhpParser\Node\Expr\BinaryOp\Plus', 'PHPParser_Node_Expr_ShiftLeft' => 'PhpParser\Node\Expr\BinaryOp\ShiftLeft', 'PHPParser_Node_Expr_ShiftRight' => 'PhpParser\Node\Expr\BinaryOp\ShiftRight', 'PHPParser_Node_Expr_Smaller' => 'PhpParser\Node\Expr\BinaryOp\Smaller', 'PHPParser_Node_Expr_SmallerOrEqual' => 'PhpParser\Node\Expr\BinaryOp\SmallerOrEqual', 'PHPParser_Node_Expr_Array' => 'PhpParser\Node\Expr\Array_', 'PHPParser_Node_Expr_ArrayDimFetch' => 'PhpParser\Node\Expr\ArrayDimFetch', 'PHPParser_Node_Expr_ArrayItem' => 'PhpParser\Node\Expr\ArrayItem', 'PHPParser_Node_Expr_Assign' => 'PhpParser\Node\Expr\Assign', 'PHPParser_Node_Expr_AssignRef' => 'PhpParser\Node\Expr\AssignRef', 'PHPParser_Node_Expr_BitwiseNot' => 'PhpParser\Node\Expr\BitwiseNot', 'PHPParser_Node_Expr_BooleanNot' => 'PhpParser\Node\Expr\BooleanNot', 'PHPParser_Node_Expr_ClassConstFetch' => 'PhpParser\Node\Expr\ClassConstFetch', 'PHPParser_Node_Expr_Clone' => 'PhpParser\Node\Expr\Clone_', 'PHPParser_Node_Expr_Closure' => 'PhpParser\Node\Expr\Closure', 'PHPParser_Node_Expr_ClosureUse' => 'PhpParser\Node\Expr\ClosureUse', 'PHPParser_Node_Expr_ConstFetch' => 'PhpParser\Node\Expr\ConstFetch', 'PHPParser_Node_Expr_Empty' => 'PhpParser\Node\Expr\Empty_', 'PHPParser_Node_Expr_ErrorSuppress' => 'PhpParser\Node\Expr\ErrorSuppress', 'PHPParser_Node_Expr_Eval' => 'PhpParser\Node\Expr\Eval_', 'PHPParser_Node_Expr_Exit' => 'PhpParser\Node\Expr\Exit_', 'PHPParser_Node_Expr_FuncCall' => 'PhpParser\Node\Expr\FuncCall', 'PHPParser_Node_Expr_Include' => 'PhpParser\Node\Expr\Include_', 'PHPParser_Node_Expr_Instanceof' => 'PhpParser\Node\Expr\Instanceof_', 'PHPParser_Node_Expr_Isset' => 'PhpParser\Node\Expr\Isset_', 'PHPParser_Node_Expr_List' => 'PhpParser\Node\Expr\List_', 'PHPParser_Node_Expr_MethodCall' => 'PhpParser\Node\Expr\MethodCall', 'PHPParser_Node_Expr_New' => 'PhpParser\Node\Expr\New_', 'PHPParser_Node_Expr_PostDec' => 'PhpParser\Node\Expr\PostDec', 'PHPParser_Node_Expr_PostInc' => 'PhpParser\Node\Expr\PostInc', 'PHPParser_Node_Expr_PreDec' => 'PhpParser\Node\Expr\PreDec', 'PHPParser_Node_Expr_PreInc' => 'PhpParser\Node\Expr\PreInc', 'PHPParser_Node_Expr_Print' => 'PhpParser\Node\Expr\Print_', 'PHPParser_Node_Expr_PropertyFetch' => 'PhpParser\Node\Expr\PropertyFetch', 'PHPParser_Node_Expr_ShellExec' => 'PhpParser\Node\Expr\ShellExec', 'PHPParser_Node_Expr_StaticCall' => 'PhpParser\Node\Expr\StaticCall', 'PHPParser_Node_Expr_StaticPropertyFetch' => 'PhpParser\Node\Expr\StaticPropertyFetch', 'PHPParser_Node_Expr_Ternary' => 'PhpParser\Node\Expr\Ternary', 'PHPParser_Node_Expr_UnaryMinus' => 'PhpParser\Node\Expr\UnaryMinus', 'PHPParser_Node_Expr_UnaryPlus' => 'PhpParser\Node\Expr\UnaryPlus', 'PHPParser_Node_Expr_Variable' => 'PhpParser\Node\Expr\Variable', 'PHPParser_Node_Expr_Yield' => 'PhpParser\Node\Expr\Yield_', 'PHPParser_Node_Scalar_ClassConst' => 'PhpParser\Node\Scalar\MagicConst\Class_', 'PHPParser_Node_Scalar_DirConst' => 'PhpParser\Node\Scalar\MagicConst\Dir', 'PHPParser_Node_Scalar_FileConst' => 'PhpParser\Node\Scalar\MagicConst\File', 'PHPParser_Node_Scalar_FuncConst' => 'PhpParser\Node\Scalar\MagicConst\Function_', 'PHPParser_Node_Scalar_LineConst' => 'PhpParser\Node\Scalar\MagicConst\Line', 'PHPParser_Node_Scalar_MethodConst' => 'PhpParser\Node\Scalar\MagicConst\Method', 'PHPParser_Node_Scalar_NSConst' => 'PhpParser\Node\Scalar\MagicConst\Namespace_', 'PHPParser_Node_Scalar_TraitConst' => 'PhpParser\Node\Scalar\MagicConst\Trait_', 'PHPParser_Node_Scalar_DNumber' => 'PhpParser\Node\Scalar\DNumber', 'PHPParser_Node_Scalar_Encapsed' => 'PhpParser\Node\Scalar\Encapsed', 'PHPParser_Node_Scalar_LNumber' => 'PhpParser\Node\Scalar\LNumber', 'PHPParser_Node_Scalar_String' => 'PhpParser\Node\Scalar\String_', ); } class_alias('PhpParser\Autoloader', 'PHPParser_Autoloader'); text = $text; $this->line = $line; } /** * Gets the comment text. * * @return string The comment text (including comment delimiters like /*) */ public function getText() { return $this->text; } /** * Sets the comment text. * * @param string $text The comment text (including comment delimiters like /*) */ public function setText($text) { $this->text = $text; } /** * Gets the line number the comment started on. * * @return int Line number */ public function getLine() { return $this->line; } /** * Sets the line number the comment started on. * * @param int $line Line number */ public function setLine($line) { $this->line = $line; } /** * Gets the comment text. * * @return string The comment text (including comment delimiters like /*) */ public function __toString() { return $this->text; } /** * Gets the reformatted comment text. * * "Reformatted" here means that we try to clean up the whitespace at the * starts of the lines. This is necessary because we receive the comments * without trailing whitespace on the first line, but with trailing whitespace * on all subsequent lines. * * @return mixed|string */ public function getReformattedText() { $text = trim($this->text); if (false === strpos($text, "\n")) { // Single line comments don't need further processing return $text; } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) { // Multi line comment of the type // // /* // * Some text. // * Some more text. // */ // // is handled by replacing the whitespace sequences before the * by a single space return preg_replace('(^\s+\*)m', ' *', $this->text); } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) { // Multi line comment of the type // // /* // Some text. // Some more text. // */ // // is handled by removing the whitespace sequence on the line before the closing // */ on all lines. So if the last line is " */", then " " is removed at the // start of all lines. return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text); } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) { // Multi line comment of the type // // /* Some text. // Some more text. // Even more text. */ // // is handled by taking the length of the "/* " segment and leaving only that // many space characters before the lines. Thus in the above example only three // space characters are left at the start of every line. return preg_replace('(^\s*(?= {' . strlen($matches[0]) . '}(?!\s)))m', '', $text); } // No idea how to format this comment, so simply return as is return $text; } }reader = new XMLReader; } public function unserialize($string) { $this->reader->XML($string); $this->reader->read(); if ('AST' !== $this->reader->name) { throw new DomainException('AST root element not found'); } return $this->read($this->reader->depth); } protected function read($depthLimit, $throw = true, &$nodeFound = null) { $nodeFound = true; while ($this->reader->read() && $depthLimit < $this->reader->depth) { if (XMLReader::ELEMENT !== $this->reader->nodeType) { continue; } if ('node' === $this->reader->prefix) { return $this->readNode(); } elseif ('scalar' === $this->reader->prefix) { return $this->readScalar(); } elseif ('comment' === $this->reader->name) { return $this->readComment(); } else { throw new DomainException(sprintf('Unexpected node of type "%s"', $this->reader->name)); } } $nodeFound = false; if ($throw) { throw new DomainException('Expected node or scalar'); } } protected function readNode() { $className = $this->getClassNameFromType($this->reader->localName); // create the node without calling it's constructor $node = unserialize( sprintf( "O:%d:\"%s\":1:{s:13:\"\0*\0attributes\";a:0:{}}", strlen($className), $className ) ); $depthLimit = $this->reader->depth; while ($this->reader->read() && $depthLimit < $this->reader->depth) { if (XMLReader::ELEMENT !== $this->reader->nodeType) { continue; } $type = $this->reader->prefix; if ('subNode' !== $type && 'attribute' !== $type) { throw new DomainException( sprintf('Expected sub node or attribute, got node of type "%s"', $this->reader->name) ); } $name = $this->reader->localName; $value = $this->read($this->reader->depth); if ('subNode' === $type) { $node->$name = $value; } else { $node->setAttribute($name, $value); } } return $node; } protected function readScalar() { switch ($name = $this->reader->localName) { case 'array': $depth = $this->reader->depth; $array = array(); while (true) { $node = $this->read($depth, false, $nodeFound); if (!$nodeFound) { break; } $array[] = $node; } return $array; case 'string': return $this->reader->readString(); case 'int': return $this->parseInt($this->reader->readString()); case 'float': $text = $this->reader->readString(); if (false === $float = filter_var($text, FILTER_VALIDATE_FLOAT)) { throw new DomainException(sprintf('"%s" is not a valid float', $text)); } return $float; case 'true': case 'false': case 'null': if (!$this->reader->isEmptyElement) { throw new DomainException(sprintf('"%s" scalar must be empty', $name)); } return constant($name); default: throw new DomainException(sprintf('Unknown scalar type "%s"', $name)); } } private function parseInt($text) { if (false === $int = filter_var($text, FILTER_VALIDATE_INT)) { throw new DomainException(sprintf('"%s" is not a valid integer', $text)); } return $int; } protected function readComment() { $className = $this->reader->getAttribute('isDocComment') === 'true' ? 'PhpParser\Comment\Doc' : 'PhpParser\Comment' ; return new $className( $this->reader->readString(), $this->parseInt($this->reader->getAttribute('line')) ); } protected function getClassNameFromType($type) { $className = 'PhpParser\\Node\\' . strtr($type, '_', '\\'); if (!class_exists($className)) { $className .= '_'; } if (!class_exists($className)) { throw new DomainException(sprintf('Unknown node type "%s"', $type)); } return $className; } } array( 'finally' => Parser::T_FINALLY, 'yield' => Parser::T_YIELD, ), self::PHP_5_4 => array( 'callable' => Parser::T_CALLABLE, 'insteadof' => Parser::T_INSTEADOF, 'trait' => Parser::T_TRAIT, '__trait__' => Parser::T_TRAIT_C, ), ); $this->newKeywords = array(); foreach ($newKeywordsPerVersion as $version => $newKeywords) { if (version_compare(PHP_VERSION, $version, '>=')) { break; } $this->newKeywords += $newKeywords; } if (version_compare(PHP_VERSION, self::PHP_7_0, '>=')) { return; } $this->tokenMap[self::T_COALESCE] = Parser::T_COALESCE; $this->tokenMap[self::T_SPACESHIP] = Parser::T_SPACESHIP; $this->tokenMap[self::T_YIELD_FROM] = Parser::T_YIELD_FROM; if (version_compare(PHP_VERSION, self::PHP_5_6, '>=')) { return; } $this->tokenMap[self::T_ELLIPSIS] = Parser::T_ELLIPSIS; $this->tokenMap[self::T_POW] = Parser::T_POW; $this->tokenMap[self::T_POW_EQUAL] = Parser::T_POW_EQUAL; } public function startLexing($code) { $this->inObjectAccess = false; $preprocessedCode = $this->preprocessCode($code); parent::startLexing($preprocessedCode); if ($preprocessedCode !== $code) { $this->postprocessTokens(); } // Set code property back to the original code, so __halt_compiler() // handling and (start|end)FilePos attributes use the correct offsets $this->code = $code; } /* * Replaces new features in the code by ~__EMU__{NAME}__{DATA}__~ sequences. * ~LABEL~ is never valid PHP code, that's why we can (to some degree) safely * use it here. * Later when preprocessing the tokens these sequences will either be replaced * by real tokens or replaced with their original content (e.g. if they occurred * inside a string, i.e. a place where they don't have a special meaning). */ protected function preprocessCode($code) { if (version_compare(PHP_VERSION, self::PHP_7_0, '>=')) { return $code; } $code = str_replace('??', '~__EMU__COALESCE__~', $code); $code = str_replace('<=>', '~__EMU__SPACESHIP__~', $code); $code = preg_replace_callback('(yield[ \n\r\t]+from)', function($matches) { // Encoding $0 in order to preserve exact whitespace return '~__EMU__YIELDFROM__' . bin2hex($matches[0]) . '__~'; }, $code); if (version_compare(PHP_VERSION, self::PHP_5_6, '>=')) { return $code; } $code = str_replace('...', '~__EMU__ELLIPSIS__~', $code); $code = preg_replace('((?=')) { return $code; } // binary notation (0b010101101001...) return preg_replace('(\b0b[01]+\b)', '~__EMU__BINARY__$0__~', $code); } /* * Replaces the ~__EMU__...~ sequences with real tokens or their original * value. */ protected function postprocessTokens() { // we need to manually iterate and manage a count because we'll change // the tokens array on the way for ($i = 0, $c = count($this->tokens); $i < $c; ++$i) { // first check that the following tokens are of form ~LABEL~, // then match the __EMU__... sequence. if ('~' === $this->tokens[$i] && isset($this->tokens[$i + 2]) && '~' === $this->tokens[$i + 2] && T_STRING === $this->tokens[$i + 1][0] && preg_match('(^__EMU__([A-Z]++)__(?:([A-Za-z0-9]++)__)?$)', $this->tokens[$i + 1][1], $matches) ) { if ('BINARY' === $matches[1]) { // the binary number can either be an integer or a double, so return a LNUMBER // or DNUMBER respectively $isInt = is_int(bindec($matches[2])); $replace = array( array($isInt ? T_LNUMBER : T_DNUMBER, $matches[2], $this->tokens[$i + 1][2]) ); } else if ('ELLIPSIS' === $matches[1]) { $replace = array( array(self::T_ELLIPSIS, '...', $this->tokens[$i + 1][2]) ); } else if ('POW' === $matches[1]) { $replace = array( array(self::T_POW, '**', $this->tokens[$i + 1][2]) ); } else if ('POWEQUAL' === $matches[1]) { $replace = array( array(self::T_POW_EQUAL, '**=', $this->tokens[$i + 1][2]) ); } else if ('COALESCE' === $matches[1]) { $replace = array( array(self::T_COALESCE, '??', $this->tokens[$i + 1][2]) ); } else if ('SPACESHIP' === $matches[1]) { $replace = array( array(self::T_SPACESHIP, '<=>', $this->tokens[$i + 1][2]), ); } else if ('YIELDFROM' === $matches[1]) { $content = $this->hex2bin($matches[2]); $replace = array( array(self::T_YIELD_FROM, $content, $this->tokens[$i + 1][2] - substr_count($content, "\n")) ); } else { throw new \RuntimeException('Invalid __EMU__ sequence'); } array_splice($this->tokens, $i, 3, $replace); $c -= 3 - count($replace); // for multichar tokens (e.g. strings) replace any ~__EMU__...~ sequences // in their content with the original character sequence } elseif (is_array($this->tokens[$i]) && 0 !== strpos($this->tokens[$i][1], '__EMU__') ) { $this->tokens[$i][1] = preg_replace_callback( '(~__EMU__([A-Z]++)__(?:([A-Za-z0-9]++)__)?~)', array($this, 'restoreContentCallback'), $this->tokens[$i][1] ); } } } /* * This method is a callback for restoring EMU sequences in * multichar tokens (like strings) to their original value. */ public function restoreContentCallback(array $matches) { if ('BINARY' === $matches[1]) { return $matches[2]; } else if ('ELLIPSIS' === $matches[1]) { return '...'; } else if ('POW' === $matches[1]) { return '**'; } else if ('POWEQUAL' === $matches[1]) { return '**='; } else if ('COALESCE' === $matches[1]) { return '??'; } else if ('SPACESHIP' === $matches[1]) { return '<=>'; } else if ('YIELDFROM' === $matches[1]) { return $this->hex2bin($matches[2]); } else { return $matches[0]; } } private function hex2bin($str) { // TODO Drop when removing support for PHP 5.3 return pack('H*', $str); } public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) { $token = parent::getNextToken($value, $startAttributes, $endAttributes); // replace new keywords by their respective tokens. This is not done // if we currently are in an object access (e.g. in $obj->namespace // "namespace" stays a T_STRING tokens and isn't converted to T_NAMESPACE) if (Parser::T_STRING === $token && !$this->inObjectAccess) { if (isset($this->newKeywords[strtolower($value)])) { return $this->newKeywords[strtolower($value)]; } } else { // keep track of whether we currently are in an object access (after ->) $this->inObjectAccess = Parser::T_OBJECT_OPERATOR === $token; } return $token; } } writer = new XMLWriter; $this->writer->openMemory(); $this->writer->setIndent(true); } public function serialize(array $nodes) { $this->writer->flush(); $this->writer->startDocument('1.0', 'UTF-8'); $this->writer->startElement('AST'); $this->writer->writeAttribute('xmlns:node', 'http://nikic.github.com/PHPParser/XML/node'); $this->writer->writeAttribute('xmlns:subNode', 'http://nikic.github.com/PHPParser/XML/subNode'); $this->writer->writeAttribute('xmlns:attribute', 'http://nikic.github.com/PHPParser/XML/attribute'); $this->writer->writeAttribute('xmlns:scalar', 'http://nikic.github.com/PHPParser/XML/scalar'); $this->_serialize($nodes); $this->writer->endElement(); return $this->writer->outputMemory(); } protected function _serialize($node) { if ($node instanceof Node) { $this->writer->startElement('node:' . $node->getType()); foreach ($node->getAttributes() as $name => $value) { $this->writer->startElement('attribute:' . $name); $this->_serialize($value); $this->writer->endElement(); } foreach ($node as $name => $subNode) { $this->writer->startElement('subNode:' . $name); $this->_serialize($subNode); $this->writer->endElement(); } $this->writer->endElement(); } elseif ($node instanceof Comment) { $this->writer->startElement('comment'); $this->writer->writeAttribute('isDocComment', $node instanceof Comment\Doc ? 'true' : 'false'); $this->writer->writeAttribute('line', (string) $node->getLine()); $this->writer->text($node->getText()); $this->writer->endElement(); } elseif (is_array($node)) { $this->writer->startElement('scalar:array'); foreach ($node as $subNode) { $this->_serialize($subNode); } $this->writer->endElement(); } elseif (is_string($node)) { $this->writer->writeElement('scalar:string', $node); } elseif (is_int($node)) { $this->writer->writeElement('scalar:int', (string) $node); } elseif (is_float($node)) { // TODO Higher precision conversion? $this->writer->writeElement('scalar:float', (string) $node); } elseif (true === $node) { $this->writer->writeElement('scalar:true'); } elseif (false === $node) { $this->writer->writeElement('scalar:false'); } elseif (null === $node) { $this->writer->writeElement('scalar:null'); } else { throw new \InvalidArgumentException('Unexpected node type'); } } } getType() . '('; foreach ($node->getSubNodeNames() as $key) { $r .= "\n " . $key . ': '; $value = $node->$key; if (null === $value) { $r .= 'null'; } elseif (false === $value) { $r .= 'false'; } elseif (true === $value) { $r .= 'true'; } elseif (is_scalar($value)) { $r .= $value; } else { $r .= str_replace("\n", "\n ", $this->dump($value)); } } } elseif (is_array($node)) { $r = 'array('; foreach ($node as $key => $value) { $r .= "\n " . $key . ': '; if (null === $value) { $r .= 'null'; } elseif (false === $value) { $r .= 'false'; } elseif (true === $value) { $r .= 'true'; } elseif (is_scalar($value)) { $r .= $value; } else { $r .= str_replace("\n", "\n ", $this->dump($value)); } } } else { throw new \InvalidArgumentException('Can only dump nodes and arrays.'); } return $r . "\n)"; } } attributes = $attributes; if (null !== $subNodes) { foreach ($subNodes as $name => $value) { $this->$name = $value; } $this->subNodeNames = array_keys($subNodes); } } /** * Gets the type of the node. * * @return string Type of the node */ public function getType() { return strtr(substr(rtrim(get_class($this), '_'), 15), '\\', '_'); } /** * Gets the names of the sub nodes. * * @return array Names of sub nodes */ public function getSubNodeNames() { return $this->subNodeNames; } /** * Gets line the node started in. * * @return int Line */ public function getLine() { return $this->getAttribute('startLine', -1); } /** * Sets line the node started in. * * @param int $line Line */ public function setLine($line) { $this->setAttribute('startLine', (int) $line); } /** * Gets the doc comment of the node. * * The doc comment has to be the last comment associated with the node. * * @return null|Comment\Doc Doc comment object or null */ public function getDocComment() { $comments = $this->getAttribute('comments'); if (!$comments) { return null; } $lastComment = $comments[count($comments) - 1]; if (!$lastComment instanceof Comment\Doc) { return null; } return $lastComment; } /** * {@inheritDoc} */ public function setAttribute($key, $value) { $this->attributes[$key] = $value; } /** * {@inheritDoc} */ public function hasAttribute($key) { return array_key_exists($key, $this->attributes); } /** * {@inheritDoc} */ public function &getAttribute($key, $default = null) { if (!array_key_exists($key, $this->attributes)) { return $default; } else { return $this->attributes[$key]; } } /** * {@inheritDoc} */ public function getAttributes() { return $this->attributes; } } lexer = $lexer; $this->errors = array(); $this->throwOnError = isset($options['throwOnError']) ? $options['throwOnError'] : true; } /** * Get array of errors that occurred during the last parse. * * This method may only return multiple errors if the 'throwOnError' option is disabled. * * @return Error[] */ public function getErrors() { return $this->errors; } /** * Parses PHP code into a node tree. * * @param string $code The source code to parse * * @return Node[]|null Array of statements (or null if the 'throwOnError' option is disabled and the parser was * unable to recover from an error). */ public function parse($code) { $this->lexer->startLexing($code); $this->errors = array(); // We start off with no lookahead-token $symbol = self::SYMBOL_NONE; // The attributes for a node are taken from the first and last token of the node. // From the first token only the startAttributes are taken and from the last only // the endAttributes. Both are merged using the array union operator (+). $startAttributes = '*POISON'; $endAttributes = '*POISON'; $this->endAttributes = $endAttributes; // In order to figure out the attributes for the starting token, we have to keep // them in a stack $this->startAttributeStack = array(); // Start off in the initial state and keep a stack of previous states $state = 0; $stateStack = array($state); // Semantic value stack (contains values of tokens and semantic action results) $this->semStack = array(); // Current position in the stack(s) $this->stackPos = 0; $errorState = 0; for (;;) { //$this->traceNewState($state, $symbol); if ($this->actionBase[$state] == 0) { $rule = $this->actionDefault[$state]; } else { if ($symbol === self::SYMBOL_NONE) { // Fetch the next token id from the lexer and fetch additional info by-ref. // The end attributes are fetched into a temporary variable and only set once the token is really // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is // reduced after a token was read but not yet shifted. $tokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $endAttributes); // map the lexer token id to the internally used symbols $symbol = $tokenId >= 0 && $tokenId < $this->tokenToSymbolMapSize ? $this->tokenToSymbol[$tokenId] : $this->invalidSymbol; if ($symbol === $this->invalidSymbol) { throw new \RangeException(sprintf( 'The lexer returned an invalid token (id=%d, value=%s)', $tokenId, $tokenValue )); } // This is necessary to assign some meaningful attributes to /* empty */ productions. They'll get // the attributes of the next token, even though they don't contain it themselves. $this->startAttributeStack[$this->stackPos+1] = $startAttributes; //$this->traceRead($symbol); } $idx = $this->actionBase[$state] + $symbol; if ((($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $symbol) || ($state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->YYNLSTATES] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $symbol)) && ($action = $this->action[$idx]) != $this->defaultAction) { /* * >= YYNLSTATES: shift and reduce * > 0: shift * = 0: accept * < 0: reduce * = -YYUNEXPECTED: error */ if ($action > 0) { /* shift */ //$this->traceShift($symbol); ++$this->stackPos; $stateStack[$this->stackPos] = $state = $action; $this->semStack[$this->stackPos] = $tokenValue; $this->startAttributeStack[$this->stackPos] = $startAttributes; $this->endAttributes = $endAttributes; $symbol = self::SYMBOL_NONE; if ($errorState) { --$errorState; } if ($action < $this->YYNLSTATES) { continue; } /* $yyn >= YYNLSTATES means shift-and-reduce */ $rule = $action - $this->YYNLSTATES; } else { $rule = -$action; } } else { $rule = $this->actionDefault[$state]; } } for (;;) { if ($rule === 0) { /* accept */ //$this->traceAccept(); return $this->semValue; } elseif ($rule !== $this->unexpectedTokenRule) { /* reduce */ //$this->traceReduce($rule); try { $this->{'reduceRule' . $rule}(); } catch (Error $e) { if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) { $e->setStartLine($startAttributes['startLine']); } $this->errors[] = $e; if ($this->throwOnError) { throw $e; } else { // Currently can't recover from "special" errors return null; } } /* Goto - shift nonterminal */ $this->stackPos -= $this->ruleToLength[$rule]; $nonTerminal = $this->ruleToNonTerminal[$rule]; $idx = $this->gotoBase[$nonTerminal] + $stateStack[$this->stackPos]; if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] == $nonTerminal) { $state = $this->goto[$idx]; } else { $state = $this->gotoDefault[$nonTerminal]; } ++$this->stackPos; $stateStack[$this->stackPos] = $state; $this->semStack[$this->stackPos] = $this->semValue; } else { /* error */ switch ($errorState) { case 0: $msg = $this->getErrorMessage($symbol, $state); $error = new Error($msg, $startAttributes + $endAttributes); $this->errors[] = $error; if ($this->throwOnError) { throw $error; } // Break missing intentionally case 1: case 2: $errorState = 3; // Pop until error-expecting state uncovered while (!( (($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $this->errorSymbol) || ($state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->YYNLSTATES] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $this->errorSymbol) ) || ($action = $this->action[$idx]) == $this->defaultAction) { // Not totally sure about this if ($this->stackPos <= 0) { // Could not recover from error return null; } $state = $stateStack[--$this->stackPos]; //$this->tracePop($state); } //$this->traceShift($this->errorSymbol); $stateStack[++$this->stackPos] = $state = $action; break; case 3: if ($symbol === 0) { // Reached EOF without recovering from error return null; } //$this->traceDiscard($symbol); $symbol = self::SYMBOL_NONE; break 2; } } if ($state < $this->YYNLSTATES) { break; } /* >= YYNLSTATES means shift-and-reduce */ $rule = $state - $this->YYNLSTATES; } } throw new \RuntimeException('Reached end of parser loop'); } protected function getErrorMessage($symbol, $state) { $expectedString = ''; if ($expected = $this->getExpectedTokens($state)) { $expectedString = ', expecting ' . implode(' or ', $expected); } return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString; } protected function getExpectedTokens($state) { $expected = array(); $base = $this->actionBase[$state]; foreach ($this->symbolToName as $symbol => $name) { $idx = $base + $symbol; if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->YYNLSTATES] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol ) { if ($this->action[$idx] != $this->unexpectedTokenRule) { if (count($expected) == 4) { /* Too many expected tokens */ return array(); } $expected[] = $name; } } } return $expected; } /* * Tracing functions used for debugging the parser. */ /* protected function traceNewState($state, $symbol) { echo '% State ' . $state . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n"; } protected function traceRead($symbol) { echo '% Reading ' . $this->symbolToName[$symbol] . "\n"; } protected function traceShift($symbol) { echo '% Shift ' . $this->symbolToName[$symbol] . "\n"; } protected function traceAccept() { echo "% Accepted.\n"; } protected function traceReduce($n) { echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n"; } protected function tracePop($state) { echo '% Recovering, uncovered state ' . $state . "\n"; } protected function traceDiscard($symbol) { echo '% Discard ' . $this->symbolToName[$symbol] . "\n"; } */ /* * Helper functions invoked by semantic actions */ /** * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions. * * @param Node[] $stmts * @return Node[] */ protected function handleNamespaces(array $stmts) { $style = $this->getNamespacingStyle($stmts); if (null === $style) { // not namespaced, nothing to do return $stmts; } elseif ('brace' === $style) { // For braced namespaces we only have to check that there are no invalid statements between the namespaces $afterFirstNamespace = false; foreach ($stmts as $stmt) { if ($stmt instanceof Node\Stmt\Namespace_) { $afterFirstNamespace = true; } elseif (!$stmt instanceof Node\Stmt\HaltCompiler && $afterFirstNamespace) { throw new Error('No code may exist outside of namespace {}', $stmt->getLine()); } } return $stmts; } else { // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts $resultStmts = array(); $targetStmts =& $resultStmts; foreach ($stmts as $stmt) { if ($stmt instanceof Node\Stmt\Namespace_) { $stmt->stmts = array(); $targetStmts =& $stmt->stmts; $resultStmts[] = $stmt; } elseif ($stmt instanceof Node\Stmt\HaltCompiler) { // __halt_compiler() is not moved into the namespace $resultStmts[] = $stmt; } else { $targetStmts[] = $stmt; } } return $resultStmts; } } private function getNamespacingStyle(array $stmts) { $style = null; $hasNotAllowedStmts = false; foreach ($stmts as $stmt) { if ($stmt instanceof Node\Stmt\Namespace_) { $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace'; if (null === $style) { $style = $currentStyle; if ($hasNotAllowedStmts) { throw new Error('Namespace declaration statement has to be the very first statement in the script', $stmt->getLine()); } } elseif ($style !== $currentStyle) { throw new Error('Cannot mix bracketed namespace declarations with unbracketed namespace declarations', $stmt->getLine()); } } elseif (!$stmt instanceof Node\Stmt\Declare_ && !$stmt instanceof Node\Stmt\HaltCompiler) { $hasNotAllowedStmts = true; } } return $style; } } type ? $this->pType($node->type) . ' ' : '') . ($node->byRef ? '&' : '') . ($node->variadic ? '...' : '') . '$' . $node->name . ($node->default ? ' = ' . $this->p($node->default) : ''); } public function pArg(Node\Arg $node) { return ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value); } public function pConst(Node\Const_ $node) { return $node->name . ' = ' . $this->p($node->value); } // Names public function pName(Name $node) { return implode('\\', $node->parts); } public function pName_FullyQualified(Name\FullyQualified $node) { return '\\' . implode('\\', $node->parts); } public function pName_Relative(Name\Relative $node) { return 'namespace\\' . implode('\\', $node->parts); } // Magic Constants public function pScalar_MagicConst_Class(MagicConst\Class_ $node) { return '__CLASS__'; } public function pScalar_MagicConst_Dir(MagicConst\Dir $node) { return '__DIR__'; } public function pScalar_MagicConst_File(MagicConst\File $node) { return '__FILE__'; } public function pScalar_MagicConst_Function(MagicConst\Function_ $node) { return '__FUNCTION__'; } public function pScalar_MagicConst_Line(MagicConst\Line $node) { return '__LINE__'; } public function pScalar_MagicConst_Method(MagicConst\Method $node) { return '__METHOD__'; } public function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node) { return '__NAMESPACE__'; } public function pScalar_MagicConst_Trait(MagicConst\Trait_ $node) { return '__TRAIT__'; } // Scalars public function pScalar_String(Scalar\String_ $node) { return '\'' . $this->pNoIndent(addcslashes($node->value, '\'\\')) . '\''; } public function pScalar_Encapsed(Scalar\Encapsed $node) { return '"' . $this->pEncapsList($node->parts, '"') . '"'; } public function pScalar_LNumber(Scalar\LNumber $node) { return (string) $node->value; } public function pScalar_DNumber(Scalar\DNumber $node) { $stringValue = sprintf('%.16G', $node->value); if ($node->value !== (double) $stringValue) { $stringValue = sprintf('%.17G', $node->value); } // ensure that number is really printed as float return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue; } // Assignments public function pExpr_Assign(Expr\Assign $node) { return $this->pInfixOp('Expr_Assign', $node->var, ' = ', $node->expr); } public function pExpr_AssignRef(Expr\AssignRef $node) { return $this->pInfixOp('Expr_AssignRef', $node->var, ' =& ', $node->expr); } public function pExpr_AssignOp_Plus(AssignOp\Plus $node) { return $this->pInfixOp('Expr_AssignOp_Plus', $node->var, ' += ', $node->expr); } public function pExpr_AssignOp_Minus(AssignOp\Minus $node) { return $this->pInfixOp('Expr_AssignOp_Minus', $node->var, ' -= ', $node->expr); } public function pExpr_AssignOp_Mul(AssignOp\Mul $node) { return $this->pInfixOp('Expr_AssignOp_Mul', $node->var, ' *= ', $node->expr); } public function pExpr_AssignOp_Div(AssignOp\Div $node) { return $this->pInfixOp('Expr_AssignOp_Div', $node->var, ' /= ', $node->expr); } public function pExpr_AssignOp_Concat(AssignOp\Concat $node) { return $this->pInfixOp('Expr_AssignOp_Concat', $node->var, ' .= ', $node->expr); } public function pExpr_AssignOp_Mod(AssignOp\Mod $node) { return $this->pInfixOp('Expr_AssignOp_Mod', $node->var, ' %= ', $node->expr); } public function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) { return $this->pInfixOp('Expr_AssignOp_BitwiseAnd', $node->var, ' &= ', $node->expr); } public function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) { return $this->pInfixOp('Expr_AssignOp_BitwiseOr', $node->var, ' |= ', $node->expr); } public function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) { return $this->pInfixOp('Expr_AssignOp_BitwiseXor', $node->var, ' ^= ', $node->expr); } public function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) { return $this->pInfixOp('Expr_AssignOp_ShiftLeft', $node->var, ' <<= ', $node->expr); } public function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) { return $this->pInfixOp('Expr_AssignOp_ShiftRight', $node->var, ' >>= ', $node->expr); } public function pExpr_AssignOp_Pow(AssignOp\Pow $node) { return $this->pInfixOp('Expr_AssignOp_Pow', $node->var, ' **= ', $node->expr); } // Binary expressions public function pExpr_BinaryOp_Plus(BinaryOp\Plus $node) { return $this->pInfixOp('Expr_BinaryOp_Plus', $node->left, ' + ', $node->right); } public function pExpr_BinaryOp_Minus(BinaryOp\Minus $node) { return $this->pInfixOp('Expr_BinaryOp_Minus', $node->left, ' - ', $node->right); } public function pExpr_BinaryOp_Mul(BinaryOp\Mul $node) { return $this->pInfixOp('Expr_BinaryOp_Mul', $node->left, ' * ', $node->right); } public function pExpr_BinaryOp_Div(BinaryOp\Div $node) { return $this->pInfixOp('Expr_BinaryOp_Div', $node->left, ' / ', $node->right); } public function pExpr_BinaryOp_Concat(BinaryOp\Concat $node) { return $this->pInfixOp('Expr_BinaryOp_Concat', $node->left, ' . ', $node->right); } public function pExpr_BinaryOp_Mod(BinaryOp\Mod $node) { return $this->pInfixOp('Expr_BinaryOp_Mod', $node->left, ' % ', $node->right); } public function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node) { return $this->pInfixOp('Expr_BinaryOp_BooleanAnd', $node->left, ' && ', $node->right); } public function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node) { return $this->pInfixOp('Expr_BinaryOp_BooleanOr', $node->left, ' || ', $node->right); } public function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node) { return $this->pInfixOp('Expr_BinaryOp_BitwiseAnd', $node->left, ' & ', $node->right); } public function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node) { return $this->pInfixOp('Expr_BinaryOp_BitwiseOr', $node->left, ' | ', $node->right); } public function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node) { return $this->pInfixOp('Expr_BinaryOp_BitwiseXor', $node->left, ' ^ ', $node->right); } public function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node) { return $this->pInfixOp('Expr_BinaryOp_ShiftLeft', $node->left, ' << ', $node->right); } public function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node) { return $this->pInfixOp('Expr_BinaryOp_ShiftRight', $node->left, ' >> ', $node->right); } public function pExpr_BinaryOp_Pow(BinaryOp\Pow $node) { return $this->pInfixOp('Expr_BinaryOp_Pow', $node->left, ' ** ', $node->right); } public function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node) { return $this->pInfixOp('Expr_BinaryOp_LogicalAnd', $node->left, ' and ', $node->right); } public function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node) { return $this->pInfixOp('Expr_BinaryOp_LogicalOr', $node->left, ' or ', $node->right); } public function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node) { return $this->pInfixOp('Expr_BinaryOp_LogicalXor', $node->left, ' xor ', $node->right); } public function pExpr_BinaryOp_Equal(BinaryOp\Equal $node) { return $this->pInfixOp('Expr_BinaryOp_Equal', $node->left, ' == ', $node->right); } public function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node) { return $this->pInfixOp('Expr_BinaryOp_NotEqual', $node->left, ' != ', $node->right); } public function pExpr_BinaryOp_Identical(BinaryOp\Identical $node) { return $this->pInfixOp('Expr_BinaryOp_Identical', $node->left, ' === ', $node->right); } public function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node) { return $this->pInfixOp('Expr_BinaryOp_NotIdentical', $node->left, ' !== ', $node->right); } public function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node) { return $this->pInfixOp('Expr_BinaryOp_Spaceship', $node->left, ' <=> ', $node->right); } public function pExpr_BinaryOp_Greater(BinaryOp\Greater $node) { return $this->pInfixOp('Expr_BinaryOp_Greater', $node->left, ' > ', $node->right); } public function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node) { return $this->pInfixOp('Expr_BinaryOp_GreaterOrEqual', $node->left, ' >= ', $node->right); } public function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node) { return $this->pInfixOp('Expr_BinaryOp_Smaller', $node->left, ' < ', $node->right); } public function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node) { return $this->pInfixOp('Expr_BinaryOp_SmallerOrEqual', $node->left, ' <= ', $node->right); } public function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node) { return $this->pInfixOp('Expr_BinaryOp_Coalesce', $node->left, ' ?? ', $node->right); } public function pExpr_Instanceof(Expr\Instanceof_ $node) { return $this->pInfixOp('Expr_Instanceof', $node->expr, ' instanceof ', $node->class); } // Unary expressions public function pExpr_BooleanNot(Expr\BooleanNot $node) { return $this->pPrefixOp('Expr_BooleanNot', '!', $node->expr); } public function pExpr_BitwiseNot(Expr\BitwiseNot $node) { return $this->pPrefixOp('Expr_BitwiseNot', '~', $node->expr); } public function pExpr_UnaryMinus(Expr\UnaryMinus $node) { return $this->pPrefixOp('Expr_UnaryMinus', '-', $node->expr); } public function pExpr_UnaryPlus(Expr\UnaryPlus $node) { return $this->pPrefixOp('Expr_UnaryPlus', '+', $node->expr); } public function pExpr_PreInc(Expr\PreInc $node) { return $this->pPrefixOp('Expr_PreInc', '++', $node->var); } public function pExpr_PreDec(Expr\PreDec $node) { return $this->pPrefixOp('Expr_PreDec', '--', $node->var); } public function pExpr_PostInc(Expr\PostInc $node) { return $this->pPostfixOp('Expr_PostInc', $node->var, '++'); } public function pExpr_PostDec(Expr\PostDec $node) { return $this->pPostfixOp('Expr_PostDec', $node->var, '--'); } public function pExpr_ErrorSuppress(Expr\ErrorSuppress $node) { return $this->pPrefixOp('Expr_ErrorSuppress', '@', $node->expr); } public function pExpr_YieldFrom(Expr\YieldFrom $node) { return $this->pPrefixOp('Expr_YieldFrom', 'yield from ', $node->expr); } public function pExpr_Print(Expr\Print_ $node) { return $this->pPrefixOp('Expr_Print', 'print ', $node->expr); } // Casts public function pExpr_Cast_Int(Cast\Int_ $node) { return $this->pPrefixOp('Expr_Cast_Int', '(int) ', $node->expr); } public function pExpr_Cast_Double(Cast\Double $node) { return $this->pPrefixOp('Expr_Cast_Double', '(double) ', $node->expr); } public function pExpr_Cast_String(Cast\String_ $node) { return $this->pPrefixOp('Expr_Cast_String', '(string) ', $node->expr); } public function pExpr_Cast_Array(Cast\Array_ $node) { return $this->pPrefixOp('Expr_Cast_Array', '(array) ', $node->expr); } public function pExpr_Cast_Object(Cast\Object_ $node) { return $this->pPrefixOp('Expr_Cast_Object', '(object) ', $node->expr); } public function pExpr_Cast_Bool(Cast\Bool_ $node) { return $this->pPrefixOp('Expr_Cast_Bool', '(bool) ', $node->expr); } public function pExpr_Cast_Unset(Cast\Unset_ $node) { return $this->pPrefixOp('Expr_Cast_Unset', '(unset) ', $node->expr); } // Function calls and similar constructs public function pExpr_FuncCall(Expr\FuncCall $node) { return $this->p($node->name) . '(' . $this->pCommaSeparated($node->args) . ')'; } public function pExpr_MethodCall(Expr\MethodCall $node) { return $this->pVarOrNewExpr($node->var) . '->' . $this->pObjectProperty($node->name) . '(' . $this->pCommaSeparated($node->args) . ')'; } public function pExpr_StaticCall(Expr\StaticCall $node) { return $this->p($node->class) . '::' . ($node->name instanceof Expr ? ($node->name instanceof Expr\Variable || $node->name instanceof Expr\ArrayDimFetch ? $this->p($node->name) : '{' . $this->p($node->name) . '}') : $node->name) . '(' . $this->pCommaSeparated($node->args) . ')'; } public function pExpr_Empty(Expr\Empty_ $node) { return 'empty(' . $this->p($node->expr) . ')'; } public function pExpr_Isset(Expr\Isset_ $node) { return 'isset(' . $this->pCommaSeparated($node->vars) . ')'; } public function pExpr_Eval(Expr\Eval_ $node) { return 'eval(' . $this->p($node->expr) . ')'; } public function pExpr_Include(Expr\Include_ $node) { static $map = array( Expr\Include_::TYPE_INCLUDE => 'include', Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once', Expr\Include_::TYPE_REQUIRE => 'require', Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once', ); return $map[$node->type] . ' ' . $this->p($node->expr); } public function pExpr_List(Expr\List_ $node) { $pList = array(); foreach ($node->vars as $var) { if (null === $var) { $pList[] = ''; } else { $pList[] = $this->p($var); } } return 'list(' . implode(', ', $pList) . ')'; } // Other public function pExpr_Variable(Expr\Variable $node) { if ($node->name instanceof Expr) { return '${' . $this->p($node->name) . '}'; } else { return '$' . $node->name; } } public function pExpr_Array(Expr\Array_ $node) { return 'array(' . $this->pCommaSeparated($node->items) . ')'; } public function pExpr_ArrayItem(Expr\ArrayItem $node) { return (null !== $node->key ? $this->p($node->key) . ' => ' : '') . ($node->byRef ? '&' : '') . $this->p($node->value); } public function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node) { return $this->pVarOrNewExpr($node->var) . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']'; } public function pExpr_ConstFetch(Expr\ConstFetch $node) { return $this->p($node->name); } public function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) { return $this->p($node->class) . '::' . $node->name; } public function pExpr_PropertyFetch(Expr\PropertyFetch $node) { return $this->pVarOrNewExpr($node->var) . '->' . $this->pObjectProperty($node->name); } public function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) { return $this->p($node->class) . '::$' . $this->pObjectProperty($node->name); } public function pExpr_ShellExec(Expr\ShellExec $node) { return '`' . $this->pEncapsList($node->parts, '`') . '`'; } public function pExpr_Closure(Expr\Closure $node) { return ($node->static ? 'static ' : '') . 'function ' . ($node->byRef ? '&' : '') . '(' . $this->pCommaSeparated($node->params) . ')' . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')': '') . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '') . ' {' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pExpr_ClosureUse(Expr\ClosureUse $node) { return ($node->byRef ? '&' : '') . '$' . $node->var; } public function pExpr_New(Expr\New_ $node) { if ($node->class instanceof Stmt\Class_) { $args = $node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : ''; return 'new ' . $this->pClassCommon($node->class, $args); } return 'new ' . $this->p($node->class) . '(' . $this->pCommaSeparated($node->args) . ')'; } public function pExpr_Clone(Expr\Clone_ $node) { return 'clone ' . $this->p($node->expr); } public function pExpr_Ternary(Expr\Ternary $node) { // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator. // this is okay because the part between ? and : never needs parentheses. return $this->pInfixOp('Expr_Ternary', $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else ); } public function pExpr_Exit(Expr\Exit_ $node) { return 'die' . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : ''); } public function pExpr_Yield(Expr\Yield_ $node) { if ($node->value === null) { return 'yield'; } else { // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary return '(yield ' . ($node->key !== null ? $this->p($node->key) . ' => ' : '') . $this->p($node->value) . ')'; } } // Declarations public function pStmt_Namespace(Stmt\Namespace_ $node) { if ($this->canUseSemicolonNamespaces) { return 'namespace ' . $this->p($node->name) . ';' . "\n" . $this->pStmts($node->stmts, false); } else { return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '') . ' {' . $this->pStmts($node->stmts) . "\n" . '}'; } } public function pStmt_Use(Stmt\Use_ $node) { return 'use ' . ($node->type === Stmt\Use_::TYPE_FUNCTION ? 'function ' : '') . ($node->type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : '') . $this->pCommaSeparated($node->uses) . ';'; } public function pStmt_UseUse(Stmt\UseUse $node) { return $this->p($node->name) . ($node->name->getLast() !== $node->alias ? ' as ' . $node->alias : ''); } public function pStmt_Interface(Stmt\Interface_ $node) { return 'interface ' . $node->name . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '') . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pStmt_Class(Stmt\Class_ $node) { return $this->pClassCommon($node, ' ' . $node->name); } public function pStmt_Trait(Stmt\Trait_ $node) { return 'trait ' . $node->name . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pStmt_TraitUse(Stmt\TraitUse $node) { return 'use ' . $this->pCommaSeparated($node->traits) . (empty($node->adaptations) ? ';' : ' {' . $this->pStmts($node->adaptations) . "\n" . '}'); } public function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node) { return $this->p($node->trait) . '::' . $node->method . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';'; } public function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node) { return (null !== $node->trait ? $this->p($node->trait) . '::' : '') . $node->method . ' as' . (null !== $node->newModifier ? ' ' . rtrim($this->pModifiers($node->newModifier), ' ') : '') . (null !== $node->newName ? ' ' . $node->newName : '') . ';'; } public function pStmt_Property(Stmt\Property $node) { return (0 === $node->type ? 'var ' : $this->pModifiers($node->type)) . $this->pCommaSeparated($node->props) . ';'; } public function pStmt_PropertyProperty(Stmt\PropertyProperty $node) { return '$' . $node->name . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); } public function pStmt_ClassMethod(Stmt\ClassMethod $node) { return $this->pModifiers($node->type) . 'function ' . ($node->byRef ? '&' : '') . $node->name . '(' . $this->pCommaSeparated($node->params) . ')' . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '') . (null !== $node->stmts ? "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}' : ';'); } public function pStmt_ClassConst(Stmt\ClassConst $node) { return 'const ' . $this->pCommaSeparated($node->consts) . ';'; } public function pStmt_Function(Stmt\Function_ $node) { return 'function ' . ($node->byRef ? '&' : '') . $node->name . '(' . $this->pCommaSeparated($node->params) . ')' . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '') . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pStmt_Const(Stmt\Const_ $node) { return 'const ' . $this->pCommaSeparated($node->consts) . ';'; } public function pStmt_Declare(Stmt\Declare_ $node) { return 'declare (' . $this->pCommaSeparated($node->declares) . ') {' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node) { return $node->key . ' = ' . $this->p($node->value); } // Control flow public function pStmt_If(Stmt\If_ $node) { return 'if (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . "\n" . '}' . $this->pImplode($node->elseifs) . (null !== $node->else ? $this->p($node->else) : ''); } public function pStmt_ElseIf(Stmt\ElseIf_ $node) { return ' elseif (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pStmt_Else(Stmt\Else_ $node) { return ' else {' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pStmt_For(Stmt\For_ $node) { return 'for (' . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '') . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '') . $this->pCommaSeparated($node->loop) . ') {' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pStmt_Foreach(Stmt\Foreach_ $node) { return 'foreach (' . $this->p($node->expr) . ' as ' . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '') . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pStmt_While(Stmt\While_ $node) { return 'while (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pStmt_Do(Stmt\Do_ $node) { return 'do {' . $this->pStmts($node->stmts) . "\n" . '} while (' . $this->p($node->cond) . ');'; } public function pStmt_Switch(Stmt\Switch_ $node) { return 'switch (' . $this->p($node->cond) . ') {' . $this->pStmts($node->cases) . "\n" . '}'; } public function pStmt_Case(Stmt\Case_ $node) { return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':' . $this->pStmts($node->stmts); } public function pStmt_TryCatch(Stmt\TryCatch $node) { return 'try {' . $this->pStmts($node->stmts) . "\n" . '}' . $this->pImplode($node->catches) . ($node->finallyStmts !== null ? ' finally {' . $this->pStmts($node->finallyStmts) . "\n" . '}' : ''); } public function pStmt_Catch(Stmt\Catch_ $node) { return ' catch (' . $this->p($node->type) . ' $' . $node->var . ') {' . $this->pStmts($node->stmts) . "\n" . '}'; } public function pStmt_Break(Stmt\Break_ $node) { return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; } public function pStmt_Continue(Stmt\Continue_ $node) { return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; } public function pStmt_Return(Stmt\Return_ $node) { return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';'; } public function pStmt_Throw(Stmt\Throw_ $node) { return 'throw ' . $this->p($node->expr) . ';'; } public function pStmt_Label(Stmt\Label $node) { return $node->name . ':'; } public function pStmt_Goto(Stmt\Goto_ $node) { return 'goto ' . $node->name . ';'; } // Other public function pStmt_Echo(Stmt\Echo_ $node) { return 'echo ' . $this->pCommaSeparated($node->exprs) . ';'; } public function pStmt_Static(Stmt\Static_ $node) { return 'static ' . $this->pCommaSeparated($node->vars) . ';'; } public function pStmt_Global(Stmt\Global_ $node) { return 'global ' . $this->pCommaSeparated($node->vars) . ';'; } public function pStmt_StaticVar(Stmt\StaticVar $node) { return '$' . $node->name . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); } public function pStmt_Unset(Stmt\Unset_ $node) { return 'unset(' . $this->pCommaSeparated($node->vars) . ');'; } public function pStmt_InlineHTML(Stmt\InlineHTML $node) { return '?>' . $this->pNoIndent("\n" . $node->value) . 'remaining; } // Helpers protected function pType($node) { return is_string($node) ? $node : $this->p($node); } protected function pClassCommon(Stmt\Class_ $node, $afterClassToken) { return $this->pModifiers($node->type) . 'class' . $afterClassToken . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '') . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; } /** @internal */ public function pObjectProperty($node) { if ($node instanceof Expr) { return '{' . $this->p($node) . '}'; } else { return $node; } } /** @internal */ public function pModifiers($modifiers) { return ($modifiers & Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') . ($modifiers & Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') . ($modifiers & Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') . ($modifiers & Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') . ($modifiers & Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') . ($modifiers & Stmt\Class_::MODIFIER_FINAL ? 'final ' : ''); } /** @internal */ public function pEncapsList(array $encapsList, $quote) { $return = ''; foreach ($encapsList as $element) { if (is_string($element)) { $return .= addcslashes($element, "\n\r\t\f\v$" . $quote . "\\"); } else { $return .= '{' . $this->p($element) . '}'; } } return $return; } /** @internal */ public function pVarOrNewExpr(Node $node) { if ($node instanceof Expr\New_) { return '(' . $this->p($node) . ')'; } else { return $this->p($node); } } } array( 0, 1), 'Expr_BitwiseNot' => array( 10, 1), 'Expr_PreInc' => array( 10, 1), 'Expr_PreDec' => array( 10, 1), 'Expr_PostInc' => array( 10, -1), 'Expr_PostDec' => array( 10, -1), 'Expr_UnaryPlus' => array( 10, 1), 'Expr_UnaryMinus' => array( 10, 1), 'Expr_Cast_Int' => array( 10, 1), 'Expr_Cast_Double' => array( 10, 1), 'Expr_Cast_String' => array( 10, 1), 'Expr_Cast_Array' => array( 10, 1), 'Expr_Cast_Object' => array( 10, 1), 'Expr_Cast_Bool' => array( 10, 1), 'Expr_Cast_Unset' => array( 10, 1), 'Expr_ErrorSuppress' => array( 10, 1), 'Expr_Instanceof' => array( 20, 0), 'Expr_BooleanNot' => array( 30, 1), 'Expr_BinaryOp_Mul' => array( 40, -1), 'Expr_BinaryOp_Div' => array( 40, -1), 'Expr_BinaryOp_Mod' => array( 40, -1), 'Expr_BinaryOp_Plus' => array( 50, -1), 'Expr_BinaryOp_Minus' => array( 50, -1), 'Expr_BinaryOp_Concat' => array( 50, -1), 'Expr_BinaryOp_ShiftLeft' => array( 60, -1), 'Expr_BinaryOp_ShiftRight' => array( 60, -1), 'Expr_BinaryOp_Smaller' => array( 70, 0), 'Expr_BinaryOp_SmallerOrEqual' => array( 70, 0), 'Expr_BinaryOp_Greater' => array( 70, 0), 'Expr_BinaryOp_GreaterOrEqual' => array( 70, 0), 'Expr_BinaryOp_Equal' => array( 80, 0), 'Expr_BinaryOp_NotEqual' => array( 80, 0), 'Expr_BinaryOp_Identical' => array( 80, 0), 'Expr_BinaryOp_NotIdentical' => array( 80, 0), 'Expr_BinaryOp_Spaceship' => array( 80, 0), 'Expr_BinaryOp_BitwiseAnd' => array( 90, -1), 'Expr_BinaryOp_BitwiseXor' => array(100, -1), 'Expr_BinaryOp_BitwiseOr' => array(110, -1), 'Expr_BinaryOp_BooleanAnd' => array(120, -1), 'Expr_BinaryOp_BooleanOr' => array(130, -1), 'Expr_BinaryOp_Coalesce' => array(140, 1), 'Expr_Ternary' => array(150, -1), // parser uses %left for assignments, but they really behave as %right 'Expr_Assign' => array(160, 1), 'Expr_AssignRef' => array(160, 1), 'Expr_AssignOp_Plus' => array(160, 1), 'Expr_AssignOp_Minus' => array(160, 1), 'Expr_AssignOp_Mul' => array(160, 1), 'Expr_AssignOp_Div' => array(160, 1), 'Expr_AssignOp_Concat' => array(160, 1), 'Expr_AssignOp_Mod' => array(160, 1), 'Expr_AssignOp_BitwiseAnd' => array(160, 1), 'Expr_AssignOp_BitwiseOr' => array(160, 1), 'Expr_AssignOp_BitwiseXor' => array(160, 1), 'Expr_AssignOp_ShiftLeft' => array(160, 1), 'Expr_AssignOp_ShiftRight' => array(160, 1), 'Expr_AssignOp_Pow' => array(160, 1), 'Expr_YieldFrom' => array(165, 1), 'Expr_Print' => array(168, 1), 'Expr_BinaryOp_LogicalAnd' => array(170, -1), 'Expr_BinaryOp_LogicalXor' => array(180, -1), 'Expr_BinaryOp_LogicalOr' => array(190, -1), 'Expr_Include' => array(200, -1), ); protected $noIndentToken; protected $canUseSemicolonNamespaces; public function __construct() { $this->noIndentToken = '_NO_INDENT_' . mt_rand(); } /** * Pretty prints an array of statements. * * @param Node[] $stmts Array of statements * * @return string Pretty printed statements */ public function prettyPrint(array $stmts) { $this->preprocessNodes($stmts); return ltrim(str_replace("\n" . $this->noIndentToken, "\n", $this->pStmts($stmts, false))); } /** * Pretty prints an expression. * * @param Expr $node Expression node * * @return string Pretty printed node */ public function prettyPrintExpr(Expr $node) { return str_replace("\n" . $this->noIndentToken, "\n", $this->p($node)); } /** * Pretty prints a file of statements (includes the opening prettyPrint($stmts)); $p = preg_replace('/^\?>\n?/', '', $p, -1, $count); $p = preg_replace('/<\?php$/', '', $p); if (!$count) { $p = "canUseSemicolonNamespaces = true; foreach ($nodes as $node) { if ($node instanceof Stmt\Namespace_ && null === $node->name) { $this->canUseSemicolonNamespaces = false; } } } /** * Pretty prints an array of nodes (statements) and indents them optionally. * * @param Node[] $nodes Array of nodes * @param bool $indent Whether to indent the printed nodes * * @return string Pretty printed statements */ protected function pStmts(array $nodes, $indent = true) { $result = ''; foreach ($nodes as $node) { $result .= "\n" . $this->pComments($node->getAttribute('comments', array())) . $this->p($node) . ($node instanceof Expr ? ';' : ''); } if ($indent) { return preg_replace('~\n(?!$|' . $this->noIndentToken . ')~', "\n ", $result); } else { return $result; } } /** * Pretty prints a node. * * @param Node $node Node to be pretty printed * * @return string Pretty printed node */ protected function p(Node $node) { return $this->{'p' . $node->getType()}($node); } protected function pInfixOp($type, Node $leftNode, $operatorString, Node $rightNode) { list($precedence, $associativity) = $this->precedenceMap[$type]; return $this->pPrec($leftNode, $precedence, $associativity, -1) . $operatorString . $this->pPrec($rightNode, $precedence, $associativity, 1); } protected function pPrefixOp($type, $operatorString, Node $node) { list($precedence, $associativity) = $this->precedenceMap[$type]; return $operatorString . $this->pPrec($node, $precedence, $associativity, 1); } protected function pPostfixOp($type, Node $node, $operatorString) { list($precedence, $associativity) = $this->precedenceMap[$type]; return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString; } /** * Prints an expression node with the least amount of parentheses necessary to preserve the meaning. * * @param Node $node Node to pretty print * @param int $parentPrecedence Precedence of the parent operator * @param int $parentAssociativity Associativity of parent operator * (-1 is left, 0 is nonassoc, 1 is right) * @param int $childPosition Position of the node relative to the operator * (-1 is left, 1 is right) * * @return string The pretty printed node */ protected function pPrec(Node $node, $parentPrecedence, $parentAssociativity, $childPosition) { $type = $node->getType(); if (isset($this->precedenceMap[$type])) { $childPrecedence = $this->precedenceMap[$type][0]; if ($childPrecedence > $parentPrecedence || ($parentPrecedence == $childPrecedence && $parentAssociativity != $childPosition) ) { return '(' . $this->{'p' . $type}($node) . ')'; } } return $this->{'p' . $type}($node); } /** * Pretty prints an array of nodes and implodes the printed values. * * @param Node[] $nodes Array of Nodes to be printed * @param string $glue Character to implode with * * @return string Imploded pretty printed nodes */ protected function pImplode(array $nodes, $glue = '') { $pNodes = array(); foreach ($nodes as $node) { $pNodes[] = $this->p($node); } return implode($glue, $pNodes); } /** * Pretty prints an array of nodes and implodes the printed values with commas. * * @param Node[] $nodes Array of Nodes to be printed * * @return string Comma separated pretty printed nodes */ protected function pCommaSeparated(array $nodes) { return $this->pImplode($nodes, ', '); } /** * Signals the pretty printer that a string shall not be indented. * * @param string $string Not to be indented string * * @return mixed String marked with $this->noIndentToken's. */ protected function pNoIndent($string) { return str_replace("\n", "\n" . $this->noIndentToken, $string); } protected function pComments(array $comments) { $result = ''; foreach ($comments as $comment) { $result .= $comment->getReformattedText() . "\n"; } return $result; } } \'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\') (?"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+") (?(?&singleQuotedString)|(?&doubleQuotedString)) (?/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/) (?\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+}) )'; const PARAMS = '\[(?[^[\]]*+(?:\[(?¶ms)\][^[\]]*+)*+)\]'; const ARGS = '\((?[^()]*+(?:\((?&args)\)[^()]*+)*+)\)'; /////////////////// /// Main script /// /////////////////// echo 'Building temporary preproprocessed grammar file.', "\n"; $grammarCode = file_get_contents($grammarFile); $grammarCode = resolveNodes($grammarCode); $grammarCode = resolveMacros($grammarCode); $grammarCode = resolveArrays($grammarCode); $grammarCode = resolveStackAccess($grammarCode); file_put_contents($tmpGrammarFile, $grammarCode); $additionalArgs = $optionDebug ? '-t -v' : ''; echo "Building parser.\n"; $output = trim(shell_exec("$kmyacc $additionalArgs -l -m $skeletonFile $tmpGrammarFile 2>&1")); echo "Output: \"$output\"\n"; $resultCode = file_get_contents($tmpResultFile); $resultCode = removeTrailingWhitespace($resultCode); ensureDirExists(dirname($parserResultFile)); file_put_contents($parserResultFile, $resultCode); unlink($tmpResultFile); if (!$optionKeepTmpGrammar) { unlink($tmpGrammarFile); } /////////////////////////////// /// Preprocessing functions /// /////////////////////////////// function resolveNodes($code) { return preg_replace_callback( '~(?[A-Z][a-zA-Z_\\\\]++)\s*' . PARAMS . '~', function($matches) { // recurse $matches['params'] = resolveNodes($matches['params']); $params = magicSplit( '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', $matches['params'] ); $paramCode = ''; foreach ($params as $param) { $paramCode .= $param . ', '; } return 'new ' . $matches['name'] . '(' . $paramCode . 'attributes())'; }, $code ); } function resolveMacros($code) { return preg_replace_callback( '~\b(?)(?!array\()(?[a-z][A-Za-z]++)' . ARGS . '~', function($matches) { // recurse $matches['args'] = resolveMacros($matches['args']); $name = $matches['name']; $args = magicSplit( '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', $matches['args'] ); if ('attributes' == $name) { assertArgs(0, $args, $name); return '$this->startAttributeStack[#1] + $this->endAttributes'; } if ('init' == $name) { return '$$ = array(' . implode(', ', $args) . ')'; } if ('push' == $name) { assertArgs(2, $args, $name); return $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0]; } if ('pushNormalizing' == $name) { assertArgs(2, $args, $name); return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); } else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }'; } if ('toArray' == $name) { assertArgs(1, $args, $name); return 'is_array(' . $args[0] . ') ? ' . $args[0] . ' : array(' . $args[0] . ')'; } if ('parseVar' == $name) { assertArgs(1, $args, $name); return 'substr(' . $args[0] . ', 1)'; } if ('parseEncapsed' == $name) { assertArgs(2, $args, $name); return 'foreach (' . $args[0] . ' as &$s) { if (is_string($s)) { $s = Node\Scalar\String_::parseEscapeSequences($s, ' . $args[1] . '); } }'; } if ('parseEncapsedDoc' == $name) { assertArgs(1, $args, $name); return 'foreach (' . $args[0] . ' as &$s) { if (is_string($s)) { $s = Node\Scalar\String_::parseEscapeSequences($s, null); } } $s = preg_replace(\'~(\r\n|\n|\r)\z~\', \'\', $s); if (\'\' === $s) array_pop(' . $args[0] . ');'; } return $matches[0]; }, $code ); } function assertArgs($num, $args, $name) { if ($num != count($args)) { die('Wrong argument count for ' . $name . '().'); } } function resolveArrays($code) { return preg_replace_callback( '~' . PARAMS . '~', function ($matches) { $elements = magicSplit( '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', $matches['params'] ); // don't convert [] to array, it might have different meaning if (empty($elements)) { return $matches[0]; } $elementCodes = array(); foreach ($elements as $element) { // convert only arrays where all elements have keys if (false === strpos($element, ':')) { return $matches[0]; } list($key, $value) = explode(':', $element, 2); $elementCodes[] = "'" . $key . "' =>" . $value; } return 'array(' . implode(', ', $elementCodes) . ')'; }, $code ); } function resolveStackAccess($code) { $code = preg_replace('/\$\d+/', '$this->semStack[$0]', $code); $code = preg_replace('/#(\d+)/', '$$1', $code); return $code; } function removeTrailingWhitespace($code) { $lines = explode("\n", $code); $lines = array_map('rtrim', $lines); return implode("\n", $lines); } function ensureDirExists($dir) { if (!is_dir($dir)) { mkdir($dir, 0777, true); } } ////////////////////////////// /// Regex helper functions /// ////////////////////////////// function regex($regex) { return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~'; } function magicSplit($regex, $string) { $pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string); foreach ($pieces as &$piece) { $piece = trim($piece); } return array_filter($pieces); } \'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\') (?"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+") (?(?&singleQuotedString)|(?&doubleQuotedString)) (?/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/) (?\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+}) )'; const RULE_BLOCK = '(?[a-z_]++):(?[^\'"/{};]*+(?:(?:(?&string)|(?&comment)|(?&code)|/|})[^\'"/{};]*+)*+);'; $usedTerminals = array_flip(array( 'T_VARIABLE', 'T_STRING', 'T_INLINE_HTML', 'T_ENCAPSED_AND_WHITESPACE', 'T_LNUMBER', 'T_DNUMBER', 'T_CONSTANT_ENCAPSED_STRING', 'T_STRING_VARNAME', 'T_NUM_STRING' )); $unusedNonterminals = array_flip(array( 'case_separator', 'optional_comma' )); function regex($regex) { return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~'; } function magicSplit($regex, $string) { $pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string); foreach ($pieces as &$piece) { $piece = trim($piece); } return array_filter($pieces); } echo '
';

////////////////////
////////////////////
////////////////////

list($defs, $ruleBlocks) = magicSplit('%%', file_get_contents(GRAMMAR_FILE));

if ('' !== trim(preg_replace(regex(RULE_BLOCK), '', $ruleBlocks))) {
    die('Not all rule blocks were properly recognized!');
}

preg_match_all(regex(RULE_BLOCK), $ruleBlocks, $ruleBlocksMatches, PREG_SET_ORDER);
foreach ($ruleBlocksMatches as $match) {
    $ruleBlockName = $match['name'];
    $rules = magicSplit('\|', $match['rules']);

    foreach ($rules as &$rule) {
        $parts = magicSplit('\s+', $rule);
        $usedParts = array();

        foreach ($parts as $part) {
            if ('{' === $part[0]) {
                preg_match_all('~\$([0-9]+)~', $part, $backReferencesMatches, PREG_SET_ORDER);
                foreach ($backReferencesMatches as $match) {
                    $usedParts[$match[1]] = true;
                }
            }
        }

        $i = 1;
        foreach ($parts as &$part) {
            if ('/' === $part[0]) {
                continue;
            }

            if (isset($usedParts[$i])) {
                if ('\'' === $part[0] || '{' === $part[0]
                    || (ctype_upper($part[0]) && !isset($usedTerminals[$part]))
                    || (ctype_lower($part[0]) && isset($unusedNonterminals[$part]))
                ) {
                    $part = '' . $part . '';
                } else {
                    $part = '' . $part . '';
                }
            } elseif ((ctype_upper($part[0]) && isset($usedTerminals[$part]))
                      || (ctype_lower($part[0]) && !isset($unusedNonterminals[$part]))

            ) {
                $part = '' . $part . '';
            }

            ++$i;
        }

        $rule = implode(' ', $parts);
    }

    echo $ruleBlockName, ':', "\n", '      ', implode("\n" . '    | ', $rules), "\n", ';', "\n\n";
}
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * Interface for mutable sequences.
 *
 * Equality of elements in the sequence is established via a shallow comparison (===).
 *
 * @author Johannes M. Schmitt 
 */
interface SequenceInterface extends CollectionInterface
{
    /**
     * Returns the first element in the collection if available.
     *
     * @return Option
     */
    public function first();

    /**
     * Returns the last element in the collection if available.
     *
     * @return Option
     */
    public function last();

    /**
     * Returns all elements in this sequence.
     *
     * @return array
     */
    public function all();

    /**
     * Adds the elements of another sequence to this sequence.
     *
     * @param SequenceInterface $seq
     *
     * @return SequenceInterface
     */
    public function addSequence(SequenceInterface $seq);

    /**
     * Returns the index of the passed element.
     *
     * @param T $elem
     *
     * @return integer the index (0-based), or -1 if not found
     */
    public function indexOf($elem);

    /**
     * Returns the last index of the passed element.
     *
     * @param T $elem
     * @return integer the index (0-based), or -1 if not found
     */
    public function lastIndexOf($elem);

    /**
     * Returns whether the given index is defined in the sequence.
     *
     * @param integer $index (0-based)
     * @return boolean
     */
    public function isDefinedAt($index);

    /**
     * Returns the first index where the given callable returns true.
     *
     * @param callable $callable receives the element as first argument, and returns true, or false
     *
     * @return integer the index (0-based), or -1 if the callable returns false for all elements
     */
    public function indexWhere($callable);

    /**
     * Returns the last index where the given callable returns true.
     *
     * @param callable $callable receives the element as first argument, and returns true, or false
     *
     * @return integer the index (0-based), or -1 if the callable returns false for all elements
     */
    public function lastIndexWhere($callable);

    /**
     * Returns all indices of this collection.
     *
     * @return array
     */
    public function indices();

    /**
     * Returns the element at the given index.
     *
     * @param integer $index (0-based)
     *
     * @return T
     */
    public function get($index);

    /**
     * Adds an element to the sequence.
     *
     * @param T $elem
     *
     * @return void
     */
    public function add($elem);

    /**
     * Removes the element at the given index, and returns it.
     *
     * @param integer $index
     *
     * @return T
     */
    public function remove($index);

    /**
     * Adds all elements to the sequence.
     *
     * @param array $elements
     *
     * @return void
     */
    public function addAll(array $elements);

    /**
     * Updates the value at the given index.
     *
     * @param integer $index
     * @param T $value
     *
     * @return void
     */
    public function update($index, $value);

    /**
     * Returns a new sequence by omitting the given number of elements from the beginning.
     *
     * If the passed number is greater than the available number of elements, all will be removed.
     *
     * @param integer $number
     *
     * @return SequenceInterface
     */
    public function drop($number);

    /**
     * Returns a new sequence by omitting the given number of elements from the end.
     *
     * If the passed number is greater than the available number of elements, all will be removed.
     *
     * @param integer $number
     *
     * @return SequenceInterface
     */
    public function dropRight($number);

    /**
     * Returns a new sequence by omitting elements from the beginning for as long as the callable returns true.
     *
     * @param callable $callable Receives the element to drop as first argument, and returns true (drop), or false (stop).
     *
     * @return SequenceInterface
     */
    public function dropWhile($callable);

    /**
     * Creates a new collection by taking the given number of elements from the beginning
     * of the current collection.
     *
     * If the passed number is greater than the available number of elements, then all elements
     * will be returned as a new collection.
     *
     * @param integer $number
     *
     * @return CollectionInterface
     */
    public function take($number);

    /**
     * Creates a new collection by taking elements from the current collection
     * for as long as the callable returns true.
     *
     * @param callable $callable
     *
     * @return CollectionInterface
     */
    public function takeWhile($callable);
}

 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * Unsorted sequence implementation.
 *
 * Characteristics:
 *
 *     - Keys: consequentially numbered, without gaps
 *     - Values: anything, duplicates allowed
 *     - Ordering: same as input unless when explicitly sorted
 *
 * @author Johannes M. Schmitt 
 */
class Sequence extends AbstractSequence implements SortableInterface
{
    public function sortWith($callable)
    {
        usort($this->elements, $callable);
    }
}
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * Basic map interface.
 *
 * @IgnoreAnnotation("template")
 * @template K the type of the keys
 * @template V the type of the values
 *
 * @author Johannes M. Schmitt 
 */
interface MapInterface extends CollectionInterface
{
    /**
     * Returns the first element in the collection if available.
     *
     * @return Option>
     */
    public function first();

    /**
     * Returns the last element in the collection if available.
     *
     * @return Option>
     */
    public function last();

    /**
     * Searches the collection for an element.
     *
     * @param callable $callable receives the element as first argument, and returns true, or false
     *
     * @return Option>
     */
    public function find($callable);

    /**
     * Returns the value associated with the given key.
     *
     * @param K $key
     *
     * @return Option
     */
    public function get($key);

    /**
     * Returns whether this map contains a given key.
     *
     * @param K $key
     *
     * @return boolean
     */
    public function containsKey($key);

    /**
     * Puts a new element in the map.
     *
     * @param K $key
     * @param V $value
     *
     * @return void
     */
    public function set($key, $value);

    /**
     * Removes an element from the map.
     *
     * @param K $key
     *
     * @return V
     */
    public function remove($key);

    /**
     * Adds all another map to this map, and returns itself.
     *
     * @param MapInterface $map
     *
     * @return MapInterface
     */
    public function addMap(MapInterface $map);

    /**
     * Returns an array with the keys.
     *
     * @return array
     */
    public function keys();

    /**
     * Returns an array with the values.
     *
     * @return array
     */
    public function values();

    /**
     * Returns a new sequence by omitting the given number of elements from the beginning.
     *
     * If the passed number is greater than the available number of elements, all will be removed.
     *
     * @param integer $number
     *
     * @return MapInterface
     */
    public function drop($number);

    /**
     * Returns a new sequence by omitting the given number of elements from the end.
     *
     * If the passed number is greater than the available number of elements, all will be removed.
     *
     * @param integer $number
     *
     * @return MapInterface
     */
    public function dropRight($number);

    /**
     * Returns a new sequence by omitting elements from the beginning for as long as the callable returns true.
     *
     * @param callable $callable Receives the element to drop as first argument, and returns true (drop), or false (stop).
     *
     * @return MapInterface
     */
    public function dropWhile($callable);

    /**
     * Creates a new collection by taking the given number of elements from the beginning
     * of the current collection.
     *
     * If the passed number is greater than the available number of elements, then all elements
     * will be returned as a new collection.
     *
     * @param integer $number
     *
     * @return MapInterface
     */
    public function take($number);

    /**
     * Creates a new collection by taking elements from the current collection
     * for as long as the callable returns true.
     *
     * @param callable $callable
     *
     * @return MapInterface
     */
    public function takeWhile($callable);
}

 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

use PhpOption\Some;
use PhpOption\None;
use PhpOption\Option;
use OutOfBoundsException;

/**
 * A sequence with numerically indexed elements.
 *
 * This is rawly equivalent to an array with only numeric keys.
 * There are no restrictions on how many same values may occur in the sequence.
 *
 * This sequence is mutable.
 *
 * @IgnoreAnnotation("template")
 * @template T The type that this sequence contains.
 *
 * @author Johannes M. Schmitt 
 */
class AbstractSequence extends AbstractCollection implements \IteratorAggregate, SequenceInterface
{
    protected $elements;

    /**
     * @param array $elements
     */
    public function __construct(array $elements = array())
    {
        $this->elements = array_values($elements);
    }

    public function addSequence(SequenceInterface $seq)
    {
        $this->addAll($seq->all());
    }

    public function indexOf($searchedElement)
    {
        foreach ($this->elements as $i => $element) {
            if ($searchedElement === $element) {
                return $i;
            }
        }

        return -1;
    }

    public function lastIndexOf($searchedElement)
    {
        for ($i=count($this->elements)-1; $i>=0; $i--) {
            if ($this->elements[$i] === $searchedElement) {
                return $i;
            }
        }

        return -1;
    }

    public function isDefinedAt($index)
    {
        return isset($this->elements[$index]);
    }

    /**
     * Finds the first index where the given callable returns true.
     *
     * @param callable $callable
     *
     * @return integer the index, or -1 if the predicate is not true for any element.
     */
    public function indexWhere($callable)
    {
        foreach ($this->elements as $i => $element) {
            if (call_user_func($callable, $element) === true) {
                return $i;
            }
        }

        return -1;
    }

    public function lastIndexWhere($callable)
    {
        for ($i=count($this->elements)-1; $i>=0; $i--) {
            if (call_user_func($callable, $this->elements[$i]) === true) {
                return $i;
            }
        }

        return -1;
    }

    public function last()
    {
        if (empty($this->elements)) {
            return None::create();
        }

        return new Some(end($this->elements));
    }

    public function first()
    {
        if (empty($this->elements)) {
            return None::create();
        }

        return new Some(reset($this->elements));
    }

    public function indices()
    {
        return array_keys($this->elements);
    }

    /**
     * Returns an element based on its index (0-based).
     *
     * @param integer $index
     *
     * @return T
     */
    public function get($index)
    {
        if ( ! isset($this->elements[$index])) {
            throw new OutOfBoundsException(sprintf('The index "%s" does not exist in this sequence.', $index));
        }

        return $this->elements[$index];
    }

    /**
     * Removes the element at the given index, and returns it.
     *
     * @param int $index
     *
     * @return T
     *
     * @throws \OutOfBoundsException If there is no element at the given index.
     */
    public function remove($index)
    {
        if ( ! isset($this->elements[$index])) {
            throw new OutOfBoundsException(sprintf('The index "%d" is not in the interval [0, %d).', $index, count($this->elements)));
        }

        $element = $this->elements[$index];
        unset($this->elements[$index]);
        $this->elements = array_values($this->elements);

        return $element;
    }

    /**
     * Updates the element at the given index (0-based).
     *
     * @param integer $index
     * @param T $value
     */
    public function update($index, $value)
    {
        if ( ! isset($this->elements[$index])) {
            throw new \InvalidArgumentException(sprintf('There is no element at index "%d".', $index));
        }

        $this->elements[$index] = $value;
    }

    public function isEmpty()
    {
        return empty($this->elements);
    }

    public function all()
    {
        return $this->elements;
    }

    public function add($newElement)
    {
        $this->elements[] = $newElement;
    }

    public function addAll(array $addedElements)
    {
        foreach ($addedElements as $newElement) {
            $this->elements[] = $newElement;
        }
    }

    public function take($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('$number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, 0, $number));
    }

    /**
     * Extracts element from the head while the passed callable returns true.
     *
     * @param callable $callable receives elements of this sequence as first argument, and returns true/false.
     *
     * @return Sequence
     */
    public function takeWhile($callable)
    {
        $newElements = array();

        for ($i=0,$c=count($this->elements); $i<$c; $i++) {
            if (call_user_func($callable, $this->elements[$i]) !== true) {
                break;
            }

            $newElements[] = $this->elements[$i];
        }

        return $this->createNew($newElements);
    }

    public function drop($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, $number));
    }

    public function dropRight($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, 0, -1 * $number));
    }

    public function dropWhile($callable)
    {
        for ($i=0,$c=count($this->elements); $i<$c; $i++) {
            if (true !== call_user_func($callable, $this->elements[$i])) {
                break;
            }
        }

        return $this->createNew(array_slice($this->elements, $i));
    }

    public function count()
    {
        return count($this->elements);
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->elements);
    }

    protected function createNew(array $elements)
    {
        return new static($elements);
    }
}
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * Interface for sortable collections.
 *
 * @author Johannes M. Schmitt 
 */
interface SortableInterface
{
    public function sortWith($callable);
}
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

use PhpOption\Some;
use PhpOption\None;

/**
 * A simple map implementation which basically wraps an array with an object oriented interface.
 *
 * @IgnoreAnnotation("template")
 * @template {K extends string} This implementation only supports strings as keys.
 *
 * @author Johannes M. Schmitt 
 */
class AbstractMap extends AbstractCollection implements \IteratorAggregate, MapInterface
{
    protected $elements;

    public function __construct(array $elements = array())
    {
        $this->elements = $elements;
    }

    public function set($key, $value)
    {
        $this->elements[$key] = $value;
    }

    /**
     * Sets all key/value pairs in the map.
     *
     * @param array $kvMap
     *
     * @return void
     */
    public function setAll(array $kvMap)
    {
        $this->elements = array_merge($this->elements, $kvMap);
    }

    public function addMap(MapInterface $map)
    {
        foreach ($map as $k => $v) {
            $this->elements[$k] = $v;
        }
    }

    public function get($key)
    {
        if (isset($this->elements[$key])) {
            return new Some($this->elements[$key]);
        }

        return None::create();
    }

    public function remove($key)
    {
        if ( ! isset($this->elements[$key])) {
            throw new \InvalidArgumentException(sprintf('The map has no key named "%s".', $key));
        }

        $element = $this->elements[$key];
        unset($this->elements[$key]);

        return $element;
    }

    public function clear()
    {
        $this->elements = array();
    }

    public function first()
    {
        if (empty($this->elements)) {
            return None::create();
        }

        $elem = reset($this->elements);

        return new Some(array(key($this->elements), $elem));
    }

    public function last()
    {
        if (empty($this->elements)) {
            return None::create();
        }

        $elem = end($this->elements);

        return new Some(array(key($this->elements), $elem));
    }

    public function contains($elem)
    {
        foreach ($this->elements as $existingElem) {
            if ($existingElem === $elem) {
                return true;
            }
        }

        return false;
    }

    public function containsKey($key)
    {
        return isset($this->elements[$key]);
    }

    public function isEmpty()
    {
        return empty($this->elements);
    }

    public function dropWhile($callable)
    {
        $newElements = array();
        $stopped = false;
        foreach ($this->elements as $k => $v) {
            if ( ! $stopped) {
                if (call_user_func($callable, $k, $v) === true) {
                    continue;
                }

                $stopped = true;
            }

            $newElements[$k] = $v;
        }

        return $this->createNew($newElements);
    }

    public function drop($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, $number, null, true));
    }

    public function dropRight($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, 0, -1 * $number, true));
    }

    public function take($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, 0, $number, true));
    }

    public function takeWhile($callable)
    {
        $newElements = array();
        foreach ($this->elements as $k => $v) {
            if (call_user_func($callable, $k, $v) !== true) {
                break;
            }

            $newElements[$k] = $v;
        }

        return $this->createNew($newElements);
    }

    public function find($callable)
    {
        foreach ($this->elements as $k => $v) {
            if (call_user_func($callable, $k, $v) === true) {
                return new Some(array($k, $v));
            }
        }

        return None::create();
    }

    public function keys()
    {
        return array_keys($this->elements);
    }

    public function values()
    {
        return array_values($this->elements);
    }

    public function count()
    {
        return count($this->elements);
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->elements);
    }

    protected function createNew(array $elements)
    {
        return new static($elements);
    }
}
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * Basic interface which adds some behaviors, and a few methods common to all collections.
 *
 * @author Johannes M. Schmitt 
 */
interface CollectionInterface extends \Traversable, \Countable
{
    /**
     * Returns whether this collection contains the passed element.
     *
     * @param mixed $elem
     *
     * @return boolean
     */
    public function contains($elem);

    /**
     * Returns whether the collection is empty.
     *
     * @return boolean
     */
    public function isEmpty();
}
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

class Map extends AbstractMap implements SortableInterface
{
    public function sortWith($callable)
    {
        uksort($this->elements, $callable);
    }
}
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * A sequence with a fixed sort-order.
 *
 * @author Johannes M. Schmitt 
 */
class SortedSequence extends AbstractSequence
{
    private $sortFunc;

    public function __construct($sortFunc, array $elements = array())
    {
        usort($elements, $sortFunc);
        parent::__construct($elements);

        $this->sortFunc = $sortFunc;
    }

    public function add($newElement)
    {
        $added = false;
        $newElements = array();
        foreach ($this->elements as $element) {
            // We insert the new element before the first element that is greater than itself.
            if ( ! $added && (integer) call_user_func($this->sortFunc, $newElement, $element) < 0) {
                $newElements[] = $newElement;
                $added = true;
            }

            $newElements[] = $element;
        }

        if ( ! $added) {
            $newElements[] = $newElement;
        }
        $this->elements = $newElements;
    }

    public function addAll(array $addedElements)
    {
        usort($addedElements, $this->sortFunc);

        $newElements = array();
        foreach ($this->elements as $element) {
            if ( ! empty($addedElements)) {
                foreach ($addedElements as $i => $newElement) {
                    // If the currently looked at $newElement is not smaller than $element, then we can also conclude
                    // that all other new elements are also not smaller than $element as we have ordered them before.
                    if ((integer) call_user_func($this->sortFunc, $newElement, $element) > -1) {
                        break;
                    }

                    $newElements[] = $newElement;
                    unset($addedElements[$i]);
                }
            }

            $newElements[] = $element;
        }

        if ( ! empty($addedElements)) {
            foreach ($addedElements as $newElement) {
                $newElements[] = $newElement;
            }
        }

        $this->elements = $newElements;
    }

    protected function createNew(array $elements)
    {
        return new static($this->sortFunc, $elements);
    }
}
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

use PhpOption\LazyOption;
use PhpOption\Some;
use PhpOption\None;

abstract class AbstractCollection
{
    public function contains($searchedElem)
    {
        foreach ($this as $elem) {
            if ($elem === $searchedElem) {
                return true;
            }
        }

        return false;
    }

    public function find($callable)
    {
        $self = $this;

        return new LazyOption(function() use ($callable, $self) {
            foreach ($self as $elem) {
                if (call_user_func($callable, $elem) === true) {
                    return new Some($elem);
                }
            }

            return None::create();
        });
    }
}count() > 0) {
            $patterns = array();
            foreach ($this as $item) {
                $this->convertToPregCompliant($item);
                $patterns[] = $item;
            }

            $pattern = '/('.implode('|', $patterns).')$/';
        }

        return $pattern;
    }

    /**
     * Converts $string into a string that can be used with preg_match.
     *
     * @param string &$string Glob-like pattern with wildcards ? and *.
     *
     * @author Greg Beaver 
     * @author mike van Riel 
     *
     * @see PhpDocumentor/phpDocumentor/Io.php
     *
     * @return void
     */
    protected function convertToPregCompliant(&$string)
    {
        $y = (DIRECTORY_SEPARATOR == '\\') ? '\\\\' : '\/';
        $string = str_replace('/', DIRECTORY_SEPARATOR, $string);
        $x = strtr(
            $string,
            array(
                 '?' => '.',
                 '*' => '.*',
                 '.' => '\\.',
                 '\\' => '\\\\',
                 '/' => '\\/',
                 '[' => '\\[',
                 ']' => '\\]',
                 '-' => '\\-'
            )
        );

        if ((strpos($string, DIRECTORY_SEPARATOR) !== false)
            && (strrpos($string, DIRECTORY_SEPARATOR) === strlen($string) - 1)
        ) {
            $x = "(?:.*$y$x?.*|$x.*)";
        }

        $string = $x;
    }

}
getPathname();
        }

        if (!is_string($file)) {
            throw new \InvalidArgumentException(
                'Expected filename or object of type SplFileInfo but received '
                . get_class($file)
            );
        }

        if (empty($file)) {
            throw new \InvalidArgumentException(
                'Expected filename or object of type SplFileInfo but received nothing at all'
            );
        }

        parent::__construct($file);
    }

    /**
     * Returns the mime type for this file.
     *
     * @throws \RuntimeException if finfo failed to load
     *                           and/or mime_content_type is unavailable
     * @throws \LogicException if the mime type could not be interpreted
     *                         from the output of finfo_file
     *
     * @return string
     */
    public function getMimeType()
    {
        if (function_exists('finfo_open')) {
            $finfo = finfo_open(FILEINFO_MIME);
            if (!$finfo) {
                throw new \RuntimeException('Failed to open finfo');
            }

            $actualInfo = @finfo_file($finfo, $this->getPathname());
            if (false === $actualInfo) {
                throw new \RuntimeException('Failed to read file info via finfo');
            }
            $mime = strtolower($actualInfo);
            finfo_close($finfo);

            if (!preg_match(
                '/^([a-z0-9]+\/[a-z0-9\-\.]+);\s+charset=(.*)$/', $mime, $matches
            )) {
                throw new \LogicException(
                    'An error parsing the MIME type "'.$mime.'".'
                );
            }

            return $matches[1];
        } elseif (function_exists('mime_content_type')) {
            return mime_content_type($this->getPathname());
        }

        throw new \RuntimeException(
            'The finfo extension or mime_content_type function are needed to '
            .'determine the Mime Type for this file.'
        );
    }

    /**
     * Returns the file contents as a string.
     *
     * @return string
     * @throws \RuntimeException if unable to open the file
     */
    public function fread()
    {
        try {
            $file = $this->openFile('r');
        } catch (\Exception $exc) {
            throw new \RuntimeException('Unable to open file', 0, $exc);
        }

        $result = '';
        foreach ($file as $line) {
            $result .= $line;
        }

        return $result;
    }

    /**
     * Returns the filename, relative to the given root.
     *
     * @param string $root_path The root_path of which this file is composed.
     *
     * @throws \InvalidArgumentException if file is not in the project root.
     *
     * @return string
     *
     * @todo this protected method is unused in this class... can it be removed?
     */
    protected function getFilenameRelativeToRoot($root_path)
    {
        // strip path from filename
        $result = ltrim(
            substr($this->getPathname(), strlen($root_path)),
            DIRECTORY_SEPARATOR
        );

        if ($result === '') {
            throw new \InvalidArgumentException(
                'File "' . $this->getPathname() . '" is not present in the '
                .'given root: ' . $root_path
            );
        }

        return $result;
    }

}

 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Fileset;

/**
 * Files container handling directory scanning, project root detection and ignores.
 *
 * Always set any filtering options (extensions, ignore patterns, hidden files, symlinks)
 * _before_ adding any directories or files.  Such filtering is done immediately
 * upon loading the directory/file.  As such, setting filtering options
 * _after_ adding directories/files will seem as though your filters were ignored.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Collection extends \ArrayObject
{
    /** @var bool Whether to follow symlinks*/
    protected $follow_symlinks = false;

    /** @var bool Whether to ignore hidden files and folders */
    protected $ignore_hidden = false;

    /** @var Collection\IgnorePatterns */
    protected $ignore_patterns = array();

    /** @var \ArrayObject Array containing a list of allowed line endings */
    protected $allowed_extensions = null;

    /** @var string[] An array containing file names */
    protected $files = array();

    /**
     * Initializes the finding component.
     */
    public function __construct()
    {
        $this->ignore_patterns = new Collection\IgnorePatterns();
        $this->allowed_extensions = new \ArrayObject(
            array('php', 'php3', 'phtml')
        );
    }

    /**
     * Sets the patterns by which to detect which files to ignore.
     *
     * @param array $patterns Glob-like patterns to filter files.
     *
     * @return void
     */
    public function setIgnorePatterns(array $patterns)
    {
        $this->ignore_patterns = new Collection\IgnorePatterns($patterns);
    }

    /**
     * Returns the ignore patterns.
     *
     * @return Collection\IgnorePatterns
     */
    public function getIgnorePatterns()
    {
        return $this->ignore_patterns;
    }

    /**
     * Sets a list of allowed extensions; if not used php, php3 and phtml
     * is assumed.
     *
     * @param array $extensions An array containing extensions to match for.
     *
     * @return void
     */
    public function setAllowedExtensions(array $extensions)
    {
        $this->allowed_extensions = new \ArrayObject($extensions);
    }

    /**
     * Adds a file extension to the list of allowed extensions.
     *
     * No dot is necessary and will even prevent the extension from being
     * picked up.
     *
     * @param string $extension Allowed file Extension to add (i.e. php).
     *
     * @return void
     */
    public function addAllowedExtension($extension)
    {
        $this->allowed_extensions->append($extension);
    }

    /**
     * Adds the content of a set of directories to the list of files to parse.
     *
     * @param array $paths The paths whose contents to add to the collection.
     *
     * @return void
     */
    public function addDirectories(array $paths)
    {
        foreach ($paths as $path) {
            $this->addDirectory($path);
        }
    }

    /**
     * Retrieve all files in the given directory and add them to the parsing list.
     *
     * @param string $path A path to a folder, may be relative, absolute or
     *  even phar.
     *
     * @return void
     */
    public function addDirectory($path)
    {
        $finder = new \Symfony\Component\Finder\Finder();

        $patterns = $this->getIgnorePatterns()->getRegularExpression();

        if ($this->follow_symlinks) {
            $finder->followLinks();
        }

        // restrict names to those ending in the given extensions
        $finder
            ->files()
            ->in($path)
            ->name(
                '/\.('.implode('|', $this->allowed_extensions->getArrayCopy()).')$/'
            )
            ->ignoreDotFiles($this->getIgnoreHidden())
            ->filter(
                function(\SplFileInfo $file) use ($patterns) {
                    if (!$patterns) {
                        return true;
                    }

                    // apply ignore list on path instead of file, finder
                    // can't do that by default
                    return !preg_match($patterns, $file->getPathname());
                }
            );

        try {
            /** @var \SplFileInfo $file */
            foreach ($finder as $file) {
                $file = new File($file);
                $path = $file->getRealPath()
                    ? $file->getRealPath()
                    : $file->getPathname();

                $this[$path] = $file;
            }
        } catch(\LogicException $e)
        {
            // if a logic exception is thrown then no folders were included
            // for phpDocumentor this is not an issue since we accept separate
            // files as well
        }
    }

    /**
     * Adds a list of individual files to the collection.
     *
     * @param array $paths File locations, may be absolute, relative or even phar.
     *
     * @return void
     */
    public function addFiles(array $paths)
    {
        foreach ($paths as $path) {
            $this->addFile($path);
        }
    }

    /**
     * Adds a file to the collection.
     *
     * @param string $path File location, may be absolute, relative or even phar.
     *
     * @return void
     */
    public function addFile($path)
    {
        $paths = $this->getGlobbedPaths($path);
        foreach ($paths as $path) {
            $file = new File($path);
            $path = $file->getRealPath()
                ? $file->getRealPath()
                : $file->getPathname();

            $this[$path] = $file;
        }
    }

    /**
     * Get a globbed list out of the given path.
     *
     * This wrapper method normalizes for OS-divergent behavior of the native glob() function.
     * @param string $path
     * @return array
     */
    protected function getGlobbedPaths($path)
    {
        $paths = glob($path);

        /*
         * Windows glob('') returns an array with one empty member...
         * 'nix glob('') returns an empty array...
         * we'd prefer to have the File('') constructor throw the exception in this edge case,
         * so keep the Windows behavior.
         */
        $result = (array() === $paths) ? array('') : $paths;

        return $result;
    }

    /**
     * Returns a list of file paths that are ready to be parsed.
     *
     * Please note that the ignore pattern will be applied and all files are
     * converted to absolute paths.
     *
     * @return string[]
     */
    public function getFilenames()
    {
        return array_keys($this->getArrayCopy());
    }

    /**
     * Calculates the project root from the given files by determining their
     * highest common path.
     *
     * @return string
     */
    public function getProjectRoot()
    {
        $base = '';
        $files = array_keys($this->getArrayCopy());
        $parts = explode(DIRECTORY_SEPARATOR, reset($files));

        foreach ($parts as $part) {
            $base_part = $base . $part . DIRECTORY_SEPARATOR;
            foreach ($files as $dir) {
                if (substr($dir, 0, strlen($base_part)) != $base_part) {
                    return $base;
                }
            }

            $base = $base_part;
        }

        return $base;
    }

    /**
     * Sets whether to ignore hidden files and folders.
     *
     * @param boolean $ignore_hidden if true skips hidden files and folders.
     *
     * @return void
     */
    public function setIgnoreHidden($ignore_hidden)
    {
        $this->ignore_hidden = $ignore_hidden;
    }

    /**
     * Returns whether files and folders that are hidden are ignored.
     *
     * @return boolean
     */
    public function getIgnoreHidden()
    {
        return $this->ignore_hidden;
    }

    /**
     * Sets whether to follow symlinks.
     *
     * PHP version 5.2.11 is at least required since the
     * RecursiveDirectoryIterator does not support the FOLLOW_SYMLINKS
     * constant before that version.
     *
     * @param boolean $follow_symlinks
     *
     * @return void
     */
    public function setFollowSymlinks($follow_symlinks)
    {
        $this->follow_symlinks = $follow_symlinks;
    }

    /**
     * Returns whether to follow symlinks.
     *
     * @return boolean
     */
    public function getFollowSymlinks()
    {
        return $this->follow_symlinks;
    }

}

 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\GraphViz;

/**
 * Class representing an exception in this GraphViz component.
 *
 * @author    Mike van Riel 
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class Exception extends \Exception
{

}
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\GraphViz;

/**
 * Class representing a single GraphViz attribute.
 *
 * @author    Mike van Riel 
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class Attribute
{
    /** @var string The name of this attribute */
    protected $key = '';

    /** @var string The value of this attribute*/
    protected $value = '';

    /**
     * Creating a new attribute.
     *
     * @param string $key   Id for the new attribute.
     * @param string $value Value for this attribute,
     */
    public function __construct($key, $value)
    {
        $this->key = $key;
        $this->value = $value;
    }

    /**
     * Sets the key for this attribute.
     *
     * @param string $key The new name of this attribute.
     *
     * @return \phpDocumentor\GraphViz\Attribute
     */
    public function setKey($key)
    {
        $this->key = $key;
        return $this;
    }

    /**
     * Returns the name for this attribute.
     *
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * Sets the value for this attribute.
     *
     * @param string $value The new value.
     *
     * @return \phpDocumentor\GraphViz\Attribute
     */
    public function setValue($value)
    {
        $this->value = $value;
        return $this;
    }

    /**
     * Returns the value for this attribute.
     *
     * @return string
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Returns the attribute definition as is requested by GraphViz.
     *
     * @return string
     */
    public function __toString()
    {
        $key = $this->getKey();
        if ($key == 'url') {
            $key = 'URL';
        }

        $value = $this->getValue();
        if (!$this->isValueInHtml() || $this->isValueContainingSpecials()) {
            $value = '"' . addslashes($value) . '"';
        }
        return $key . '=' . $value;
    }

    /**
     * Returns whether the value contains HTML.
     *
     * @return bool
     */
    public function isValueInHtml()
    {
        $value = $this->getValue();

        return (bool)(isset($value[0]) && ($value[0] == '<'));
    }

    /**
     * Checks whether the value contains any any special characters needing escaping.
     *
     * @return bool
     */
    public function isValueContainingSpecials()
    {
        return strstr($this->getValue(), "\\") !== false;
    }
}

 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\GraphViz;

/**
 * Class representing an edge (arrow, line).
 *
 * @author    Mike van Riel 
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class Edge
{
    /** @var \phpDocumentor\GraphViz\Node Node from where to link */
    protected $from = null;

    /** @var \phpDocumentor\GraphViz\Node Node where to to link */
    protected $to = null;

    /** @var \phpDocumentor\GraphViz\Attribute List of attributes for this edge */
    protected $attributes = array();

    /**
     * Creates a new Edge / Link between the given nodes.
     *
     * @param \phpDocumentor\GraphViz\Node $from Starting node to create an Edge from.
     * @param \phpDocumentor\GraphViz\Node $to   Destination node where to create and
     *  edge to.
     */
    function __construct(Node $from, Node $to)
    {
        $this->from = $from;
        $this->to   = $to;
    }

    /**
     * Factory method used to assist with fluent interface handling.
     *
     * See the examples for more details.
     *
     * @param \phpDocumentor\GraphViz\Node $from Starting node to create an Edge from.
     * @param \phpDocumentor\GraphViz\Node $to   Destination node where to create and
     *  edge to.
     *
     * @return \phpDocumentor\GraphViz\Edge
     */
    public static function create(Node $from, Node $to) {
        return new self($from, $to);
    }

    /**
     * Returns the source Node for this Edge.
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    public function getFrom()
    {
        return $this->from;
    }

    /**
     * Returns the destination Node for this Edge.
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    public function getTo()
    {
        return $this->to;
    }

    /**
     * Magic method to provide a getter/setter to add attributes on the edge.
     *
     * Using this method we make sure that we support any attribute without too
     * much hassle. If the name for this method does not start with get or set
     * we return null.
     *
     * Set methods return this graph (fluent interface) whilst get methods
     * return the attribute value.
     *
     * @param string  $name      name of the invoked method, expect it to be
     *  setX or getX.
     * @param mixed[] $arguments Arguments for the setter, only 1 is expected: value
     *
     * @return \phpDocumentor\GraphViz\Attribute[]|\phpDocumentor\GraphViz\Edge|null
     */
    function __call($name, $arguments)
    {
        $key = strtolower(substr($name, 3));
        if (strtolower(substr($name, 0, 3)) == 'set') {
            $this->attributes[$key] = new Attribute($key, $arguments[0]);

            return $this;
        }
        if (strtolower(substr($name, 0, 3)) == 'get') {
            return $this->attributes[$key];
        }

        return null;
    }

    /**
     * Returns the edge definition as is requested by GraphViz.
     *
     * @return string
     */
    public function __toString()
    {
        $attributes = array();
        foreach ($this->attributes as $value) {
            $attributes[] = (string)$value;
        }
        $attributes = implode("\n", $attributes);

        $from_name = addslashes($this->getFrom()->getName());
        $to_name   = addslashes($this->getTo()->getName());

        return << "$to_name" [
$attributes
]
DOT;
    }
}

 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\GraphViz;

/**
 * Class representing a node / element in a graph.
 *
 * @author    Mike van Riel 
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 *
 * @method void setLabel(string $name) Sets the label for this node.
 */
class Node
{

    /** @var string Name for this node */
    protected $name = '';

    /** @var \phpDocumentor\GraphViz\Attribute[] List of attributes for this node */
    protected $attributes = array();

    /**
     * Creates a new node with name and optional label.
     *
     * @param string      $name  Name of the new node.
     * @param string|null $label Optional label text.
     */
    function __construct($name, $label = null)
    {
        $this->setName($name);
        if ($label !== null) {
            $this->setLabel($label);
        }
    }

    /**
     * Factory method used to assist with fluent interface handling.
     *
     * See the examples for more details.
     *
     * @param string      $name  Name of the new node.
     * @param string|null $label Optional label text.
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    public static function create($name, $label = null)
    {
        return new self($name, $label);
    }

    /**
     * Sets the name for this node.
     *
     * Not to confuse with the label.
     *
     * @param string $name Name for this node.
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    /**
     * Returns the name for this node.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Magic method to provide a getter/setter to add attributes on the Node.
     *
     * Using this method we make sure that we support any attribute without
     * too much hassle. If the name for this method does not start with get or
     * set we return null.
     *
     * Set methods return this graph (fluent interface) whilst get methods
     * return the attribute value.
     *
     * @param string  $name      Method name; either getX or setX is expected.
     * @param mixed[] $arguments List of arguments; only 1 is expected for setX.
     *
     * @return \phpDocumentor\GraphViz\Attribute[]|\phpDocumentor\GraphViz\Node|null
     */
    function __call($name, $arguments)
    {
        $key = strtolower(substr($name, 3));
        if (strtolower(substr($name, 0, 3)) == 'set') {
            $this->attributes[$key] = new Attribute($key, $arguments[0]);
            return $this;
        }

        if (strtolower(substr($name, 0, 3)) == 'get') {
            return $this->attributes[$key];
        }

        return null;
    }

    /**
     * Returns the node definition as is requested by GraphViz.
     *
     * @return string
     */
    public function __toString()
    {
        $attributes = array();
        foreach ($this->attributes as $value) {
            $attributes[] = (string)$value;
        }
        $attributes = implode("\n", $attributes);

        $name = addslashes($this->getName());

        return <<
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\GraphViz;

/**
 * Class representing a graph; this may be a main graph but also a subgraph.
 *
 * In case of a subgraph:
 * When the name of the subgraph is prefixed with _cluster_ then the contents
 * of this graph will be grouped and a border will be added. Otherwise it is
 * used as logical container to place defaults in.
 *
 * @author    Mike van Riel 
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 * 
 * @method Graph setRankSep(string $rankSep)
 * @method Graph setCenter(string $center)
 * @method Graph setRank(string $rank)
 * @method Graph setRankDir(string $rankDir)
 * @method Graph setSplines(string $splines)
 * @method Graph setConcentrate(string $concentrate)
 */
class Graph
{

    /** @var string Name of this graph */
    protected $name = 'G';

    /** @var string Type of this graph; may be digraph, graph or subgraph */
    protected $type = 'digraph';

    /** @var \phpDocumentor\GraphViz\Attribute[] A list of attributes for this Graph */
    protected $attributes = array();

    /** @var \phpDocumentor\GraphViz\Graph[] A list of subgraphs for this Graph */
    protected $graphs = array();

    /** @var \phpDocumentor\GraphViz\Node[] A list of nodes for this Graph */
    protected $nodes = array();

    /** @var \phpDocumentor\GraphViz\Edge[] A list of edges / arrows for this Graph */
    protected $edges = array();

    protected $path = '';

    /**
     * Factory method to instantiate a Graph so that you can use fluent coding
     * to chain everything.
     *
     * @param string $name        The name for this graph.
     * @param bool   $directional Whether this is a directed or undirected graph.
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public static function create($name = 'G', $directional = true)
    {
        $graph = new self();
        $graph
            ->setName($name)
            ->setType($directional ? 'digraph' : 'graph');

        return $graph;
    }

    /**
     * Sets the path for the execution. Only needed if it is not in the PATH env.
     *
     * @param string $path The path to execute dot from
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function setPath($path)
    {
        if ($path && $path = realpath($path)) {
            $this->path = $path . DIRECTORY_SEPARATOR;
        }
        return $this;
    }

    /**
     * Sets the name for this graph.
     *
     * If this is a subgraph you can prefix the name with _cluster_ to group all
     * contained nodes and add a border.
     *
     * @param string $name The new name for this graph.
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    /**
     * Returns the name for this Graph.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets the type for this graph.
     *
     * @param string $type Must be either "digraph", "graph" or "subgraph".
     *
     * @throws \InvalidArgumentException if $type is not "digraph", "graph" or
     *  "subgraph".
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function setType($type)
    {
        if (!in_array($type, array('digraph', 'graph', 'subgraph'))) {
            throw new \InvalidArgumentException(
                'The type for a graph must be either "digraph", "graph" or '
                . '"subgraph"'
            );
        }

        $this->type = $type;
        return $this;
    }

    /**
     * Returns the type of this Graph.
     *
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Magic method to provide a getter/setter to add attributes on the Graph.
     *
     * Using this method we make sure that we support any attribute without
     * too much hassle. If the name for this method does not start with get
     * or set we return null.
     *
     * Set methods return this graph (fluent interface) whilst get methods
     * return the attribute value.
     *
     * @param string  $name      Name of the method including get/set
     * @param mixed[] $arguments The arguments, should be 1: the value
     *
     * @return \phpDocumentor\GraphViz\Attribute[]|\phpDocumentor\GraphViz\Graph|null
     */
    function __call($name, $arguments)
    {
        $key = strtolower(substr($name, 3));
        if (strtolower(substr($name, 0, 3)) === 'set') {
            $this->attributes[$key] = new Attribute($key, $arguments[0]);

            return $this;
        }
        if (strtolower(substr($name, 0, 3)) === 'get') {
            return $this->attributes[$key];
        }

        return null;
    }

    /**
     * Adds a subgraph to this graph; automatically changes the type to subgraph.
     *
     * Please note that an index is maintained using the name of the subgraph.
     * Thus if you have 2 subgraphs with the same name that the first will be
     * overwritten by the latter.
     *
     * @param \phpDocumentor\GraphViz\Graph $graph The graph to add onto this graph as
     *  subgraph.
     *
     * @see \phpDocumentor\GraphViz\Graph::create()
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function addGraph(\phpDocumentor\GraphViz\Graph $graph)
    {
        $graph->setType('subgraph');
        $this->graphs[$graph->getName()] = $graph;
        return $this;
    }

    /**
     * Checks whether a graph with a certain name already exists.
     *
     * @param string $name Name of the graph to find.
     *
     * @return bool
     */
    public function hasGraph($name)
    {
        return isset($this->graphs[$name]);
    }

    /**
     * Returns the subgraph with a given name.
     *
     * @param string $name Name of the requested graph.
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function getGraph($name)
    {
        return $this->graphs[$name];
    }

    /**
     * Sets a node in the $nodes array; uses the name of the node as index.
     *
     * Nodes can be retrieved by retrieving the property with the same name.
     * Thus 'node1' can be retrieved by invoking: $graph->node1
     *
     * @param \phpDocumentor\GraphViz\Node $node The node to set onto this Graph.
     *
     * @see \phpDocumentor\GraphViz\Node::create()
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function setNode(Node $node)
    {
        $this->nodes[$node->getName()] = $node;
        return $this;
    }

    /**
     * Finds a node in this graph or any of its subgraphs.
     *
     * @param string $name Name of the node to find.
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    public function findNode($name)
    {
        if (isset($this->nodes[$name])) {
            return $this->nodes[$name];
        }

        foreach ($this->graphs as $graph) {
            $node = $graph->findNode($name);
            if ($node) {
                return $node;
            }
        }

        return null;
    }

    /**
     * Sets a node using a custom name.
     *
     * @param string                       $name  Name of the node.
     * @param \phpDocumentor\GraphViz\Node $value Node to set on the given name.
     *
     * @see \phpDocumentor\GraphViz\Graph::setNode()
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    function __set($name, $value)
    {
        $this->nodes[$name] = $value;
        return $this;
    }


    /**
     * Returns the requested node by its name.
     *
     * @param string $name The name of the node to retrieve.
     *
     * @see \phpDocumentor\GraphViz\Graph::setNode()
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    function __get($name)
    {
        return isset($this->nodes[$name]) ? $this->nodes[$name] : null;
    }

    /**
     * Links two nodes to eachother and registers the Edge onto this graph.
     *
     * @param \phpDocumentor\GraphViz\Edge $edge The link between two classes.
     *
     * @see \phpDocumentor\GraphViz\Edge::create()
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function link(Edge $edge)
    {
        $this->edges[] = $edge;
        return $this;
    }

    /**
     * Exports this graph to a generated image.
     *
     * This is the only method that actually requires GraphViz.
     *
     * @param string $type     The type to export to; see the link above for a
     *  list of supported types.
     * @param string $filename The path to write to.
     *
     * @uses GraphViz/dot
     *
     * @link http://www.graphviz.org/content/output-formats
     *
     * @throws \phpDocumentor\GraphViz\Exception if an error occurred in GraphViz.
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function export($type, $filename)
    {
        $type = escapeshellarg($type);
        $filename = escapeshellarg($filename);

        // write the dot file to a temporary file
        $tmpfile = tempnam(sys_get_temp_dir(), 'gvz');
        file_put_contents($tmpfile, (string)$this);

        // escape the temp file for use as argument
        $tmpfileArg = escapeshellarg($tmpfile);

        // create the dot output
        $output = array();
        $code = 0;
        exec($this->path . "dot -T$type -o$filename < $tmpfileArg 2>&1", $output, $code);
        unlink($tmpfile);

        if ($code != 0) {
            throw new Exception(
                'An error occurred while creating the graph; GraphViz returned: '
                . implode(PHP_EOL, $output)
            );
        }

        return $this;
    }

    /**
     * Generates a DOT file for use with GraphViz.
     *
     * GraphViz is not used in this method; it is safe to call it even without
     * GraphViz installed.
     *
     * @return string
     */
    public function __toString()
    {
        $elements = array_merge(
            $this->graphs, $this->attributes, $this->edges, $this->nodes
        );

        $attributes = array();
        foreach ($elements as $value) {
            $attributes[] = (string)$value;
        }
        $attributes = implode(PHP_EOL, $attributes);

        return <<getType()} "{$this->getName()}" {
$attributes
}
DOT;
    }

}

 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use PhpParser\Node\Scalar\String_;
use PhpParser\PrettyPrinter\Standard;

/**
 * Custom PrettyPrinter for phpDocumentor.
 *
 * phpDocumentor has a custom PrettyPrinter for PHP-Parser because it needs the
 * unmodified value for Scalar variables instead of an interpreted version.
 *
 * If the interpreted version was to be used then the XML interpretation would
 * fail because of special characters.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class PrettyPrinter extends Standard
{
    /**
     * Converts the string into it's original representation without converting
     * the special character combinations.
     *
     * This method is overridden from the original Zend Pretty Printer because
     * the original returns the strings as interpreted by PHP-Parser.
     * Since we do not want such conversions we take the original that is
     * injected by our own custom Lexer.
     *
     * @param String $node The node to return a string
     *     representation of.
     *
     * @see Lexer where the originalValue is injected.
     *
     * @return string
     */
    public function pScalar_String(String_ $node)
    {
        if (method_exists($this, 'pSafe')) {
            return $this->pSafe($node->getAttribute('originalValue'));
        }
        
        return $this->pNoIndent($node->getAttribute('originalValue'));
    }

}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\TraitUse;

/**
 * Provides static reflection for a class.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class ClassReflector extends InterfaceReflector
{
    /** @var Class_ */
    protected $node;

    /** @var string[] */
    protected $traits = array();

    public function parseSubElements()
    {
        /** @var TraitUse $stmt  */
        foreach ($this->node->stmts as $stmt) {
            if ($stmt instanceof TraitUse) {
                foreach ($stmt->traits as $trait) {
                    $this->traits[] = '\\' . (string) $trait;
                }
            }
        }

        parent::parseSubElements();
    }

    /**
     * Returns whether this is an abstract class.
     *
     * @return bool
     */
    public function isAbstract()
    {
        return (bool) ($this->node->type & Class_::MODIFIER_ABSTRACT);
    }

    /**
     * Returns whether this class is final and thus cannot be extended.
     *
     * @return bool
     */
    public function isFinal()
    {
        return (bool) ($this->node->type & Class_::MODIFIER_FINAL);
    }

    /**
     * Returns a list of the names of traits used in this class.
     *
     * @return string[]
     */
    public function getTraits()
    {
        return $this->traits;
    }

    public function getParentClass()
    {
        return isset($this->node->extends) ? '\\'.(string) $this->node->extends : '';
    }

    /**
     * BC Break: used to be getParentInterfaces
     *
     * @return string[] Names of interfaces the class implements.
     */
    public function getInterfaces()
    {
        $names = array();
        if (isset($this->node->implements)) {
            /** @var Name */
            foreach ($this->node->implements as $node) {
                $names[] = '\\'.(string) $node;
            }
        }

        return $names;
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Reflection;

/**
 * An exception specifically originating from the Reflection component.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Exception extends \Exception
{
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Parser\Event\LogEvent;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Context;
use phpDocumentor\Reflection\DocBlock\Location;
use phpDocumentor\Reflection\Event\PostDocBlockExtractionEvent;
use phpDocumentor\Reflection\Exception;
use PhpParser\Node\Stmt\ClassMethod;
use Psr\Log\LogLevel;
use PhpParser\Comment\Doc;
use PhpParser\Node;
use PhpParser\Node\Const_;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Include_;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\Const_ as ConstStmt;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\InlineHTML;
use PhpParser\Node\Stmt\Interface_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\PropertyProperty;
use PhpParser\Node\Stmt\Trait_;
use PhpParser\Node\Stmt\UseUse;
use PhpParser\NodeVisitor;

/**
 * Reflection class for a full file.
 *
 * @author    Mike van Riel 
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class FileReflector extends ReflectionAbstract implements NodeVisitor
{
    /** @var string An MD5 hashed representation of the contents of this file */
    protected $hash;

    /** @var string The contents of this file. */
    protected $contents = '';

    /** @var IncludeReflector[] */
    protected $includes = array();

    /** @var ConstantReflector[] */
    protected $constants = array();

    /** @var ClassReflector[] */
    protected $classes = array();

    /** @var TraitReflector[] */
    protected $traits = array();

    /** @var InterfaceReflector[] */
    protected $interfaces = array();

    /** @var FunctionReflector[] */
    protected $functions = array();

    /** @var string The name of the file associated with this reflection object. */
    protected $filename = '';

    /** @var DocBlock */
    protected $doc_block;

    /** @var string The package name that should be used if none is present in the file */
    protected $default_package_name = 'Default';

    /** @var string[] A list of markers contained in this file. */
    protected $markers = array();

    /** @var string[] A list of errors during processing */
    protected $parse_markers = array();

    /** @var string[] A list of all marker types to search for in this file. */
    protected $marker_terms = array('TODO', 'FIXME');

    /** @var Context */
    protected $context;

    /**
     * Opens the file and retrieves its contents.
     *
     * During construction the given file is checked whether it is readable and
     * if the $validate argument is true a PHP Lint action is executed to
     * check whether the there are no parse errors.
     *
     * By default the Lint check is disabled because of the performance hit
     * introduced by this action.
     *
     * If the validation checks out, the file's contents are read, converted to
     * UTF-8 and the object is created from those contents.
     *
     * @param string  $file     Name of the file.
     * @param boolean $validate Whether to check the file using PHP Lint.
     * @param string  $encoding The encoding of the file.
     *
     * @throws Exception\UnreadableFile If the filename is incorrect or
     *   the file cannot be opened
     * @throws Exception\UnparsableFile If the file fails PHP lint checking
     *   (this can only happen when $validate is set to true)
     */
    public function __construct($file, $validate = false, $encoding = 'utf-8')
    {
        if (!is_string($file) || (!is_readable($file))) {
            throw new Exception\UnreadableFile(
                'The given file should be a string, should exist on the filesystem and should be readable'
            );
        }

        if ($validate) {
            exec('php -l ' . escapeshellarg($file), $output, $result);
            if ($result != 0) {
                throw new Exception\UnparsableFile(
                    'The given file could not be interpreted as it contains errors: '
                    . implode(PHP_EOL, $output)
                );
            }
        }

        $this->filename = $file;
        $this->contents = file_get_contents($file);
        $this->context = new Context();

        if (strtolower($encoding) !== 'utf-8' && extension_loaded('iconv')) {
            $this->contents = iconv(
                strtolower($encoding),
                'utf-8//IGNORE//TRANSLIT',
                $this->contents
            );
        }

        // filemtime($file) is sometimes between 0.00001 and 0.00005 seconds
        // faster but md5 is more accurate. It can also result in false
        // positives or false negatives after copying or checking out a codebase.
        $this->hash = md5($this->contents);
    }

    public function process()
    {
        // with big fluent interfaces it can happen that PHP-Parser's Traverser
        // exceeds the 100 recursions limit; we set it to 10000 to be sure.
        ini_set('xdebug.max_nesting_level', 10000);

        $traverser = new Traverser();
        $traverser->addVisitor($this);
        $traverser->traverse($this->contents);

        $this->scanForMarkers();
    }

    /**
     * @return ClassReflector[]
     */
    public function getClasses()
    {
        return $this->classes;
    }

    /**
     * @return TraitReflector[]
     */
    public function getTraits()
    {
        return $this->traits;
    }

    /**
     * @return ConstantReflector[]
     */
    public function getConstants()
    {
        return $this->constants;
    }

    /**
     * @return FunctionReflector[]
     */
    public function getFunctions()
    {
        return $this->functions;
    }

    /**
     * @return IncludeReflector[]
     */
    public function getIncludes()
    {
        return $this->includes;
    }

    /**
     * @return InterfaceReflector[]
     */
    public function getInterfaces()
    {
        return $this->interfaces;
    }

    public function beforeTraverse(array $nodes)
    {
        $node = null;
        $key = 0;
        foreach ($nodes as $k => $n) {
            if (!$n instanceof InlineHTML) {
                $node = $n;
                $key = $k;
                break;
            }
        }

        if ($node) {
            $comments = (array) $node->getAttribute('comments');

            // remove non-DocBlock comments
            $comments = array_values(
                array_filter(
                    $comments,
                    function ($comment) {
                        return $comment instanceof Doc;
                    }
                )
            );

            if (!empty($comments)) {
                try {
                    $docblock = new DocBlock(
                        (string) $comments[0],
                        null,
                        new Location($comments[0]->getLine())
                    );

                    // the first DocBlock in a file documents the file if
                    // * it precedes another DocBlock or
                    // * it contains a @package tag and doesn't precede a class
                    //   declaration or
                    // * it precedes a non-documentable element (thus no include,
                    //   require, class, function, define, const)
                    if (count($comments) > 1
                        || (!$node instanceof Class_
                        && !$node instanceof Interface_
                        && $docblock->hasTag('package'))
                        || !$this->isNodeDocumentable($node)
                    ) {
                        $this->doc_block = $docblock;

                        // remove the file level DocBlock from the node's comments
                        array_shift($comments);
                    }
                } catch (\Exception $e) {
                    $this->log($e->getMessage(), LogLevel::CRITICAL);
                }
            }

            // always update the comments attribute so that standard comments
            // do not stop DocBlock from being attached to an element
            $node->setAttribute('comments', $comments);
            $nodes[$key] = $node;
        }

        if (class_exists('phpDocumentor\Event\Dispatcher')) {
            Dispatcher::getInstance()->dispatch(
                'reflection.docblock-extraction.post',
                PostDocBlockExtractionEvent
                ::createInstance($this)->setDocblock($this->doc_block)
            );
        }

        return $nodes;
    }

    /**
     * Checks whether the given node is recogized by phpDocumentor as a
     * documentable element.
     *
     * The following elements are recognized:
     *
     * - Trait
     * - Class
     * - Interface
     * - Class constant
     * - Class method
     * - Property
     * - Include/Require
     * - Constant, both const and define
     * - Function
     *
     * @param Node $node
     *
     * @return bool
     */
    protected function isNodeDocumentable(Node $node)
    {
        return ($node instanceof Class_)
            || ($node instanceof Interface_)
            || ($node instanceof ClassConst)
            || ($node instanceof ClassMethod)
            || ($node instanceof ConstStmt)
            || ($node instanceof Function_)
            || ($node instanceof Property)
            || ($node instanceof PropertyProperty)
            || ($node instanceof Trait_)
            || ($node instanceof Include_)
            || ($node instanceof FuncCall
            && ($node->name instanceof Name)
            && $node->name == 'define');
    }

    public function enterNode(Node $node)
    {
    }

    public function getName()
    {
        return $this->filename;
    }

    public function getFilename()
    {
        return $this->filename;
    }

    public function getHash()
    {
        return $this->hash;
    }

    public function getDocBlock()
    {
        return $this->doc_block;
    }

    public function getLineNumber()
    {
        return 0;
    }

    public function getDefaultPackageName()
    {
        return $this->default_package_name;
    }

    /**
     * Adds a marker to scan the contents of this file for.
     *
     * @param string $name The Marker term, e.g. FIXME or TODO.
     *
     * @return void
     */
    public function addMarker($name)
    {
        $this->marker_terms[] = $name;
    }

    /**
     * Sets a list of markers to search for.
     *
     * @param string[] $markers A list of marker terms to scan for.
     *
     * @see phpDocumentor\Reflection\FileReflector::addMarker()
     *
     * @return void
     */
    public function setMarkers(array $markers)
    {
        $this->marker_terms = array();

        foreach ($markers as $marker) {
            $this->addMarker($marker);
        }
    }

    public function getMarkers()
    {
        return $this->markers;
    }

    /**
     * Adds a parse error to the system
     *
     * @param LogEvent $data Contains the type,
     *     message, line and code element.
     *
     * @return void
     */
    public function addParserMarker($data)
    {
        $this->parse_markers[] = array(
            $data->getType(),
            $data->getMessage(),
            $data->getLine(),
            $data->getCode()
        );
    }

    /**
     * Scans the file for markers and records them in the markers property.
     *
     * @see getMarkers()
     *
     * @todo this method may incur a performance penalty while the AST also
     * contains the comments. This method should be replaced by a piece of
     * code that interprets the comments in the AST.
     * This has not been done since that may be an extensive refactoring (each
     * PhpParser\Node* contains a 'comments' attribute and must thus recursively
     * be discovered)
     *
     * @return void
     */
    public function scanForMarkers()
    {
        // find all markers, get the entire file and check for marker terms.
        $marker_data = array();
        foreach (explode("\n", $this->contents) as $line_number => $line) {
            preg_match_all(
                '~//[\s]*(' . implode('|', $this->marker_terms) . ')\:?[\s]*(.*)~',
                $line,
                $matches,
                PREG_SET_ORDER
            );
            foreach ($matches as &$match) {
                $match[3] = $line_number + 1;
            }
            $marker_data = array_merge($marker_data, $matches);
        }

        // store marker results and remove first entry (entire match),
        // this results in an array with 2 entries:
        // marker name and content
        $this->markers = $marker_data;
        foreach ($this->markers as &$marker) {
            array_shift($marker);
        }
    }

    public function getParseErrors()
    {
        return $this->parse_markers;
    }

    public function getNamespace()
    {
        return $this->context->getNamespace();
    }

    public function getNamespaceAliases()
    {
        return $this->context->getNamespaceAliases();
    }

    public function getContents()
    {
        return $this->contents;
    }

    public function setDefaultPackageName($default_package_name)
    {
        $this->default_package_name = $default_package_name;
    }

    public function setFilename($filename)
    {
        $this->filename = $filename;
    }

    public function leaveNode(Node $node)
    {
        $prettyPrinter = new PrettyPrinter;

        switch (get_class($node)) {
            case 'PhpParser\Node\Stmt\Use_':
                /** @var \PhpParser\Node\Stmt\UseUse $use */
                foreach ($node->uses as $use) {
                    $this->context->setNamespaceAlias(
                        $use->alias,
                        implode('\\', $use->name->parts)
                    );
                }
                break;
            case 'PhpParser\Node\Stmt\Namespace_':
                $this->context->setNamespace(
                    isset($node->name) && ($node->name) ? implode('\\', $node->name->parts) : ''
                );
                break;
            case 'PhpParser\Node\Stmt\Class_':
                $class = new ClassReflector($node, $this->context);
                $class->parseSubElements();
                $this->classes[] = $class;
                break;
            case 'PhpParser\Node\Stmt\Trait_':
                $trait = new TraitReflector($node, $this->context);
                $trait->parseSubElements();
                $this->traits[] = $trait;
                break;
            case 'PhpParser\Node\Stmt\Interface_':
                $interface = new InterfaceReflector($node, $this->context);
                $interface->parseSubElements();
                $this->interfaces[] = $interface;
                break;
            case 'PhpParser\Node\Stmt\Function_':
                $function = new FunctionReflector($node, $this->context);
                $this->functions[] = $function;
                break;
            case 'PhpParser\Node\Stmt\Const_':
                foreach ($node->consts as $constant) {
                    $reflector = new ConstantReflector(
                        $node,
                        $this->context,
                        $constant
                    );
                    $this->constants[] = $reflector;
                }
                break;
            case 'PhpParser\Node\Expr\FuncCall':
                if (($node->name instanceof Name)
                    && ($node->name == 'define')
                    && isset($node->args[0])
                    && isset($node->args[1])
                ) {
                    // transform the first argument of the define function call into a constant name
                    $name = str_replace(
                        array('\\\\', '"', "'"),
                        array('\\', '', ''),
                        trim($prettyPrinter->prettyPrintExpr($node->args[0]->value), '\'')
                    );
                    $nameParts = explode('\\', $name);
                    $shortName = end($nameParts);

                    $constant = new Const_($shortName, $node->args[1]->value, $node->getAttributes());
                    $constant->namespacedName = new Name($name);

                    $constant_statement = new ConstStmt(array($constant));
                    $constant_statement->setAttribute('comments', array($node->getDocComment()));
                    $this->constants[] = new ConstantReflector($constant_statement, $this->context, $constant);
                }
                break;
            case 'PhpParser\Node\Expr\Include_':
                $include = new IncludeReflector($node, $this->context);
                $this->includes[] = $include;
                break;
        }
    }

    public function afterTraverse(array $nodes)
    {
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use PhpParser\Error;
use PhpParser\NodeVisitor\NameResolver;
use PhpParser\Parser;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor;
use PhpParser\NodeVisitorAbstract;

/**
 * The source code traverser that scans the given source code and transforms
 * it into tokens.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Traverser
{
    /**
     * List of visitors to apply upon traversing.
     *
     * @see traverse()
     *
     * @var \PhpParser\NodeVisitorAbstract[]
     */
    public $visitors = array();

    /**
     * Traverses the given contents and builds an AST.
     *
     * @param string $contents The source code of the file that is to be scanned
     *
     * @return void
     */
    public function traverse($contents)
    {
        try {
            $this->createTraverser()->traverse(
                $this->createParser()->parse($contents)
            );
        } catch (Error $e) {
            echo 'Parse Error: ', $e->getMessage();
        }
    }

    /**
     * Adds a visitor object to the traversal process.
     *
     * With visitors it is possible to extend the traversal process and
     * modify the found tokens.
     *
     * @param \PhpParser\NodeVisitor $visitor
     *
     * @return void
     */
    public function addVisitor(\PhpParser\NodeVisitor $visitor)
    {
        $this->visitors[] = $visitor;
    }

    /**
     * Creates a parser object using our own Lexer.
     *
     * @return Parser
     */
    protected function createParser()
    {
        return new Parser(new Lexer());
    }

    /**
     * Creates a new traverser object and adds visitors.
     *
     * @return NodeTraverser
     */
    protected function createTraverser()
    {
        $node_traverser = new NodeTraverser();
        $node_traverser->addVisitor(new NameResolver());

        foreach ($this->visitors as $visitor) {
            $node_traverser->addVisitor($visitor);
        }

        return $node_traverser;
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use phpDocumentor\Reflection\BaseReflector;
use phpDocumentor\Reflection\DocBlock\Context;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Function_;

/**
 * Provides Static Reflection for functions.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class FunctionReflector extends BaseReflector
{
    /** @var \PhpParser\Node\Stmt\Function_ */
    protected $node;

    /** @var FunctionReflector\ArgumentReflector[] */
    protected $arguments = array();

    /**
     * Initializes the reflector using the function statement object of
     * PHP-Parser.
     *
     * @param \PhpParser\Node\Stmt $node    Function object coming from PHP-Parser.
     * @param Context             $context The context in which the node occurs.
     */
    public function __construct(\PhpParser\Node\Stmt $node, Context $context)
    {
        parent::__construct($node, $context);

        /** @var \PhpParser\Node\Param $param  */
        foreach ($node->params as $param) {
            $reflector = new FunctionReflector\ArgumentReflector(
                $param,
                $context
            );
            $this->arguments[$reflector->getName()] = $reflector;
        }
    }

    /**
     * Checks whether the function returns a value by reference.
     *
     * @return bool TRUE if the return value is by reference, FALSE otherwise.
     */
    public function isByRef()
    {
        return $this->node->byRef;
    }

    /**
     * Returns a list of Argument objects.
     *
     * @return FunctionReflector\ArgumentReflector[]
     */
    public function getArguments()
    {
        return $this->arguments;
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

class TraitReflector extends ClassReflector
{
    /** @var \PhpParser\Node\Stmt\Trait_ */
    protected $node;
}

 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use PhpParser\Lexer as BaseLexer;
use PhpParser\Parser;

/**
 * Custom lexer for phpDocumentor.
 *
 * phpDocumentor has a custom Lexer for PHP-Parser because it needs
 * unmodified value for Scalar variables instead of an interpreted version.
 *
 * If the interpreted version was to be used then the XML interpretation would
 * fail because of special characters.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Lexer extends BaseLexer
{
    /**
     * Retrieves the next token and determines the associated attributes and
     * returns the token id.
     *
     * @param string   $value
     * @param string[] $startAttributes
     * @param string[] $endAttributes
     *
     * @return int
     */
    public function getNextToken(
        &$value = null,
        &$startAttributes = null,
        &$endAttributes = null
    ) {
        $tokenId = parent::getNextToken($value, $startAttributes, $endAttributes);

        if ($this->isTokenScalar($tokenId)) {
            // store original value because the value itself will be interpreted
            // by PHP_Parser and we want the unformatted value
            $endAttributes['originalValue'] = $value;
        }

        return $tokenId;
    }

    /**
     * Returns whether the given token id is a scalar that will be interpreted
     * by PHP-Parser.
     *
     * @param int $tokenId The id to check, must match a \PhpParser_Parser::T_*
     *     constant.
     *
     * @return bool
     */
    protected function isTokenScalar($tokenId)
    {
        return $tokenId == Parser::T_CONSTANT_ENCAPSED_STRING
            || $tokenId == Parser::T_LNUMBER
            || $tokenId == Parser::T_DNUMBER;
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\ClassReflector;

use phpDocumentor\Reflection\BaseReflector;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Context;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\PropertyProperty;

class PropertyReflector extends BaseReflector
{
    /** @var Property */
    protected $property;

    /** @var PropertyProperty */
    protected $node;

    public function __construct(
        Property $property,
        Context $context,
        PropertyProperty $node
    ) {
        parent::__construct($node, $context);
        $this->property = $property;
    }

    public function getName()
    {
        return '$'.parent::getName();
    }

    /**
     * Returns the default value or null if none found.
     *
     * Please note that if the default value is null that this method returns
     * string 'null'.
     *
     * @return null|string
     */
    public function getDefault()
    {
        $result = null;
        if ($this->node->default) {
            $result = $this->getRepresentationOfValue($this->node->default);
        }

        return $result;
    }

    /**
     * Returns the visibility for this item.
     *
     * The returned value should match either of the following:
     *
     * * public
     * * protected
     * * private
     *
     * If a method has no visibility set in the class definition this method
     * will return 'public'.
     *
     * @return string
     */
    public function getVisibility()
    {
        if ($this->property->type & \PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED) {
            return 'protected';
        }
        if ($this->property->type & \PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE) {
            return 'private';
        }

        return 'public';
    }

    /**
     * Returns whether this property is static.
     *
     * @return bool
     */
    public function isStatic()
    {
        return (bool) ($this->property->type & \PhpParser\Node\Stmt\Class_::MODIFIER_STATIC);
    }

    /**
     * Returns the parsed DocBlock.
     *
     * @return DocBlock|null
     */
    public function getDocBlock()
    {
        return $this->extractDocBlock($this->property);
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\ClassReflector;

use phpDocumentor\Reflection\FunctionReflector;
use PhpParser\Node\Stmt\Class_;

class MethodReflector extends FunctionReflector
{
    /** @var \PhpParser\Node\Stmt\ClassMethod */
    protected $node;

    /**
     * Returns the visibility for this item.
     *
     * The returned value should match either of the following:
     *
     * * public
     * * protected
     * * private
     *
     * If a method has no visibility set in the class definition this method
     * will return 'public'.
     *
     * @return string
     */
    public function getVisibility()
    {
        if ($this->node->type & Class_::MODIFIER_PROTECTED) {
            return 'protected';
        }
        if ($this->node->type & Class_::MODIFIER_PRIVATE) {
            return 'private';
        }

        return 'public';
    }

    /**
     * Returns whether this method is static.
     *
     * @return bool
     */
    public function isAbstract()
    {
        return (bool) ($this->node->type & Class_::MODIFIER_ABSTRACT);
    }

    /**
     * Returns whether this method is static.
     *
     * @return bool
     */
    public function isStatic()
    {
        return (bool) ($this->node->type & Class_::MODIFIER_STATIC);
    }

    /**
     * Returns whether this method is final.
     *
     * @return bool
     */
    public function isFinal()
    {
        return (bool) ($this->node->type & Class_::MODIFIER_FINAL);
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\ClassReflector;

use phpDocumentor\Reflection\BaseReflector;
use phpDocumentor\Reflection\ConstantReflector as BaseConstantReflector;
use phpDocumentor\Reflection\DocBlock\Context;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Const_;

class ConstantReflector extends BaseConstantReflector
{
    /** @var ClassConst */
    protected $constant;

    /**
     * Registers the Constant Statement and Node with this reflector.
     *
     * @param ClassConst $stmt
     * @param Context $context
     * @param Const_ $node
     */
    public function __construct(
        ClassConst $stmt,
        Context $context,
        Const_ $node
    ) {
        BaseReflector::__construct($node, $context);
        $this->constant = $stmt;
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Context;
use PhpParser\Node\Const_;
use PhpParser\Node\Stmt\Const_ as ConstStmt;

/**
 * Provides Static Reflection for file-level constants.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class ConstantReflector extends BaseReflector
{
    /** @var ConstStmt */
    protected $constant;

    /** @var Const_ */
    protected $node;

    /**
     * Registers the Constant Statement and Node with this reflector.
     *
     * @param ConstStmt $stmt
     * @param Const_ $node
     */
    public function __construct(
        ConstStmt $stmt,
        Context $context,
        Const_ $node
    ) {
        parent::__construct($node, $context);
        $this->constant = $stmt;
    }

    /**
     * Returns the value contained in this Constant.
     *
     * @return string
     */
    public function getValue()
    {
        return $this->getRepresentationOfValue($this->node->value);
    }

    /**
     * Returns the parsed DocBlock.
     *
     * @return DocBlock|null
     */
    public function getDocBlock()
    {
        return $this->extractDocBlock($this->constant);
    }
}
docblock = $docblock;

        return $this;
    }

    /**
     * @return DocBlock|null
     */
    public function getDocblock()
    {
        return $this->docblock;
    }
}
xml;
    }

    /**
     * @return Tag|null
     */
    public function getObject()
    {
        return $this->object;
    }

    /**
     * @param Tag $object
     *
     * @return ExportDocBlockTagEvent
     */
    public function setObject(Tag $object = null)
    {
        $this->object = $object;

        return $this;
    }

    /**
     * @param DOMNode $xml
     *
     * @return ExportDocBlockTagEvent
     */
    public function setXml(DOMNode $xml = null)
    {
        $this->xml = $xml;

        return $this;
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\FunctionReflector;

use phpDocumentor\Reflection\BaseReflector;
use PhpParser\Node\Param;

class ArgumentReflector extends BaseReflector
{
    /** @var Param */
    protected $node;

    /**
     * Checks whether the argument is passed by reference.
     *
     * @return bool TRUE if the argument is by reference, FALSE otherwise.
     */
    public function isByRef()
    {
        return $this->node->byRef;
    }

    /**
     * Returns the default value or null is none is set.
     *
     * @return string|null
     */
    public function getDefault()
    {
        $result = null;
        if ($this->node->default) {
            $result = $this->getRepresentationOfValue($this->node->default);
        }

        return $result;
    }

    /**
     * Returns the typehint, or null if none is set.
     *
     * @return string|null
     */
    public function getType()
    {
        $type = (string) $this->node->type;

        // in case of the callable of array keyword; do not prefix with a \
        if ($type == 'callable' || $type == 'array'
            || $type == 'self' || $type == '$this'
        ) {
            return $type;
        }

        return $type ? '\\'.$type : '';
    }

    public function getName()
    {
        return '$'.parent::getName();
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Interface_;

class InterfaceReflector extends BaseReflector
{
    /** @var Interface_|\PhpParser\Node\Stmt\Class_ */
    protected $node;

    /**
     * @var ClassReflector\ConstantReflector[]
     */
    protected $constants = array();
    /**
     * @var ClassReflector\PropertyReflector[]
     */
    protected $properties = array();
    /**
     * @var ClassReflector\MethodReflector[]
     */
    protected $methods = array();

    public function parseSubElements()
    {
        foreach ($this->node->stmts as $stmt) {
            switch (get_class($stmt)) {
                case 'PhpParser\Node\Stmt\Property':
                    foreach ($stmt->props as $property) {
                        $this->properties[] = new ClassReflector\PropertyReflector(
                            $stmt,
                            $this->context,
                            $property
                        );
                    }
                    break;
                case 'PhpParser\Node\Stmt\ClassMethod':
                    $this->methods[strtolower($stmt->name)] = new ClassReflector\MethodReflector(
                        $stmt,
                        $this->context
                    );
                    break;
                case 'PhpParser\Node\Stmt\ClassConst':
                    foreach ($stmt->consts as $constant) {
                        $this->constants[] = new ClassReflector\ConstantReflector(
                            $stmt,
                            $this->context,
                            $constant
                        );
                    }
                    break;
            }
        }
    }

    public function getParentInterfaces()
    {
        $names = array();
        if ($this->node instanceof Interface_
            && $this->node->extends
        ) {
            /** @var Name */
            foreach ($this->node->extends as $node) {
                $names[] = '\\'.(string) $node;
            }
        }

        return $names;
    }

    /**
     * @return ClassReflector\ConstantReflector[]
     */
    public function getConstants()
    {
        return $this->constants;
    }

    /**
     * @return ClassReflector\PropertyReflector[]
     */
    public function getProperties()
    {
        return $this->properties;
    }

    /**
     * @return ClassReflector\MethodReflector[]
     */
    public function getMethods()
    {
        return $this->methods;
    }

    /**
     * @param string $name the method name
     * @return ClassReflector\MethodReflector|null
     */
    public function getMethod($name)
    {
        $name = strtolower($name);

        return isset($this->methods[$name]) ? $this->methods[$name] : null;
    }
}

 * @copyright 2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use phpDocumentor\Event\DebugEvent;
use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Event\LogEvent;

/**
 * Provides basic event logging and dispatching for every reflection class.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
abstract class ReflectionAbstract
{
    /**
     * The context (namespace, aliases) for the reflection.
     *
     * @var \phpDocumentor\Reflection\DocBlock\Context
     */
    protected $context = null;

    /**
     * Dispatches a logging request.
     *
     * @param string $message  The message to log.
     * @param int    $priority The logging priority, the lower,
     *  the more important. Ranges from 1 to 7
     *
     * @return void
     */
    public function log($message, $priority = 6)
    {
        if (class_exists('phpDocumentor\Event\Dispatcher')) {
            Dispatcher::getInstance()->dispatch(
                'system.log',
                LogEvent::createInstance($this)
                ->setMessage($message)->setPriority($priority)
            );
        }
    }

    /**
     * Dispatches a logging request to log a debug message.
     *
     * @param string $message The message to log.
     *
     * @return void
     */
    public function debug($message)
    {
        if (class_exists('phpDocumentor\Event\Dispatcher')) {
            Dispatcher::getInstance()->dispatch(
                'system.debug',
                DebugEvent::createInstance($this)
                ->setMessage($message)
            );
        }
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\Exception;

/**
 * Exception representing any situation where the file is not parsable.
 *
 * @author    Mike van Riel 
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class UnparsableFile extends \phpDocumentor\Reflection\Exception
{
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\Exception;

/**
 * Exception representing any error in the Reflection library due to a file not
 * being readable or accessible.
 *
 * @author    Mike van Riel 
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class UnreadableFile extends \phpDocumentor\Reflection\Exception
{
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use Exception;
use PhpParser\Node\Expr\Include_;

class IncludeReflector extends BaseReflector
{
    /** @var Include_ */
    protected $node;

    /**
     * Returns the type of this include.
     *
     * Valid types are:
     * - Include
     * - Include Once
     * - Require
     * - Require Once
     *
     * @throws Exception if the include is of an unknown type
     *
     * @return string
     */
    public function getType()
    {
        switch ($this->node->type) {
            case Include_::TYPE_INCLUDE:
                return 'Include';
            case Include_::TYPE_INCLUDE_ONCE:
                return 'Include Once';
            case Include_::TYPE_REQUIRE:
                return 'Require';
            case Include_::TYPE_REQUIRE_ONCE:
                return 'Require Once';
            default:
                throw new Exception(
                    'Unknown include type detected: '.$this->node->type
                );
        }
    }

    public function getShortName()
    {
        return (string) $this->node->expr->value;
    }
}

 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use Exception;
use InvalidArgumentException;
use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Context;
use phpDocumentor\Reflection\DocBlock\Location;
use phpDocumentor\Reflection\Event\PostDocBlockExtractionEvent;
use PhpParser\NodeAbstract;
use Psr\Log\LogLevel;
use PhpParser\Node\Expr;
use PhpParser\Node\Stmt;
use PhpParser\PrettyPrinterAbstract;

/**
 * Basic reflection providing support for events and basic properties as a
 * DocBlock and names.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
abstract class BaseReflector extends ReflectionAbstract
{
    /** @var \PhpParser\Node\Stmt */
    protected $node;

    /**
     * The package name that is passed on by the parent Reflector.
     *
     * May be overwritten and should be passed on to children supporting
     * packages.
     *
     * @var string
     */
    protected $default_package_name = '';

    /**
     * PHP AST pretty printer used to get representations of values.
     *
     * @var \PhpParser\PrettyPrinterAbstract
     */
    protected static $prettyPrinter = null;

    /**
     * Initializes this reflector with the correct node as produced by
     * PHP-Parser.
     *
     * @param NodeAbstract $node
     * @param Context                $context
     *
     * @link http://github.com/nikic/PHP-Parser
     */
    public function __construct(NodeAbstract $node, Context $context)
    {
        $this->node = $node;
        $context->setLSEN($this->getLSEN());
        $this->context = $context;
    }

    /**
     * Returns the current PHP-Parser node that holds more detailed information
     * about the reflected object. e.g. position in the file and further attributes.
     * @return \PhpParser\Node\Stmt|\PhpParser\NodeAbstract
     */
    public function getNode()
    {
        return $this->node;
    }

    /**
     * Sets the name for the namespace.
     *
     * @param string $namespace
     *
     * @throws InvalidArgumentException if something other than a string is
     *     passed.
     *
     * @return void
     */
    public function setNamespace($namespace)
    {
        if (!is_string($namespace)) {
            throw new InvalidArgumentException(
                'Expected a string for the namespace'
            );
        }

        $this->context->setNamespace($namespace);
    }

    /**
     * Returns the parsed DocBlock.
     *
     * @return DocBlock|null
     */
    public function getDocBlock()
    {
        return $this->extractDocBlock($this->node);
    }

    /**
     * Extracts a parsed DocBlock from an object.
     *
     * @param object $node Any object with a "getDocComment()" method.
     *
     * @return DocBlock|null
     */
    protected function extractDocBlock($node)
    {
        $doc_block = null;
        $comment = $node->getDocComment();
        if ($comment) {
            try {
                $doc_block = new DocBlock(
                    (string) $comment,
                    $this->context,
                    new Location($comment->getLine())
                );
            } catch (Exception $e) {
                $this->log($e->getMessage(), LogLevel::CRITICAL);
            }
        }

        if (class_exists('phpDocumentor\Event\Dispatcher')) {
            Dispatcher::getInstance()->dispatch(
                'reflection.docblock-extraction.post',
                PostDocBlockExtractionEvent
                ::createInstance($this)->setDocblock($doc_block)
            );
        }

        return $doc_block;
    }

    /**
     * Returns the name for this Reflector instance.
     *
     * @return string
     */
    public function getName()
    {
        if (isset($this->node->namespacedName)) {
            return '\\'.implode('\\', $this->node->namespacedName->parts);
        }

        return $this->getShortName();
    }

    /**
     * Returns the last component of a namespaced name as a short form.
     *
     * @return string
     */
    public function getShortName()
    {
        return isset($this->node->name)
            ? $this->node->name
            : (string) $this->node;
    }

    /**
     * Gets the LSEN.
     *
     * Returns this element's Local Structural Element Name (LSEN). This name
     * consistents of the element's short name, along with punctuation that
     * hints at the kind of structural element. If the structural element is
     * part of a type (i.e. an interface/trait/class' property/method/constant),
     * it also contains the name of the owning type.
     *
     * @return string
     */
    public function getLSEN()
    {
        return '';
    }

    /**
     * Returns the namespace name for this object.
     *
     * If this object does not have a namespace then the word 'global' is
     * returned to indicate a global namespace.
     *
     * @return string
     */
    public function getNamespace()
    {
        if (!isset($this->node->namespacedName)) {
            return $this->context->getNamespace();
        }

        $parts = $this->node->namespacedName->parts;
        array_pop($parts);

        $namespace = implode('\\', $parts);

        return $namespace ? $namespace : 'global';
    }

    /**
     * Returns a listing of namespace aliases where the key represents the alias
     * and the value the Fully Qualified Namespace Name.
     *
     * @return string[]
     */
    public function getNamespaceAliases()
    {
        return $this->context->getNamespaceAliases();
    }

    /**
     * Sets a listing of namespace aliases.
     *
     * The keys represents the alias name and the value the
     * Fully Qualified Namespace Name (FQNN).
     *
     * @param string[] $aliases
     *
     * @return void
     */
    public function setNamespaceAliases(array $aliases)
    {
        $this->context->setNamespaceAliases($aliases);
    }

    /**
     * Sets the Fully Qualified Namespace Name (FQNN) for an alias.
     *
     * @param string $alias
     * @param string $fqnn
     *
     * @return void
     */
    public function setNamespaceAlias($alias, $fqnn)
    {
        $this->context->setNamespaceAlias($alias, $fqnn);
    }

    /**
     * Returns the line number where this object starts.
     *
     * @return int
     */
    public function getLinenumber()
    {
        return $this->node->getLine();
    }

    /**
     * Sets the default package name for this object.
     *
     * If the DocBlock contains a different package name then that overrides
     * this package name.
     *
     * @param string $default_package_name The name of the package as defined
     *     in the PHPDoc Standard.
     *
     * @return void
     */
    public function setDefaultPackageName($default_package_name)
    {
        $this->default_package_name = $default_package_name;
    }

    /**
     * Returns the package name that is default for this element.
     *
     * This value may change after the DocBlock is interpreted. If that contains
     * a package tag then that tag overrides the Default package name.
     *
     * @return string
     */
    public function getDefaultPackageName()
    {
        return $this->default_package_name;
    }

    /**
     * Returns a simple human readable output for a value.
     *
     * @param \PhpParser\Node\Expr $value The value node as provided by
     *     PHP-Parser.
     *
     * @return string
     */
    protected function getRepresentationOfValue(
        \PhpParser\Node\Expr $value = null
    ) {
        if (null === $value) {
            return '';
        }

        if (!self::$prettyPrinter) {
            self::$prettyPrinter = new PrettyPrinter();
        }

        return self::$prettyPrinter->prettyPrintExpr($value);
    }
}

 * @copyright 2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock;

use phpDocumentor\Reflection\DocBlock;

/**
 * Serializes a DocBlock instance.
 *
 * @author  Barry vd. Heuvel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Serializer
{

    /** @var string The string to indent the comment with. */
    protected $indentString = ' ';

    /** @var int The number of times the indent string is repeated. */
    protected $indent = 0;

    /** @var bool Whether to indent the first line. */
    protected $isFirstLineIndented = true;

    /** @var int|null The max length of a line. */
    protected $lineLength = null;

    /**
     * Create a Serializer instance.
     *
     * @param int      $indent          The number of times the indent string is
     *     repeated.
     * @param string   $indentString    The string to indent the comment with.
     * @param bool     $indentFirstLine Whether to indent the first line.
     * @param int|null $lineLength      The max length of a line or NULL to
     *     disable line wrapping.
     */
    public function __construct(
        $indent = 0,
        $indentString = ' ',
        $indentFirstLine = true,
        $lineLength = null
    ) {
        $this->setIndentationString($indentString);
        $this->setIndent($indent);
        $this->setIsFirstLineIndented($indentFirstLine);
        $this->setLineLength($lineLength);
    }

    /**
     * Sets the string to indent comments with.
     * 
     * @param string $indentationString The string to indent comments with.
     * 
     * @return $this This serializer object.
     */
    public function setIndentationString($indentString)
    {
        $this->indentString = (string)$indentString;
        return $this;
    }

    /**
     * Gets the string to indent comments with.
     * 
     * @return string The indent string.
     */
    public function getIndentationString()
    {
        return $this->indentString;
    }

    /**
     * Sets the number of indents.
     * 
     * @param int $indent The number of times the indent string is repeated.
     * 
     * @return $this This serializer object.
     */
    public function setIndent($indent)
    {
        $this->indent = (int)$indent;
        return $this;
    }

    /**
     * Gets the number of indents.
     * 
     * @return int The number of times the indent string is repeated.
     */
    public function getIndent()
    {
        return $this->indent;
    }

    /**
     * Sets whether or not the first line should be indented.
     * 
     * Sets whether or not the first line (the one with the "/**") should be
     * indented.
     * 
     * @param bool $indentFirstLine The new value for this setting.
     * 
     * @return $this This serializer object.
     */
    public function setIsFirstLineIndented($indentFirstLine)
    {
        $this->isFirstLineIndented = (bool)$indentFirstLine;
        return $this;
    }

    /**
     * Gets whether or not the first line should be indented.
     * 
     * @return bool Whether or not the first line should be indented.
     */
    public function isFirstLineIndented()
    {
        return $this->isFirstLineIndented;
    }

    /**
     * Sets the line length.
     * 
     * Sets the length of each line in the serialization. Content will be
     * wrapped within this limit.
     * 
     * @param int|null $lineLength The length of each line. NULL to disable line
     *     wrapping altogether.
     * 
     * @return $this This serializer object.
     */
    public function setLineLength($lineLength)
    {
        $this->lineLength = null === $lineLength ? null : (int)$lineLength;
        return $this;
    }

    /**
     * Gets the line length.
     * 
     * @return int|null The length of each line or NULL if line wrapping is
     *     disabled.
     */
    public function getLineLength()
    {
        return $this->lineLength;
    }

    /**
     * Generate a DocBlock comment.
     *
     * @param DocBlock The DocBlock to serialize.
     * 
     * @return string The serialized doc block.
     */
    public function getDocComment(DocBlock $docblock)
    {
        $indent = str_repeat($this->indentString, $this->indent);
        $firstIndent = $this->isFirstLineIndented ? $indent : '';

        $text = $docblock->getText();
        if ($this->lineLength) {
            //3 === strlen(' * ')
            $wrapLength = $this->lineLength - strlen($indent) - 3;
            $text = wordwrap($text, $wrapLength);
        }
        $text = str_replace("\n", "\n{$indent} * ", $text);

        $comment = "{$firstIndent}/**\n{$indent} * {$text}\n{$indent} *\n";

        /** @var Tag $tag */
        foreach ($docblock->getTags() as $tag) {
            $tagText = (string) $tag;
            if ($this->lineLength) {
                $tagText = wordwrap($tagText, $wrapLength);
            }
            $tagText = str_replace("\n", "\n{$indent} * ", $tagText);

            $comment .= "{$indent} * {$tagText}\n";
        }

        $comment .= $indent . ' */';

        return $comment;
    }
}

 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock;

use phpDocumentor\Reflection\DocBlock;

/**
 * Parses a Description of a DocBlock or tag.
 *
 * @author  Mike van Riel 
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Description implements \Reflector
{
    /** @var string */
    protected $contents = '';

    /** @var array The contents, as an array of strings and Tag objects. */
    protected $parsedContents = null;

    /** @var DocBlock The DocBlock which this description belongs to. */
    protected $docblock = null;

    /**
     * Populates the fields of a description.
     *
     * @param string   $content  The description's conetnts.
     * @param DocBlock $docblock The DocBlock which this description belongs to.
     */
    public function __construct($content, DocBlock $docblock = null)
    {
        $this->setContent($content)->setDocBlock($docblock);
    }

    /**
     * Gets the text of this description.
     *
     * @return string
     */
    public function getContents()
    {
        return $this->contents;
    }

    /**
     * Sets the text of this description.
     *
     * @param string $content The new text of this description.
     *
     * @return $this
     */
    public function setContent($content)
    {
        $this->contents = trim($content);

        $this->parsedContents = null;
        return $this;
    }

    /**
     * Returns the parsed text of this description.
     *
     * @return array An array of strings and tag objects, in the order they
     *     occur within the description.
     */
    public function getParsedContents()
    {
        if (null === $this->parsedContents) {
            $this->parsedContents = preg_split(
                '/\{
                    # "{@}" is not a valid inline tag. This ensures that
                    # we do not treat it as one, but treat it literally.
                    (?!@\})
                    # We want to capture the whole tag line, but without the
                    # inline tag delimiters.
                    (\@
                        # Match everything up to the next delimiter.
                        [^{}]*
                        # Nested inline tag content should not be captured, or
                        # it will appear in the result separately.
                        (?:
                            # Match nested inline tags.
                            (?:
                                # Because we did not catch the tag delimiters
                                # earlier, we must be explicit with them here.
                                # Notice that this also matches "{}", as a way
                                # to later introduce it as an escape sequence.
                                \{(?1)?\}
                                |
                                # Make sure we match hanging "{".
                                \{
                            )
                            # Match content after the nested inline tag.
                            [^{}]*
                        )* # If there are more inline tags, match them as well.
                           # We use "*" since there may not be any nested inline
                           # tags.
                    )
                \}/Sux',
                $this->contents,
                null,
                PREG_SPLIT_DELIM_CAPTURE
            );

            $count = count($this->parsedContents);
            for ($i=1; $i<$count; $i += 2) {
                $this->parsedContents[$i] = Tag::createInstance(
                    $this->parsedContents[$i],
                    $this->docblock
                );
            }

            //In order to allow "literal" inline tags, the otherwise invalid
            //sequence "{@}" is changed to "@", and "{}" is changed to "}".
            //See unit tests for examples.
            for ($i=0; $i<$count; $i += 2) {
                $this->parsedContents[$i] = str_replace(
                    array('{@}', '{}'),
                    array('@', '}'),
                    $this->parsedContents[$i]
                );
            }
        }
        return $this->parsedContents;
    }

    /**
     * Return a formatted variant of the Long Description using MarkDown.
     *
     * @todo this should become a more intelligent piece of code where the
     *     configuration contains a setting what format long descriptions are.
     *
     * @codeCoverageIgnore Will be removed soon, in favor of adapters at
     *     PhpDocumentor itself that will process text in various formats.
     *
     * @return string
     */
    public function getFormattedContents()
    {
        $result = $this->contents;

        // if the long description contains a plain HTML  element, surround
        // it with a pre element. Please note that we explicitly used str_replace
        // and not preg_replace to gain performance
        if (strpos($result, '') !== false) {
            $result = str_replace(
                array('', "\r\n", "\n", "\r", ''),
                array('
', '', '', '', '
'), $result ); } if (class_exists('Parsedown')) { $markdown = \Parsedown::instance(); $result = $markdown->parse($result); } elseif (class_exists('dflydev\markdown\MarkdownExtraParser')) { $markdown = new \dflydev\markdown\MarkdownExtraParser(); $result = $markdown->transformMarkdown($result); } return trim($result); } /** * Gets the docblock this tag belongs to. * * @return DocBlock The docblock this description belongs to. */ public function getDocBlock() { return $this->docblock; } /** * Sets the docblock this tag belongs to. * * @param DocBlock $docblock The new docblock this description belongs to. * Setting NULL removes any association. * * @return $this */ public function setDocBlock(DocBlock $docblock = null) { $this->docblock = $docblock; return $this; } /** * Builds a string representation of this object. * * @todo determine the exact format as used by PHP Reflection * and implement it. * * @return void * @codeCoverageIgnore Not yet implemented */ public static function export() { throw new \Exception('Not yet implemented'); } /** * Returns the long description as a string. * * @return string */ public function __toString() { return $this->getContents(); } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; /** * The context in which a DocBlock occurs. * * @author Vasil Rangelov * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class Context { /** @var string The current namespace. */ protected $namespace = ''; /** @var array List of namespace aliases => Fully Qualified Namespace. */ protected $namespace_aliases = array(); /** @var string Name of the structural element, within the namespace. */ protected $lsen = ''; /** * Cteates a new context. * @param string $namespace The namespace where this DocBlock * resides in. * @param array $namespace_aliases List of namespace aliases => Fully * Qualified Namespace. * @param string $lsen Name of the structural element, within * the namespace. */ public function __construct( $namespace = '', array $namespace_aliases = array(), $lsen = '' ) { if (!empty($namespace)) { $this->setNamespace($namespace); } $this->setNamespaceAliases($namespace_aliases); $this->setLSEN($lsen); } /** * @return string The namespace where this DocBlock resides in. */ public function getNamespace() { return $this->namespace; } /** * @return array List of namespace aliases => Fully Qualified Namespace. */ public function getNamespaceAliases() { return $this->namespace_aliases; } /** * Returns the Local Structural Element Name. * * @return string Name of the structural element, within the namespace. */ public function getLSEN() { return $this->lsen; } /** * Sets a new namespace. * * Sets a new namespace for the context. Leading and trailing slashes are * trimmed, and the keywords "global" and "default" are treated as aliases * to no namespace. * * @param string $namespace The new namespace to set. * * @return $this */ public function setNamespace($namespace) { if ('global' !== $namespace && 'default' !== $namespace ) { // Srip leading and trailing slash $this->namespace = trim((string)$namespace, '\\'); } else { $this->namespace = ''; } return $this; } /** * Sets the namespace aliases, replacing all previous ones. * * @param array $namespace_aliases List of namespace aliases => Fully * Qualified Namespace. * * @return $this */ public function setNamespaceAliases(array $namespace_aliases) { $this->namespace_aliases = array(); foreach ($namespace_aliases as $alias => $fqnn) { $this->setNamespaceAlias($alias, $fqnn); } return $this; } /** * Adds a namespace alias to the context. * * @param string $alias The alias name (the part after "as", or the last * part of the Fully Qualified Namespace Name) to add. * @param string $fqnn The Fully Qualified Namespace Name for this alias. * Any form of leading/trailing slashes are accepted, but what will be * stored is a name, prefixed with a slash, and no trailing slash. * * @return $this */ public function setNamespaceAlias($alias, $fqnn) { $this->namespace_aliases[$alias] = '\\' . trim((string)$fqnn, '\\'); return $this; } /** * Sets a new Local Structural Element Name. * * Sets a new Local Structural Element Name. A local name also contains * punctuation determining the kind of structural element (e.g. trailing "(" * and ")" for functions and methods). * * @param string $lsen The new local name of a structural element. * * @return $this */ public function setLSEN($lsen) { $this->lsen = (string)$lsen; return $this; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @property-write tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class PropertyWriteTag extends PropertyTag { } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @param tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class ParamTag extends ReturnTag { /** @var string */ protected $variableName = ''; /** @var bool determines whether this is a variadic argument */ protected $isVariadic = false; /** * {@inheritdoc} */ public function getContent() { if (null === $this->content) { $this->content = "{$this->type} {$this->variableName} {$this->description}"; } return $this->content; } /** * {@inheritdoc} */ public function setContent($content) { Tag::setContent($content); $parts = preg_split( '/(\s+)/Su', $this->description, 3, PREG_SPLIT_DELIM_CAPTURE ); // if the first item that is encountered is not a variable; it is a type if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$') ) { $this->type = array_shift($parts); array_shift($parts); } // if the next item starts with a $ or ...$ it must be the variable name if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] == '$' || substr($parts[0], 0, 4) === '...$') ) { $this->variableName = array_shift($parts); array_shift($parts); if (substr($this->variableName, 0, 3) === '...') { $this->isVariadic = true; $this->variableName = substr($this->variableName, 3); } } $this->setDescription(implode('', $parts)); $this->content = $content; return $this; } /** * Returns the variable's name. * * @return string */ public function getVariableName() { return $this->variableName; } /** * Sets the variable's name. * * @param string $name The new name for this variable. * * @return $this */ public function setVariableName($name) { $this->variableName = $name; $this->content = null; return $this; } /** * Returns whether this tag is variadic. * * @return boolean */ public function isVariadic() { return $this->isVariadic; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @property-read tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class PropertyReadTag extends PropertyTag { } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @property tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class PropertyTag extends ParamTag { } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @uses tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class UsesTag extends SeeTag { } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @see tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class SeeTag extends Tag { /** @var string */ protected $refers = null; /** * {@inheritdoc} */ public function getContent() { if (null === $this->content) { $this->content = "{$this->refers} {$this->description}"; } return $this->content; } /** * {@inheritdoc} */ public function setContent($content) { parent::setContent($content); $parts = preg_split('/\s+/Su', $this->description, 2); // any output is considered a type $this->refers = $parts[0]; $this->setDescription(isset($parts[1]) ? $parts[1] : ''); $this->content = $content; return $this; } /** * Gets the structural element this tag refers to. * * @return string */ public function getReference() { return $this->refers; } /** * Sets the structural element this tag refers to. * * @param string $refers The new type this tag refers to. * * @return $this */ public function setReference($refers) { $this->refers = $refers; $this->content = null; return $this; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag\VersionTag; /** * Reflection class for a @deprecated tag in a Docblock. * * @author Vasil Rangelov * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class DeprecatedTag extends VersionTag { } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @link tag in a Docblock. * * @author Ben Selby * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class LinkTag extends Tag { /** @var string */ protected $link = ''; /** * {@inheritdoc} */ public function getContent() { if (null === $this->content) { $this->content = "{$this->link} {$this->description}"; } return $this->content; } /** * {@inheritdoc} */ public function setContent($content) { parent::setContent($content); $parts = preg_split('/\s+/Su', $this->description, 2); $this->link = $parts[0]; $this->setDescription(isset($parts[1]) ? $parts[1] : $parts[0]); $this->content = $content; return $this; } /** * Gets the link * * @return string */ public function getLink() { return $this->link; } /** * Sets the link * * @param string $link The link * * @return $this */ public function setLink($link) { $this->link = $link; $this->content = null; return $this; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Type\Collection; /** * Reflection class for a @return tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class ReturnTag extends Tag { /** @var string The raw type component. */ protected $type = ''; /** @var Collection The parsed type component. */ protected $types = null; /** * {@inheritdoc} */ public function getContent() { if (null === $this->content) { $this->content = "{$this->type} {$this->description}"; } return $this->content; } /** * {@inheritdoc} */ public function setContent($content) { parent::setContent($content); $parts = preg_split('/\s+/Su', $this->description, 2); // any output is considered a type $this->type = $parts[0]; $this->types = null; $this->setDescription(isset($parts[1]) ? $parts[1] : ''); $this->content = $content; return $this; } /** * Returns the unique types of the variable. * * @return string[] */ public function getTypes() { return $this->getTypesCollection()->getArrayCopy(); } /** * Returns the type section of the variable. * * @return string */ public function getType() { return (string) $this->getTypesCollection(); } /** * Returns the type collection. * * @return void */ protected function getTypesCollection() { if (null === $this->types) { $this->types = new Collection( array($this->type), $this->docblock ? $this->docblock->getContext() : null ); } return $this->types; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @method in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class MethodTag extends ReturnTag { /** @var string */ protected $method_name = ''; /** @var string */ protected $arguments = ''; /** @var bool */ protected $isStatic = false; /** * {@inheritdoc} */ public function getContent() { if (null === $this->content) { $this->content = ''; if ($this->isStatic) { $this->content .= 'static '; } $this->content .= $this->type . " {$this->method_name}({$this->arguments}) " . $this->description; } return $this->content; } /** * {@inheritdoc} */ public function setContent($content) { Tag::setContent($content); // 1. none or more whitespace // 2. optionally the keyword "static" followed by whitespace // 3. optionally a word with underscores followed by whitespace : as // type for the return value // 4. then optionally a word with underscores followed by () and // whitespace : as method name as used by phpDocumentor // 5. then a word with underscores, followed by ( and any character // until a ) and whitespace : as method name with signature // 6. any remaining text : as description if (preg_match( '/^ # Static keyword # Declates a static method ONLY if type is also present (?: (static) \s+ )? # Return type (?: ([\w\|_\\\\]+) \s+ )? # Legacy method name (not captured) (?: [\w_]+\(\)\s+ )? # Method name ([\w\|_\\\\]+) # Arguments \(([^\)]*)\) \s* # Description (.*) $/sux', $this->description, $matches )) { list( , $static, $this->type, $this->method_name, $this->arguments, $this->description ) = $matches; if ($static) { if (!$this->type) { $this->type = 'static'; } else { $this->isStatic = true; } } else { if (!$this->type) { $this->type = 'void'; } } $this->parsedDescription = null; } return $this; } /** * Sets the name of this method. * * @param string $method_name The name of the method. * * @return $this */ public function setMethodName($method_name) { $this->method_name = $method_name; $this->content = null; return $this; } /** * Retrieves the method name. * * @return string */ public function getMethodName() { return $this->method_name; } /** * Sets the arguments for this method. * * @param string $arguments A comma-separated arguments line. * * @return void */ public function setArguments($arguments) { $this->arguments = $arguments; $this->content = null; return $this; } /** * Returns an array containing each argument as array of type and name. * * Please note that the argument sub-array may only contain 1 element if no * type was specified. * * @return string[] */ public function getArguments() { if (empty($this->arguments)) { return array(); } $arguments = explode(',', $this->arguments); foreach ($arguments as $key => $value) { $arguments[$key] = explode(' ', trim($value)); } return $arguments; } /** * Checks whether the method tag describes a static method or not. * * @return bool TRUE if the method declaration is for a static method, FALSE * otherwise. */ public function isStatic() { return $this->isStatic; } /** * Sets a new value for whether the method is static or not. * * @param bool $isStatic The new value to set. * * @return $this */ public function setIsStatic($isStatic) { $this->isStatic = $isStatic; $this->content = null; return $this; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @source tag in a Docblock. * * @author Vasil Rangelov * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class SourceTag extends Tag { /** * @var int The starting line, relative to the structural element's * location. */ protected $startingLine = 1; /** * @var int|null The number of lines, relative to the starting line. NULL * means "to the end". */ protected $lineCount = null; /** * {@inheritdoc} */ public function getContent() { if (null === $this->content) { $this->content = "{$this->startingLine} {$this->lineCount} {$this->description}"; } return $this->content; } /** * {@inheritdoc} */ public function setContent($content) { parent::setContent($content); if (preg_match( '/^ # Starting line ([1-9]\d*) \s* # Number of lines (?: ((?1)) \s+ )? # Description (.*) $/sux', $this->description, $matches )) { $this->startingLine = (int)$matches[1]; if (isset($matches[2]) && '' !== $matches[2]) { $this->lineCount = (int)$matches[2]; } $this->setDescription($matches[3]); $this->content = $content; } return $this; } /** * Gets the starting line. * * @return int The starting line, relative to the structural element's * location. */ public function getStartingLine() { return $this->startingLine; } /** * Sets the starting line. * * @param int $startingLine The new starting line, relative to the * structural element's location. * * @return $this */ public function setStartingLine($startingLine) { $this->startingLine = $startingLine; $this->content = null; return $this; } /** * Returns the number of lines. * * @return int|null The number of lines, relative to the starting line. NULL * means "to the end". */ public function getLineCount() { return $this->lineCount; } /** * Sets the number of lines. * * @param int|null $lineCount The new number of lines, relative to the * starting line. NULL means "to the end". * * @return $this */ public function setLineCount($lineCount) { $this->lineCount = $lineCount; $this->content = null; return $this; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @covers tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class CoversTag extends SeeTag { } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @var tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class VarTag extends ParamTag { } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @example tag in a Docblock. * * @author Vasil Rangelov * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class ExampleTag extends SourceTag { /** * @var string Path to a file to use as an example. * May also be an absolute URI. */ protected $filePath = ''; /** * @var bool Whether the file path component represents an URI. * This determines how the file portion appears at {@link getContent()}. */ protected $isURI = false; /** * {@inheritdoc} */ public function getContent() { if (null === $this->content) { $filePath = ''; if ($this->isURI) { if (false === strpos($this->filePath, ':')) { $filePath = str_replace( '%2F', '/', rawurlencode($this->filePath) ); } else { $filePath = $this->filePath; } } else { $filePath = '"' . $this->filePath . '"'; } $this->content = $filePath . ' ' . parent::getContent(); } return $this->content; } /** * {@inheritdoc} */ public function setContent($content) { Tag::setContent($content); if (preg_match( '/^ # File component (?: # File path in quotes \"([^\"]+)\" | # File URI (\S+) ) # Remaining content (parsed by SourceTag) (?:\s+(.*))? $/sux', $this->description, $matches )) { if ('' !== $matches[1]) { $this->setFilePath($matches[1]); } else { $this->setFileURI($matches[2]); } if (isset($matches[3])) { parent::setContent($matches[3]); } else { $this->setDescription(''); } $this->content = $content; } return $this; } /** * Returns the file path. * * @return string Path to a file to use as an example. * May also be an absolute URI. */ public function getFilePath() { return $this->filePath; } /** * Sets the file path. * * @param string $filePath The new file path to use for the example. * * @return $this */ public function setFilePath($filePath) { $this->isURI = false; $this->filePath = trim($filePath); $this->content = null; return $this; } /** * Sets the file path as an URI. * * This function is equivalent to {@link setFilePath()}, except that it * convers an URI to a file path before that. * * There is no getFileURI(), as {@link getFilePath()} is compatible. * * @param type $uri The new file URI to use as an example. */ public function setFileURI($uri) { $this->isURI = true; if (false === strpos($uri, ':')) { //Relative URL $this->filePath = rawurldecode( str_replace(array('/', '\\'), '%2F', $uri) ); } else { //Absolute URL or URI. $this->filePath = $uri; } $this->content = null; return $this; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @version tag in a Docblock. * * @author Vasil Rangelov * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class VersionTag extends Tag { /** * PCRE regular expression matching a version vector. * Assumes the "x" modifier. */ const REGEX_VECTOR = '(?: # Normal release vectors. \d\S* | # VCS version vectors. Per PHPCS, they are expected to # follow the form of the VCS name, followed by ":", followed # by the version vector itself. # By convention, popular VCSes like CVS, SVN and GIT use "$" # around the actual version vector. [^\s\:]+\:\s*\$[^\$]+\$ )'; /** @var string The version vector. */ protected $version = ''; public function getContent() { if (null === $this->content) { $this->content = "{$this->version} {$this->description}"; } return $this->content; } /** * {@inheritdoc} */ public function setContent($content) { parent::setContent($content); if (preg_match( '/^ # The version vector (' . self::REGEX_VECTOR . ') \s* # The description (.+)? $/sux', $this->description, $matches )) { $this->version = $matches[1]; $this->setDescription(isset($matches[2]) ? $matches[2] : ''); $this->content = $content; } return $this; } /** * Gets the version section of the tag. * * @return string The version section of the tag. */ public function getVersion() { return $this->version; } /** * Sets the version section of the tag. * * @param string $version The new version section of the tag. * An invalid value will set an empty string. * * @return $this */ public function setVersion($version) { $this->version = preg_match('/^' . self::REGEX_VECTOR . '$/ux', $version) ? $version : ''; $this->content = null; return $this; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag\VersionTag; /** * Reflection class for a @since tag in a Docblock. * * @author Vasil Rangelov * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class SinceTag extends VersionTag { } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for a @throws tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class ThrowsTag extends ReturnTag { } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Tag; /** * Reflection class for an @author tag in a Docblock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class AuthorTag extends Tag { /** * PCRE regular expression matching any valid value for the name component. */ const REGEX_AUTHOR_NAME = '[^\<]*'; /** * PCRE regular expression matching any valid value for the email component. */ const REGEX_AUTHOR_EMAIL = '[^\>]*'; /** @var string The name of the author */ protected $authorName = ''; /** @var string The email of the author */ protected $authorEmail = ''; public function getContent() { if (null === $this->content) { $this->content = $this->authorName; if ('' != $this->authorEmail) { $this->content .= "<{$this->authorEmail}>"; } } return $this->content; } /** * {@inheritdoc} */ public function setContent($content) { parent::setContent($content); if (preg_match( '/^(' . self::REGEX_AUTHOR_NAME . ')(\<(' . self::REGEX_AUTHOR_EMAIL . ')\>)?$/u', $this->description, $matches )) { $this->authorName = trim($matches[1]); if (isset($matches[3])) { $this->authorEmail = trim($matches[3]); } } return $this; } /** * Gets the author's name. * * @return string The author's name. */ public function getAuthorName() { return $this->authorName; } /** * Sets the author's name. * * @param string $authorName The new author name. * An invalid value will set an empty string. * * @return $this */ public function setAuthorName($authorName) { $this->content = null; $this->authorName = preg_match('/^' . self::REGEX_AUTHOR_NAME . '$/u', $authorName) ? $authorName : ''; return $this; } /** * Gets the author's email. * * @return string The author's email. */ public function getAuthorEmail() { return $this->authorEmail; } /** * Sets the author's email. * * @param string $authorEmail The new author email. * An invalid value will set an empty string. * * @return $this */ public function setAuthorEmail($authorEmail) { $this->authorEmail = preg_match('/^' . self::REGEX_AUTHOR_EMAIL . '$/u', $authorEmail) ? $authorEmail : ''; $this->content = null; return $this; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlock; /** * Parses a tag definition for a DocBlock. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class Tag implements \Reflector { /** * PCRE regular expression matching a tag name. */ const REGEX_TAGNAME = '[\w\-\_\\\\]+'; /** @var string Name of the tag */ protected $tag = ''; /** * @var string|null Content of the tag. * When set to NULL, it means it needs to be regenerated. */ protected $content = ''; /** @var string Description of the content of this tag */ protected $description = ''; /** * @var array|null The description, as an array of strings and Tag objects. * When set to NULL, it means it needs to be regenerated. */ protected $parsedDescription = null; /** @var Location Location of the tag. */ protected $location = null; /** @var DocBlock The DocBlock which this tag belongs to. */ protected $docblock = null; /** * @var array An array with a tag as a key, and an FQCN to a class that * handles it as an array value. The class is expected to inherit this * class. */ private static $tagHandlerMappings = array( 'author' => '\phpDocumentor\Reflection\DocBlock\Tag\AuthorTag', 'covers' => '\phpDocumentor\Reflection\DocBlock\Tag\CoversTag', 'deprecated' => '\phpDocumentor\Reflection\DocBlock\Tag\DeprecatedTag', 'example' => '\phpDocumentor\Reflection\DocBlock\Tag\ExampleTag', 'link' => '\phpDocumentor\Reflection\DocBlock\Tag\LinkTag', 'method' => '\phpDocumentor\Reflection\DocBlock\Tag\MethodTag', 'param' => '\phpDocumentor\Reflection\DocBlock\Tag\ParamTag', 'property-read' => '\phpDocumentor\Reflection\DocBlock\Tag\PropertyReadTag', 'property' => '\phpDocumentor\Reflection\DocBlock\Tag\PropertyTag', 'property-write' => '\phpDocumentor\Reflection\DocBlock\Tag\PropertyWriteTag', 'return' => '\phpDocumentor\Reflection\DocBlock\Tag\ReturnTag', 'see' => '\phpDocumentor\Reflection\DocBlock\Tag\SeeTag', 'since' => '\phpDocumentor\Reflection\DocBlock\Tag\SinceTag', 'source' => '\phpDocumentor\Reflection\DocBlock\Tag\SourceTag', 'throw' => '\phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag', 'throws' => '\phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag', 'uses' => '\phpDocumentor\Reflection\DocBlock\Tag\UsesTag', 'var' => '\phpDocumentor\Reflection\DocBlock\Tag\VarTag', 'version' => '\phpDocumentor\Reflection\DocBlock\Tag\VersionTag' ); /** * Factory method responsible for instantiating the correct sub type. * * @param string $tag_line The text for this tag, including description. * @param DocBlock $docblock The DocBlock which this tag belongs to. * @param Location $location Location of the tag. * * @throws \InvalidArgumentException if an invalid tag line was presented. * * @return static A new tag object. */ final public static function createInstance( $tag_line, DocBlock $docblock = null, Location $location = null ) { if (!preg_match( '/^@(' . self::REGEX_TAGNAME . ')(?:\s*([^\s].*)|$)?/us', $tag_line, $matches )) { throw new \InvalidArgumentException( 'Invalid tag_line detected: ' . $tag_line ); } $handler = __CLASS__; if (isset(self::$tagHandlerMappings[$matches[1]])) { $handler = self::$tagHandlerMappings[$matches[1]]; } elseif (isset($docblock)) { $tagName = (string)new Type\Collection( array($matches[1]), $docblock->getContext() ); if (isset(self::$tagHandlerMappings[$tagName])) { $handler = self::$tagHandlerMappings[$tagName]; } } return new $handler( $matches[1], isset($matches[2]) ? $matches[2] : '', $docblock, $location ); } /** * Registers a handler for tags. * * Registers a handler for tags. The class specified is autoloaded if it's * not available. It must inherit from this class. * * @param string $tag Name of tag to regiser a handler for. When * registering a namespaced tag, the full name, along with a prefixing * slash MUST be provided. * @param string|null $handler FQCN of handler. Specifing NULL removes the * handler for the specified tag, if any. * * @return bool TRUE on success, FALSE on failure. */ final public static function registerTagHandler($tag, $handler) { $tag = trim((string)$tag); if (null === $handler) { unset(self::$tagHandlerMappings[$tag]); return true; } if ('' !== $tag && class_exists($handler, true) && is_subclass_of($handler, __CLASS__) && !strpos($tag, '\\') //Accept no slash, and 1st slash at offset 0. ) { self::$tagHandlerMappings[$tag] = $handler; return true; } return false; } /** * Parses a tag and populates the member variables. * * @param string $name Name of the tag. * @param string $content The contents of the given tag. * @param DocBlock $docblock The DocBlock which this tag belongs to. * @param Location $location Location of the tag. */ public function __construct( $name, $content, DocBlock $docblock = null, Location $location = null ) { $this ->setName($name) ->setContent($content) ->setDocBlock($docblock) ->setLocation($location); } /** * Gets the name of this tag. * * @return string The name of this tag. */ public function getName() { return $this->tag; } /** * Sets the name of this tag. * * @param string $name The new name of this tag. * * @return $this * @throws \InvalidArgumentException When an invalid tag name is provided. */ public function setName($name) { if (!preg_match('/^' . self::REGEX_TAGNAME . '$/u', $name)) { throw new \InvalidArgumentException( 'Invalid tag name supplied: ' . $name ); } $this->tag = $name; return $this; } /** * Gets the content of this tag. * * @return string */ public function getContent() { if (null === $this->content) { $this->content = $this->description; } return $this->content; } /** * Sets the content of this tag. * * @param string $content The new content of this tag. * * @return $this */ public function setContent($content) { $this->setDescription($content); $this->content = $content; return $this; } /** * Gets the description component of this tag. * * @return string */ public function getDescription() { return $this->description; } /** * Sets the description component of this tag. * * @param string $description The new description component of this tag. * * @return $this */ public function setDescription($description) { $this->content = null; $this->parsedDescription = null; $this->description = trim($description); return $this; } /** * Gets the parsed text of this description. * * @return array An array of strings and tag objects, in the order they * occur within the description. */ public function getParsedDescription() { if (null === $this->parsedDescription) { $description = new Description($this->description, $this->docblock); $this->parsedDescription = $description->getParsedContents(); } return $this->parsedDescription; } /** * Gets the docblock this tag belongs to. * * @return DocBlock The docblock this tag belongs to. */ public function getDocBlock() { return $this->docblock; } /** * Sets the docblock this tag belongs to. * * @param DocBlock $docblock The new docblock this tag belongs to. Setting * NULL removes any association. * * @return $this */ public function setDocBlock(DocBlock $docblock = null) { $this->docblock = $docblock; return $this; } /** * Gets the location of the tag. * * @return Location The tag's location. */ public function getLocation() { return $this->location; } /** * Sets the location of the tag. * * @param Location $location The new location of the tag. * * @return $this */ public function setLocation(Location $location = null) { $this->location = $location; return $this; } /** * Builds a string representation of this object. * * @todo determine the exact format as used by PHP Reflection and implement it. * * @return void * @codeCoverageIgnore Not yet implemented */ public static function export() { throw new \Exception('Not yet implemented'); } /** * Returns the tag as a serialized string * * @return string */ public function __toString() { return "@{$this->getName()} {$this->getContent()}"; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock\Type; use phpDocumentor\Reflection\DocBlock\Context; /** * Collection * * @author Mike van Riel * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class Collection extends \ArrayObject { /** @var string Definition of the OR operator for types */ const OPERATOR_OR = '|'; /** @var string Definition of the ARRAY operator for types */ const OPERATOR_ARRAY = '[]'; /** @var string Definition of the NAMESPACE operator in PHP */ const OPERATOR_NAMESPACE = '\\'; /** @var string[] List of recognized keywords */ protected static $keywords = array( 'string', 'int', 'integer', 'bool', 'boolean', 'float', 'double', 'object', 'mixed', 'array', 'resource', 'void', 'null', 'scalar', 'callback', 'callable', 'false', 'true', 'self', '$this', 'static' ); /** * Current invoking location. * * This is used to prepend to type with a relative location. * May also be 'default' or 'global', in which case they are ignored. * * @var Context */ protected $context = null; /** * Registers the namespace and aliases; uses that to add and expand the * given types. * * @param string[] $types Array containing a list of types to add to this * container. * @param Context $location The current invoking location. */ public function __construct( array $types = array(), Context $context = null ) { $this->context = null === $context ? new Context() : $context; foreach ($types as $type) { $this->add($type); } } /** * Returns the current invoking location. * * @return Context */ public function getContext() { return $this->context; } /** * Adds a new type to the collection and expands it if it contains a * relative namespace. * * If a class in the type contains a relative namespace than this collection * will try to expand that into a FQCN. * * @param string $type A 'Type' as defined in the phpDocumentor * documentation. * * @throws \InvalidArgumentException if a non-string argument is passed. * * @see http://phpdoc.org/docs/latest/for-users/types.html for the * definition of a type. * * @return void */ public function add($type) { if (!is_string($type)) { throw new \InvalidArgumentException( 'A type should be represented by a string, received: ' .var_export($type, true) ); } // separate the type by the OR operator $type_parts = explode(self::OPERATOR_OR, $type); foreach ($type_parts as $part) { $expanded_type = $this->expand($part); if ($expanded_type) { $this[] = $expanded_type; } } } /** * Returns a string representation of the collection. * * @return string The resolved types across the collection, separated with * {@link self::OPERATOR_OR}. */ public function __toString() { return implode(self::OPERATOR_OR, $this->getArrayCopy()); } /** * Analyzes the given type and returns the FQCN variant. * * When a type is provided this method checks whether it is not a keyword or * Fully Qualified Class Name. If so it will use the given namespace and * aliases to expand the type to a FQCN representation. * * This method only works as expected if the namespace and aliases are set; * no dynamic reflection is being performed here. * * @param string $type The relative or absolute type. * * @uses getNamespace to determine with what to prefix the type name. * @uses getNamespaceAliases to check whether the first part of the relative * type name should not be replaced with another namespace. * * @return string */ protected function expand($type) { $type = trim($type); if (!$type) { return ''; } if ($this->isTypeAnArray($type)) { return $this->expand(substr($type, 0, -2)) . self::OPERATOR_ARRAY; } if ($this->isRelativeType($type) && !$this->isTypeAKeyword($type)) { $type_parts = explode(self::OPERATOR_NAMESPACE, $type, 2); $namespace_aliases = $this->context->getNamespaceAliases(); // if the first segment is not an alias; prepend namespace name and // return if (!isset($namespace_aliases[$type_parts[0]])) { $namespace = $this->context->getNamespace(); if ('' !== $namespace) { $namespace .= self::OPERATOR_NAMESPACE; } return self::OPERATOR_NAMESPACE . $namespace . $type; } $type_parts[0] = $namespace_aliases[$type_parts[0]]; $type = implode(self::OPERATOR_NAMESPACE, $type_parts); } return $type; } /** * Detects whether the given type represents an array. * * @param string $type A relative or absolute type as defined in the * phpDocumentor documentation. * * @return bool */ protected function isTypeAnArray($type) { return substr($type, -2) === self::OPERATOR_ARRAY; } /** * Detects whether the given type represents a PHPDoc keyword. * * @param string $type A relative or absolute type as defined in the * phpDocumentor documentation. * * @return bool */ protected function isTypeAKeyword($type) { return in_array(strtolower($type), static::$keywords, true); } /** * Detects whether the given type represents a relative or absolute path. * * This method will detect keywords as being absolute; even though they are * not preceeded by a namespace separator. * * @param string $type A relative or absolute type as defined in the * phpDocumentor documentation. * * @return bool */ protected function isRelativeType($type) { return ($type[0] !== self::OPERATOR_NAMESPACE) || $this->isTypeAKeyword($type); } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection\DocBlock; /** * The location a DocBlock occurs within a file. * * @author Vasil Rangelov * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class Location { /** @var int Line where the DocBlock text starts. */ protected $lineNumber = 0; /** @var int Column where the DocBlock text starts. */ protected $columnNumber = 0; public function __construct( $lineNumber = 0, $columnNumber = 0 ) { $this->setLineNumber($lineNumber)->setColumnNumber($columnNumber); } /** * @return int Line where the DocBlock text starts. */ public function getLineNumber() { return $this->lineNumber; } /** * * @param type $lineNumber * @return $this */ public function setLineNumber($lineNumber) { $this->lineNumber = (int)$lineNumber; return $this; } /** * @return int Column where the DocBlock text starts. */ public function getColumnNumber() { return $this->columnNumber; } /** * * @param int $columnNumber * @return $this */ public function setColumnNumber($columnNumber) { $this->columnNumber = (int)$columnNumber; return $this; } } * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ namespace phpDocumentor\Reflection; use phpDocumentor\Reflection\DocBlock\Tag; use phpDocumentor\Reflection\DocBlock\Context; use phpDocumentor\Reflection\DocBlock\Location; /** * Parses the DocBlock for any structure. * * @author Mike van Riel * @license http://www.opensource.org/licenses/mit-license.php MIT * @link http://phpdoc.org */ class DocBlock implements \Reflector { /** @var string The opening line for this docblock. */ protected $short_description = ''; /** * @var DocBlock\Description The actual * description for this docblock. */ protected $long_description = null; /** * @var Tag[] An array containing all * the tags in this docblock; except inline. */ protected $tags = array(); /** @var Context Information about the context of this DocBlock. */ protected $context = null; /** @var Location Information about the location of this DocBlock. */ protected $location = null; /** @var bool Is this DocBlock (the start of) a template? */ protected $isTemplateStart = false; /** @var bool Does this DocBlock signify the end of a DocBlock template? */ protected $isTemplateEnd = false; /** * Parses the given docblock and populates the member fields. * * The constructor may also receive namespace information such as the * current namespace and aliases. This information is used by some tags * (e.g. @return, @param, etc.) to turn a relative Type into a FQCN. * * @param \Reflector|string $docblock A docblock comment (including * asterisks) or reflector supporting the getDocComment method. * @param Context $context The context in which the DocBlock * occurs. * @param Location $location The location within the file that this * DocBlock occurs in. * * @throws \InvalidArgumentException if the given argument does not have the * getDocComment method. */ public function __construct( $docblock, Context $context = null, Location $location = null ) { if (is_object($docblock)) { if (!method_exists($docblock, 'getDocComment')) { throw new \InvalidArgumentException( 'Invalid object passed; the given reflector must support ' . 'the getDocComment method' ); } $docblock = $docblock->getDocComment(); } $docblock = $this->cleanInput($docblock); list($templateMarker, $short, $long, $tags) = $this->splitDocBlock($docblock); $this->isTemplateStart = $templateMarker === '#@+'; $this->isTemplateEnd = $templateMarker === '#@-'; $this->short_description = $short; $this->long_description = new DocBlock\Description($long, $this); $this->parseTags($tags); $this->context = $context; $this->location = $location; } /** * Strips the asterisks from the DocBlock comment. * * @param string $comment String containing the comment text. * * @return string */ protected function cleanInput($comment) { $comment = trim( preg_replace( '#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]{0,1}(.*)?#u', '$1', $comment ) ); // reg ex above is not able to remove */ from a single line docblock if (substr($comment, -2) == '*/') { $comment = trim(substr($comment, 0, -2)); } // normalize strings $comment = str_replace(array("\r\n", "\r"), "\n", $comment); return $comment; } /** * Splits the DocBlock into a template marker, summary, description and block of tags. * * @param string $comment Comment to split into the sub-parts. * * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. * @author Mike van Riel for extending the regex with template marker support. * * @return string[] containing the template marker (if any), summary, description and a string containing the tags. */ protected function splitDocBlock($comment) { // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the // performance impact of running a regular expression if (strpos($comment, '@') === 0) { return array('', '', '', $comment); } // clears all extra horizontal whitespace from the line endings to prevent parsing issues $comment = preg_replace('/\h*$/Sum', '', $comment); /* * Splits the docblock into a template marker, short description, long description and tags section * * - The template marker is empty, #@+ or #@- if the DocBlock starts with either of those (a newline may * occur after it and will be stripped). * - The short description is started from the first character until a dot is encountered followed by a * newline OR two consecutive newlines (horizontal whitespace is taken into account to consider spacing * errors). This is optional. * - The long description, any character until a new line is encountered followed by an @ and word * characters (a tag). This is optional. * - Tags; the remaining characters * * Big thanks to RichardJ for contributing this Regular Expression */ preg_match( '/ \A # 1. Extract the template marker (?:(\#\@\+|\#\@\-)\n?)? # 2. Extract the summary (?: (?! @\pL ) # The summary may not start with an @ ( [^\n.]+ (?: (?! \. \n | \n{2} ) # End summary upon a dot followed by newline or two newlines [\n.] (?! [ \t]* @\pL ) # End summary when an @ is found as first character on a new line [^\n.]+ # Include anything else )* \.? )? ) # 3. Extract the description (?: \s* # Some form of whitespace _must_ precede a description because a summary must be there (?! @\pL ) # The description may not start with an @ ( [^\n]+ (?: \n+ (?! [ \t]* @\pL ) # End description when an @ is found as first character on a new line [^\n]+ # Include anything else )* ) )? # 4. Extract the tags (anything that follows) (\s+ [\s\S]*)? # everything that follows /ux', $comment, $matches ); array_shift($matches); while (count($matches) < 4) { $matches[] = ''; } return $matches; } /** * Creates the tag objects. * * @param string $tags Tag block to parse. * * @return void */ protected function parseTags($tags) { $result = array(); $tags = trim($tags); if ('' !== $tags) { if ('@' !== $tags[0]) { throw new \LogicException( 'A tag block started with text instead of an actual tag,' . ' this makes the tag block invalid: ' . $tags ); } foreach (explode("\n", $tags) as $tag_line) { if (isset($tag_line[0]) && ($tag_line[0] === '@')) { $result[] = $tag_line; } else { $result[count($result) - 1] .= "\n" . $tag_line; } } // create proper Tag objects foreach ($result as $key => $tag_line) { $result[$key] = Tag::createInstance(trim($tag_line), $this); } } $this->tags = $result; } /** * Gets the text portion of the doc block. * * Gets the text portion (short and long description combined) of the doc * block. * * @return string The text portion of the doc block. */ public function getText() { $short = $this->getShortDescription(); $long = $this->getLongDescription()->getContents(); if ($long) { return "{$short}\n\n{$long}"; } else { return $short; } } /** * Set the text portion of the doc block. * * Sets the text portion (short and long description combined) of the doc * block. * * @param string $docblock The new text portion of the doc block. * * @return $this This doc block. */ public function setText($comment) { list(,$short, $long) = $this->splitDocBlock($comment); $this->short_description = $short; $this->long_description = new DocBlock\Description($long, $this); return $this; } /** * Returns the opening line or also known as short description. * * @return string */ public function getShortDescription() { return $this->short_description; } /** * Returns the full description or also known as long description. * * @return DocBlock\Description */ public function getLongDescription() { return $this->long_description; } /** * Returns whether this DocBlock is the start of a Template section. * * A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker * (`#@+`) that is appended directly after the opening `/**` of a DocBlock. * * An example of such an opening is: * * ``` * /**#@+ * * My DocBlock * * / * ``` * * The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all * elements that follow until another DocBlock is found that contains the closing marker (`#@-`). * * @see self::isTemplateEnd() for the check whether a closing marker was provided. * * @return boolean */ public function isTemplateStart() { return $this->isTemplateStart; } /** * Returns whether this DocBlock is the end of a Template section. * * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality. * * @return boolean */ public function isTemplateEnd() { return $this->isTemplateEnd; } /** * Returns the current context. * * @return Context */ public function getContext() { return $this->context; } /** * Returns the current location. * * @return Location */ public function getLocation() { return $this->location; } /** * Returns the tags for this DocBlock. * * @return Tag[] */ public function getTags() { return $this->tags; } /** * Returns an array of tags matching the given name. If no tags are found * an empty array is returned. * * @param string $name String to search by. * * @return Tag[] */ public function getTagsByName($name) { $result = array(); /** @var Tag $tag */ foreach ($this->getTags() as $tag) { if ($tag->getName() != $name) { continue; } $result[] = $tag; } return $result; } /** * Checks if a tag of a certain type is present in this DocBlock. * * @param string $name Tag name to check for. * * @return bool */ public function hasTag($name) { /** @var Tag $tag */ foreach ($this->getTags() as $tag) { if ($tag->getName() == $name) { return true; } } return false; } /** * Appends a tag at the end of the list of tags. * * @param Tag $tag The tag to add. * * @return Tag The newly added tag. * * @throws \LogicException When the tag belongs to a different DocBlock. */ public function appendTag(Tag $tag) { if (null === $tag->getDocBlock()) { $tag->setDocBlock($this); } if ($tag->getDocBlock() === $this) { $this->tags[] = $tag; } else { throw new \LogicException( 'This tag belongs to a different DocBlock object.' ); } return $tag; } /** * Builds a string representation of this object. * * @todo determine the exact format as used by PHP Reflection and * implement it. * * @return string * @codeCoverageIgnore Not yet implemented */ public static function export() { throw new \Exception('Not yet implemented'); } /** * Returns the exported information (we should use the export static method * BUT this throws an exception at this point). * * @return string * @codeCoverageIgnore Not yet implemented */ public function __toString() { return 'Not yet implemented'; } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace PhpOption; use ArrayIterator; final class Some extends Option { private $value; public function __construct($value) { $this->value = $value; } public static function create($value) { return new self($value); } public function isDefined() { return true; } public function isEmpty() { return false; } public function get() { return $this->value; } public function getOrElse($default) { return $this->value; } public function getOrCall($callable) { return $this->value; } public function getOrThrow(\Exception $ex) { return $this->value; } public function orElse(Option $else) { return $this; } /** * @deprecated Use forAll() instead. */ public function ifDefined($callable) { call_user_func($callable, $this->value); } public function forAll($callable) { call_user_func($callable, $this->value); return $this; } public function map($callable) { return new self(call_user_func($callable, $this->value)); } public function flatMap($callable) { $rs = call_user_func($callable, $this->value); if ( ! $rs instanceof Option) { throw new \RuntimeException('Callables passed to flatMap() must return an Option. Maybe you should use map() instead?'); } return $rs; } public function filter($callable) { if (true === call_user_func($callable, $this->value)) { return $this; } return None::create(); } public function filterNot($callable) { if (false === call_user_func($callable, $this->value)) { return $this; } return None::create(); } public function select($value) { if ($this->value === $value) { return $this; } return None::create(); } public function reject($value) { if ($this->value === $value) { return None::create(); } return $this; } public function getIterator() { return new ArrayIterator(array($this->value)); } public function foldLeft($initialValue, $callable) { return call_user_func($callable, $initialValue, $this->value); } public function foldRight($initialValue, $callable) { return call_user_func($callable, $this->value, $initialValue); } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace PhpOption; use EmptyIterator; final class None extends Option { private static $instance; public static function create() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } public function get() { throw new \RuntimeException('None has no value.'); } public function getOrCall($callable) { return call_user_func($callable); } public function getOrElse($default) { return $default; } public function getOrThrow(\Exception $ex) { throw $ex; } public function isEmpty() { return true; } public function isDefined() { return false; } public function orElse(Option $else) { return $else; } /** * @deprecated Use forAll() instead. */ public function ifDefined($callable) { // Just do nothing in that case. } public function forAll($callable) { return $this; } public function map($callable) { return $this; } public function flatMap($callable) { return $this; } public function filter($callable) { return $this; } public function filterNot($callable) { return $this; } public function select($value) { return $this; } public function reject($value) { return $this; } public function getIterator() { return new EmptyIterator(); } public function foldLeft($initialValue, $callable) { return $initialValue; } public function foldRight($initialValue, $callable) { return $initialValue; } private function __construct() { } } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace PhpOption; use IteratorAggregate; /** * Base Option Class. * * @author Johannes M. Schmitt */ abstract class Option implements IteratorAggregate { /** * Creates an option given a return value. * * This is intended for consuming existing APIs and allows you to easily * convert them to an option. By default, we treat ``null`` as the None case, * and everything else as Some. * * @param mixed $value The actual return value. * @param mixed $noneValue The value which should be considered "None"; null * by default. * * @return Option */ public static function fromValue($value, $noneValue = null) { if ($value === $noneValue) { return None::create(); } return new Some($value); } /** * Creates an option from an array's value. * * If the key does not exist in the array, the array is not actually an array, or the * array's value at the given key is null, None is returned. * * Otherwise, Some is returned wrapping the value at the given key. * * @param mixed $array a potential array value * @param string $key the key to check * * @return Option */ public static function fromArraysValue($array, $key) { if ( ! isset($array[$key])) { return None::create(); } return new Some($array[$key]); } /** * Creates a lazy-option with the given callback. * * This is also a helper constructor for lazy-consuming existing APIs where * the return value is not yet an option. By default, we treat ``null`` as * None case, and everything else as Some. * * @param callable $callback The callback to evaluate. * @param array $arguments * @param mixed $noneValue The value which should be considered "None"; null * by default. * * @return Option */ public static function fromReturn($callback, array $arguments = array(), $noneValue = null) { return new LazyOption(function() use ($callback, $arguments, $noneValue) { $return = call_user_func_array($callback, $arguments); if ($return === $noneValue) { return None::create(); } return new Some($return); }); } /** * Option factory, which creates new option based on passed value. * If value is already an option, it simply returns * If value is a \Closure, LazyOption with passed callback created and returned. If Option returned from callback, * it returns directly (flatMap-like behaviour) * On other case value passed to Option::fromValue() method * * @param Option|\Closure|mixed $value * @param null $noneValue used when $value is mixed or Closure, for None-check * * @return Option */ public static function ensure($value, $noneValue = null) { if ($value instanceof Option) { return $value; } elseif ($value instanceof \Closure) { return new LazyOption(function() use ($value, $noneValue) { $return = $value(); if ($return instanceof Option) { return $return; } else { return Option::fromValue($return, $noneValue); } }); } else { return Option::fromValue($value, $noneValue); } } /** * Returns the value if available, or throws an exception otherwise. * * @throws \RuntimeException if value is not available * * @return mixed */ abstract public function get(); /** * Returns the value if available, or the default value if not. * * @param mixed $default * * @return mixed */ abstract public function getOrElse($default); /** * Returns the value if available, or the results of the callable. * * This is preferable over ``getOrElse`` if the computation of the default * value is expensive. * * @param callable $callable * * @return mixed */ abstract public function getOrCall($callable); /** * Returns the value if available, or throws the passed exception. * * @param \Exception $ex * * @return mixed */ abstract public function getOrThrow(\Exception $ex); /** * Returns true if no value is available, false otherwise. * * @return boolean */ abstract public function isEmpty(); /** * Returns true if a value is available, false otherwise. * * @return boolean */ abstract public function isDefined(); /** * Returns this option if non-empty, or the passed option otherwise. * * This can be used to try multiple alternatives, and is especially useful * with lazy evaluating options: * * ```php * $repo->findSomething() * ->orElse(new LazyOption(array($repo, 'findSomethingElse'))) * ->orElse(new LazyOption(array($repo, 'createSomething'))); * ``` * * @param Option $else * * @return Option */ abstract public function orElse(Option $else); /** * This is similar to map() below except that the return value has no meaning; * the passed callable is simply executed if the option is non-empty, and * ignored if the option is empty. * * In all cases, the return value of the callable is discarded. * * ```php * $comment->getMaybeFile()->ifDefined(function($file) { * // Do something with $file here. * }); * ``` * * If you're looking for something like ``ifEmpty``, you can use ``getOrCall`` * and ``getOrElse`` in these cases. * * @deprecated Use forAll() instead. * * @param callable $callable * * @return void */ abstract public function ifDefined($callable); /** * This is similar to map() except that the return value of the callable has no meaning. * * The passed callable is simply executed if the option is non-empty, and ignored if the * option is empty. This method is preferred for callables with side-effects, while map() * is intended for callables without side-effects. * * @param callable $callable * * @return Option */ abstract public function forAll($callable); /** * Applies the callable to the value of the option if it is non-empty, * and returns the return value of the callable wrapped in Some(). * * If the option is empty, then the callable is not applied. * * ```php * (new Some("foo"))->map('strtoupper')->get(); // "FOO" * ``` * * @param callable $callable * * @return Option */ abstract public function map($callable); /** * Applies the callable to the value of the option if it is non-empty, and * returns the return value of the callable directly. * * In contrast to ``map``, the return value of the callable is expected to * be an Option itself; it is not automatically wrapped in Some(). * * @param callable $callable must return an Option * * @return Option */ abstract public function flatMap($callable); /** * If the option is empty, it is returned immediately without applying the callable. * * If the option is non-empty, the callable is applied, and if it returns true, * the option itself is returned; otherwise, None is returned. * * @param callable $callable * * @return Option */ abstract public function filter($callable); /** * If the option is empty, it is returned immediately without applying the callable. * * If the option is non-empty, the callable is applied, and if it returns false, * the option itself is returned; otherwise, None is returned. * * @param callable $callable * * @return Option */ abstract public function filterNot($callable); /** * If the option is empty, it is returned immediately. * * If the option is non-empty, and its value does not equal the passed value * (via a shallow comparison ===), then None is returned. Otherwise, the * Option is returned. * * In other words, this will filter all but the passed value. * * @param mixed $value * * @return Option */ abstract public function select($value); /** * If the option is empty, it is returned immediately. * * If the option is non-empty, and its value does equal the passed value (via * a shallow comparison ===), then None is returned; otherwise, the Option is * returned. * * In other words, this will let all values through except the passed value. * * @param mixed $value * * @return Option */ abstract public function reject($value); /** * Binary operator for the initial value and the option's value. * * If empty, the initial value is returned. * If non-empty, the callable receives the initial value and the option's value as arguments * * ```php * * $some = new Some(5); * $none = None::create(); * $result = $some->foldLeft(1, function($a, $b) { return $a + $b; }); // int(6) * $result = $none->foldLeft(1, function($a, $b) { return $a + $b; }); // int(1) * * // This can be used instead of something like the following: * $option = Option::fromValue($integerOrNull); * $result = 1; * if ( ! $option->isEmpty()) { * $result += $option->get(); * } * ``` * * @param mixed $initialValue * @param callable $callable function(initialValue, callable): result * * @return mixed */ abstract public function foldLeft($initialValue, $callable); /** * foldLeft() but with reversed arguments for the callable. * * @param mixed $initialValue * @param callable $callable function(callable, initialValue): result * * @return mixed */ abstract public function foldRight($initialValue, $callable); } * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace PhpOption; final class LazyOption extends Option { /** @var callable */ private $callback; /** @var array */ private $arguments; /** @var Option|null */ private $option; /** * Helper Constructor. * * @param callable $callback * @param array $arguments * * @return LazyOption */ public static function create($callback, array $arguments = array()) { return new self($callback, $arguments); } /** * Constructor. * * @param callable $callback * @param array $arguments */ public function __construct($callback, array $arguments = array()) { if (!is_callable($callback)) { throw new \InvalidArgumentException('Invalid callback given'); } $this->callback = $callback; $this->arguments = $arguments; } public function isDefined() { return $this->option()->isDefined(); } public function isEmpty() { return $this->option()->isEmpty(); } public function get() { return $this->option()->get(); } public function getOrElse($default) { return $this->option()->getOrElse($default); } public function getOrCall($callable) { return $this->option()->getOrCall($callable); } public function getOrThrow(\Exception $ex) { return $this->option()->getOrThrow($ex); } public function orElse(Option $else) { return $this->option()->orElse($else); } /** * @deprecated Use forAll() instead. */ public function ifDefined($callable) { $this->option()->ifDefined($callable); } public function forAll($callable) { return $this->option()->forAll($callable); } public function map($callable) { return $this->option()->map($callable); } public function flatMap($callable) { return $this->option()->flatMap($callable); } public function filter($callable) { return $this->option()->filter($callable); } public function filterNot($callable) { return $this->option()->filterNot($callable); } public function select($value) { return $this->option()->select($value); } public function reject($value) { return $this->option()->reject($value); } public function getIterator() { return $this->option()->getIterator(); } public function foldLeft($initialValue, $callable) { return $this->option()->foldLeft($initialValue, $callable); } public function foldRight($initialValue, $callable) { return $this->option()->foldRight($initialValue, $callable); } /** * @return Option */ private function option() { if (null === $this->option) { $this->option = call_user_func_array($this->callback, $this->arguments); if (!$this->option instanceof Option) { $this->option = null; throw new \RuntimeException('Expected instance of \PhpOption\Option'); } } return $this->option; } } values = $values; } /** * Sets a parameter or an object. * * Objects must be defined as Closures. * * Allowing any PHP callable leads to difficult to debug problems * as function names (strings) are callable (creating a function with * the same a name as an existing parameter would break your container). * * @param string $id The unique identifier for the parameter or object * @param mixed $value The value of the parameter or a closure to defined an object */ public function offsetSet($id, $value) { $this->values[$id] = $value; } /** * Gets a parameter or an object. * * @param string $id The unique identifier for the parameter or object * * @return mixed The value of the parameter or an object * * @throws InvalidArgumentException if the identifier is not defined */ public function offsetGet($id) { if (!array_key_exists($id, $this->values)) { throw new InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); } $isFactory = is_object($this->values[$id]) && method_exists($this->values[$id], '__invoke'); return $isFactory ? $this->values[$id]($this) : $this->values[$id]; } /** * Checks if a parameter or an object is set. * * @param string $id The unique identifier for the parameter or object * * @return Boolean */ public function offsetExists($id) { return array_key_exists($id, $this->values); } /** * Unsets a parameter or an object. * * @param string $id The unique identifier for the parameter or object */ public function offsetUnset($id) { unset($this->values[$id]); } /** * Returns a closure that stores the result of the given service definition * for uniqueness in the scope of this instance of Pimple. * * @param callable $callable A service definition to wrap for uniqueness * * @return Closure The wrapped closure */ public static function share($callable) { if (!is_object($callable) || !method_exists($callable, '__invoke')) { throw new InvalidArgumentException('Service definition is not a Closure or invokable object.'); } return function ($c) use ($callable) { static $object; if (null === $object) { $object = $callable($c); } return $object; }; } /** * Protects a callable from being interpreted as a service. * * This is useful when you want to store a callable as a parameter. * * @param callable $callable A callable to protect from being evaluated * * @return Closure The protected closure */ public static function protect($callable) { if (!is_object($callable) || !method_exists($callable, '__invoke')) { throw new InvalidArgumentException('Callable is not a Closure or invokable object.'); } return function ($c) use ($callable) { return $callable; }; } /** * Gets a parameter or the closure defining an object. * * @param string $id The unique identifier for the parameter or object * * @return mixed The value of the parameter or the closure defining an object * * @throws InvalidArgumentException if the identifier is not defined */ public function raw($id) { if (!array_key_exists($id, $this->values)) { throw new InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); } return $this->values[$id]; } /** * Extends an object definition. * * Useful when you want to extend an existing object definition, * without necessarily loading that object. * * @param string $id The unique identifier for the object * @param callable $callable A service definition to extend the original * * @return Closure The wrapped closure * * @throws InvalidArgumentException if the identifier is not defined or not a service definition */ public function extend($id, $callable) { if (!array_key_exists($id, $this->values)) { throw new InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); } if (!is_object($this->values[$id]) || !method_exists($this->values[$id], '__invoke')) { throw new InvalidArgumentException(sprintf('Identifier "%s" does not contain an object definition.', $id)); } if (!is_object($callable) || !method_exists($callable, '__invoke')) { throw new InvalidArgumentException('Extension service definition is not a Closure or invokable object.'); } $factory = $this->values[$id]; return $this->values[$id] = function ($c) use ($callable, $factory) { return $callable($factory($c), $c); }; } /** * Returns all defined value names. * * @return array An array of value names */ public function keys() { return array_keys($this->values); } } log(LogLevel::EMERGENCY, $message, $context); } /** * Action must be taken immediately. * * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * * @param string $message * @param array $context * @return null */ public function alert($message, array $context = array()) { $this->log(LogLevel::ALERT, $message, $context); } /** * Critical conditions. * * Example: Application component unavailable, unexpected exception. * * @param string $message * @param array $context * @return null */ public function critical($message, array $context = array()) { $this->log(LogLevel::CRITICAL, $message, $context); } /** * Runtime errors that do not require immediate action but should typically * be logged and monitored. * * @param string $message * @param array $context * @return null */ public function error($message, array $context = array()) { $this->log(LogLevel::ERROR, $message, $context); } /** * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * * @param string $message * @param array $context * @return null */ public function warning($message, array $context = array()) { $this->log(LogLevel::WARNING, $message, $context); } /** * Normal but significant events. * * @param string $message * @param array $context * @return null */ public function notice($message, array $context = array()) { $this->log(LogLevel::NOTICE, $message, $context); } /** * Interesting events. * * Example: User logs in, SQL logs. * * @param string $message * @param array $context * @return null */ public function info($message, array $context = array()) { $this->log(LogLevel::INFO, $message, $context); } /** * Detailed debug information. * * @param string $message * @param array $context * @return null */ public function debug($message, array $context = array()) { $this->log(LogLevel::DEBUG, $message, $context); } /** * Logs with an arbitrary level. * * @param mixed $level * @param string $message * @param array $context * @return null */ abstract public function log($level, $message, array $context = array()); } logger = $logger; } } log(LogLevel::EMERGENCY, $message, $context); } /** * Action must be taken immediately. * * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * * @param string $message * @param array $context * @return null */ public function alert($message, array $context = array()) { $this->log(LogLevel::ALERT, $message, $context); } /** * Critical conditions. * * Example: Application component unavailable, unexpected exception. * * @param string $message * @param array $context * @return null */ public function critical($message, array $context = array()) { $this->log(LogLevel::CRITICAL, $message, $context); } /** * Runtime errors that do not require immediate action but should typically * be logged and monitored. * * @param string $message * @param array $context * @return null */ public function error($message, array $context = array()) { $this->log(LogLevel::ERROR, $message, $context); } /** * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * * @param string $message * @param array $context * @return null */ public function warning($message, array $context = array()) { $this->log(LogLevel::WARNING, $message, $context); } /** * Normal but significant events. * * @param string $message * @param array $context * @return null */ public function notice($message, array $context = array()) { $this->log(LogLevel::NOTICE, $message, $context); } /** * Interesting events. * * Example: User logs in, SQL logs. * * @param string $message * @param array $context * @return null */ public function info($message, array $context = array()) { $this->log(LogLevel::INFO, $message, $context); } /** * Detailed debug information. * * @param string $message * @param array $context * @return null */ public function debug($message, array $context = array()) { $this->log(LogLevel::DEBUG, $message, $context); } } logger) { }` * blocks. */ class NullLogger extends AbstractLogger { /** * Logs with an arbitrary level. * * @param mixed $level * @param string $message * @param array $context * @return null */ public function log($level, $message, array $context = array()) { // noop } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem; use Symfony\Component\Filesystem\Exception\IOException; /** * Provides basic utility to manipulate the file system. * * @author Fabien Potencier */ class Filesystem { /** * Copies a file. * * This method only copies the file if the origin file is newer than the target file. * * By default, if the target already exists, it is not overridden. * * @param string $originFile The original filename * @param string $targetFile The target filename * @param boolean $override Whether to override an existing file or not * * @throws IOException When copy fails */ public function copy($originFile, $targetFile, $override = false) { if (stream_is_local($originFile) && !is_file($originFile)) { throw new IOException(sprintf('Failed to copy %s because file not exists', $originFile)); } $this->mkdir(dirname($targetFile)); if (!$override && is_file($targetFile)) { $doCopy = filemtime($originFile) > filemtime($targetFile); } else { $doCopy = true; } if ($doCopy) { // https://bugs.php.net/bug.php?id=64634 $source = fopen($originFile, 'r'); $target = fopen($targetFile, 'w+'); stream_copy_to_stream($source, $target); fclose($source); fclose($target); unset($source, $target); if (!is_file($targetFile)) { throw new IOException(sprintf('Failed to copy %s to %s', $originFile, $targetFile)); } } } /** * Creates a directory recursively. * * @param string|array|\Traversable $dirs The directory path * @param integer $mode The directory mode * * @throws IOException On any directory creation failure */ public function mkdir($dirs, $mode = 0777) { foreach ($this->toIterator($dirs) as $dir) { if (is_dir($dir)) { continue; } if (true !== @mkdir($dir, $mode, true)) { throw new IOException(sprintf('Failed to create %s', $dir)); } } } /** * Checks the existence of files or directories. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to check * * @return Boolean true if the file exists, false otherwise */ public function exists($files) { foreach ($this->toIterator($files) as $file) { if (!file_exists($file)) { return false; } } return true; } /** * Sets access and modification time of file. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create * @param integer $time The touch time as a unix timestamp * @param integer $atime The access time as a unix timestamp * * @throws IOException When touch fails */ public function touch($files, $time = null, $atime = null) { foreach ($this->toIterator($files) as $file) { $touch = $time ? @touch($file, $time, $atime) : @touch($file); if (true !== $touch) { throw new IOException(sprintf('Failed to touch %s', $file)); } } } /** * Removes files or directories. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove * * @throws IOException When removal fails */ public function remove($files) { $files = iterator_to_array($this->toIterator($files)); $files = array_reverse($files); foreach ($files as $file) { if (!file_exists($file) && !is_link($file)) { continue; } if (is_dir($file) && !is_link($file)) { $this->remove(new \FilesystemIterator($file)); if (true !== @rmdir($file)) { throw new IOException(sprintf('Failed to remove directory %s', $file)); } } else { // https://bugs.php.net/bug.php?id=52176 if (defined('PHP_WINDOWS_VERSION_MAJOR') && is_dir($file)) { if (true !== @rmdir($file)) { throw new IOException(sprintf('Failed to remove file %s', $file)); } } else { if (true !== @unlink($file)) { throw new IOException(sprintf('Failed to remove file %s', $file)); } } } } } /** * Change mode for an array of files or directories. * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change mode * @param integer $mode The new mode (octal) * @param integer $umask The mode mask (octal) * @param Boolean $recursive Whether change the mod recursively or not * * @throws IOException When the change fail */ public function chmod($files, $mode, $umask = 0000, $recursive = false) { foreach ($this->toIterator($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chmod(new \FilesystemIterator($file), $mode, $umask, true); } if (true !== @chmod($file, $mode & ~$umask)) { throw new IOException(sprintf('Failed to chmod file %s', $file)); } } } /** * Change the owner of an array of files or directories * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change owner * @param string $user The new owner user name * @param Boolean $recursive Whether change the owner recursively or not * * @throws IOException When the change fail */ public function chown($files, $user, $recursive = false) { foreach ($this->toIterator($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chown(new \FilesystemIterator($file), $user, true); } if (is_link($file) && function_exists('lchown')) { if (true !== @lchown($file, $user)) { throw new IOException(sprintf('Failed to chown file %s', $file)); } } else { if (true !== @chown($file, $user)) { throw new IOException(sprintf('Failed to chown file %s', $file)); } } } } /** * Change the group of an array of files or directories * * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to change group * @param string $group The group name * @param Boolean $recursive Whether change the group recursively or not * * @throws IOException When the change fail */ public function chgrp($files, $group, $recursive = false) { foreach ($this->toIterator($files) as $file) { if ($recursive && is_dir($file) && !is_link($file)) { $this->chgrp(new \FilesystemIterator($file), $group, true); } if (is_link($file) && function_exists('lchgrp')) { if (true !== @lchgrp($file, $group)) { throw new IOException(sprintf('Failed to chgrp file %s', $file)); } } else { if (true !== @chgrp($file, $group)) { throw new IOException(sprintf('Failed to chgrp file %s', $file)); } } } } /** * Renames a file. * * @param string $origin The origin filename * @param string $target The new filename * @param Boolean $overwrite Whether to overwrite the target if it already exists * * @throws IOException When target file already exists * @throws IOException When origin cannot be renamed */ public function rename($origin, $target, $overwrite = false) { // we check that target does not exist if (!$overwrite && is_readable($target)) { throw new IOException(sprintf('Cannot rename because the target "%s" already exist.', $target)); } if (true !== @rename($origin, $target)) { throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target)); } } /** * Creates a symbolic link or copy a directory. * * @param string $originDir The origin directory path * @param string $targetDir The symbolic link name * @param Boolean $copyOnWindows Whether to copy files if on Windows * * @throws IOException When symlink fails */ public function symlink($originDir, $targetDir, $copyOnWindows = false) { if (!function_exists('symlink') && $copyOnWindows) { $this->mirror($originDir, $targetDir); return; } $this->mkdir(dirname($targetDir)); $ok = false; if (is_link($targetDir)) { if (readlink($targetDir) != $originDir) { $this->remove($targetDir); } else { $ok = true; } } if (!$ok) { if (true !== @symlink($originDir, $targetDir)) { $report = error_get_last(); if (is_array($report)) { if (defined('PHP_WINDOWS_VERSION_MAJOR') && false !== strpos($report['message'], 'error code(1314)')) { throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?'); } } throw new IOException(sprintf('Failed to create symbolic link from %s to %s', $originDir, $targetDir)); } } } /** * Given an existing path, convert it to a path relative to a given starting path * * @param string $endPath Absolute path of target * @param string $startPath Absolute path where traversal begins * * @return string Path of target relative to starting path */ public function makePathRelative($endPath, $startPath) { // Normalize separators on windows if (defined('PHP_WINDOWS_VERSION_MAJOR')) { $endPath = strtr($endPath, '\\', '/'); $startPath = strtr($startPath, '\\', '/'); } // Split the paths into arrays $startPathArr = explode('/', trim($startPath, '/')); $endPathArr = explode('/', trim($endPath, '/')); // Find for which directory the common path stops $index = 0; while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) { $index++; } // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels) $depth = count($startPathArr) - $index; // Repeated "../" for each level need to reach the common path $traverser = str_repeat('../', $depth); $endPathRemainder = implode('/', array_slice($endPathArr, $index)); // Construct $endPath from traversing to the common path, then to the remaining $endPath $relativePath = $traverser.(strlen($endPathRemainder) > 0 ? $endPathRemainder.'/' : ''); return (strlen($relativePath) === 0) ? './' : $relativePath; } /** * Mirrors a directory to another. * * @param string $originDir The origin directory * @param string $targetDir The target directory * @param \Traversable $iterator A Traversable instance * @param array $options An array of boolean options * Valid options are: * - $options['override'] Whether to override an existing file on copy or not (see copy()) * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink()) * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) * * @throws IOException When file type is unknown */ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array()) { $targetDir = rtrim($targetDir, '/\\'); $originDir = rtrim($originDir, '/\\'); // Iterate in destination folder to remove obsolete entries if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) { $deleteIterator = $iterator; if (null === $deleteIterator) { $flags = \FilesystemIterator::SKIP_DOTS; $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST); } foreach ($deleteIterator as $file) { $origin = str_replace($targetDir, $originDir, $file->getPathname()); if (!$this->exists($origin)) { $this->remove($file); } } } $copyOnWindows = false; if (isset($options['copy_on_windows']) && !function_exists('symlink')) { $copyOnWindows = $options['copy_on_windows']; } if (null === $iterator) { $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS; $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST); } foreach ($iterator as $file) { $target = str_replace($originDir, $targetDir, $file->getPathname()); if ($copyOnWindows) { if (is_link($file) || is_file($file)) { $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); } elseif (is_dir($file)) { $this->mkdir($target); } else { throw new IOException(sprintf('Unable to guess "%s" file type.', $file)); } } else { if (is_link($file)) { $this->symlink($file, $target); } elseif (is_dir($file)) { $this->mkdir($target); } elseif (is_file($file)) { $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); } else { throw new IOException(sprintf('Unable to guess "%s" file type.', $file)); } } } } /** * Returns whether the file path is an absolute path. * * @param string $file A file path * * @return Boolean */ public function isAbsolutePath($file) { if (strspn($file, '/\\', 0, 1) || (strlen($file) > 3 && ctype_alpha($file[0]) && substr($file, 1, 1) === ':' && (strspn($file, '/\\', 2, 1)) ) || null !== parse_url($file, PHP_URL_SCHEME) ) { return true; } return false; } /** * @param mixed $files * * @return \Traversable */ private function toIterator($files) { if (!$files instanceof \Traversable) { $files = new \ArrayObject(is_array($files) ? $files : array($files)); } return $files; } /** * Atomically dumps content into a file. * * @param string $filename The file to be written to. * @param string $content The data to write into the file. * @param integer $mode The file mode (octal). * @throws IOException If the file cannot be written to. */ public function dumpFile($filename, $content, $mode = 0666) { $dir = dirname($filename); if (!is_dir($dir)) { $this->mkdir($dir); } elseif (!is_writable($dir)) { throw new IOException(sprintf('Unable to write in the %s directory\n', $dir)); } $tmpFile = tempnam($dir, basename($filename)); if (false === @file_put_contents($tmpFile, $content)) { throw new IOException(sprintf('Failed to write file "%s".', $filename)); } $this->rename($tmpFile, $filename, true); $this->chmod($filename, $mode); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem\Exception; /** * Exception class thrown when a filesystem operation failure happens * * @author Romain Neutron * * @api */ class IOException extends \RuntimeException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Filesystem\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Romain Neutron * * @api */ interface ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * A simple implementation of ContainerAwareInterface. * * @author Fabien Potencier * * @api */ abstract class ContainerAware implements ContainerAwareInterface { /** * @var ContainerInterface * * @api */ protected $container; /** * Sets the Container associated with this Controller. * * @param ContainerInterface $container A ContainerInterface instance * * @api */ public function setContainer(ContainerInterface $container = null) { $this->container = $container; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Reference represents a service reference. * * @author Fabien Potencier * * @api */ class Reference { private $id; private $invalidBehavior; private $strict; /** * Constructor. * * @param string $id The service identifier * @param int $invalidBehavior The behavior when the service does not exist * @param bool $strict Sets how this reference is validated * * @see Container */ public function __construct($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $strict = true) { $this->id = strtolower($id); $this->invalidBehavior = $invalidBehavior; $this->strict = $strict; } /** * __toString. * * @return string The service identifier */ public function __toString() { return $this->id; } /** * Returns the behavior to be used when the service does not exist. * * @return int */ public function getInvalidBehavior() { return $this->invalidBehavior; } /** * Returns true when this Reference is strict. * * @return bool */ public function isStrict() { return $this->strict; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\ExpressionLanguage\Expression; /** * SimpleXMLElement class. * * @author Fabien Potencier * * @deprecated Deprecated since version 2.5, to be removed in 3.0. */ class SimpleXMLElement extends \SimpleXMLElement { /** * Converts an attribute as a PHP type. * * @param string $name * * @return mixed */ public function getAttributeAsPhp($name) { return self::phpize($this[$name]); } /** * Returns arguments as valid PHP types. * * @param string $name * @param bool $lowercase * * @return mixed */ public function getArgumentsAsPhp($name, $lowercase = true) { $arguments = array(); foreach ($this->$name as $arg) { if (isset($arg['name'])) { $arg['key'] = (string) $arg['name']; } $key = isset($arg['key']) ? (string) $arg['key'] : (!$arguments ? 0 : max(array_keys($arguments)) + 1); // parameter keys are case insensitive if ('parameter' == $name && $lowercase) { $key = strtolower($key); } // this is used by DefinitionDecorator to overwrite a specific // argument of the parent definition if (isset($arg['index'])) { $key = 'index_'.$arg['index']; } switch ($arg['type']) { case 'service': $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; if (isset($arg['on-invalid']) && 'ignore' == $arg['on-invalid']) { $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; } elseif (isset($arg['on-invalid']) && 'null' == $arg['on-invalid']) { $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; } if (isset($arg['strict'])) { $strict = self::phpize($arg['strict']); } else { $strict = true; } $arguments[$key] = new Reference((string) $arg['id'], $invalidBehavior, $strict); break; case 'expression': $arguments[$key] = new Expression((string) $arg); break; case 'collection': $arguments[$key] = $arg->getArgumentsAsPhp($name, false); break; case 'string': $arguments[$key] = (string) $arg; break; case 'constant': $arguments[$key] = constant((string) $arg); break; default: $arguments[$key] = self::phpize($arg); } } return $arguments; } /** * Converts an xml value to a PHP type. * * @param mixed $value * * @return mixed */ public static function phpize($value) { return XmlUtils::phpize($value); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; /** * ContainerBuilder is a DI container that provides an API to easily describe services. * * @author Fabien Potencier * * @api */ class ContainerBuilder extends Container implements TaggedContainerInterface { /** * @var ExtensionInterface[] */ private $extensions = array(); /** * @var ExtensionInterface[] */ private $extensionsByNs = array(); /** * @var Definition[] */ private $definitions = array(); /** * @var Definition[] */ private $obsoleteDefinitions = array(); /** * @var Alias[] */ private $aliasDefinitions = array(); /** * @var ResourceInterface[] */ private $resources = array(); private $extensionConfigs = array(); /** * @var Compiler */ private $compiler; private $trackResources = true; /** * @var InstantiatorInterface|null */ private $proxyInstantiator; /** * @var ExpressionLanguage|null */ private $expressionLanguage; /** * @var ExpressionFunctionProviderInterface[] */ private $expressionLanguageProviders = array(); /** * Sets the track resources flag. * * If you are not using the loaders and therefore don't want * to depend on the Config component, set this flag to false. * * @param bool $track true if you want to track resources, false otherwise */ public function setResourceTracking($track) { $this->trackResources = (bool) $track; } /** * Checks if resources are tracked. * * @return bool true if resources are tracked, false otherwise */ public function isTrackingResources() { return $this->trackResources; } /** * Sets the instantiator to be used when fetching proxies. * * @param InstantiatorInterface $proxyInstantiator */ public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) { $this->proxyInstantiator = $proxyInstantiator; } /** * Registers an extension. * * @param ExtensionInterface $extension An extension instance * * @api */ public function registerExtension(ExtensionInterface $extension) { $this->extensions[$extension->getAlias()] = $extension; if (false !== $extension->getNamespace()) { $this->extensionsByNs[$extension->getNamespace()] = $extension; } } /** * Returns an extension by alias or namespace. * * @param string $name An alias or a namespace * * @return ExtensionInterface An extension instance * * @throws LogicException if the extension is not registered * * @api */ public function getExtension($name) { if (isset($this->extensions[$name])) { return $this->extensions[$name]; } if (isset($this->extensionsByNs[$name])) { return $this->extensionsByNs[$name]; } throw new LogicException(sprintf('Container extension "%s" is not registered', $name)); } /** * Returns all registered extensions. * * @return ExtensionInterface[] An array of ExtensionInterface * * @api */ public function getExtensions() { return $this->extensions; } /** * Checks if we have an extension. * * @param string $name The name of the extension * * @return bool If the extension exists * * @api */ public function hasExtension($name) { return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]); } /** * Returns an array of resources loaded to build this configuration. * * @return ResourceInterface[] An array of resources * * @api */ public function getResources() { return array_unique($this->resources); } /** * Adds a resource for this configuration. * * @param ResourceInterface $resource A resource instance * * @return ContainerBuilder The current instance * * @api */ public function addResource(ResourceInterface $resource) { if (!$this->trackResources) { return $this; } $this->resources[] = $resource; return $this; } /** * Sets the resources for this configuration. * * @param ResourceInterface[] $resources An array of resources * * @return ContainerBuilder The current instance * * @api */ public function setResources(array $resources) { if (!$this->trackResources) { return $this; } $this->resources = $resources; return $this; } /** * Adds the object class hierarchy as resources. * * @param object $object An object instance * * @return ContainerBuilder The current instance * * @api */ public function addObjectResource($object) { if ($this->trackResources) { $this->addClassResource(new \ReflectionClass($object)); } return $this; } /** * Adds the given class hierarchy as resources. * * @param \ReflectionClass $class * * @return ContainerBuilder The current instance */ public function addClassResource(\ReflectionClass $class) { if (!$this->trackResources) { return $this; } do { $this->addResource(new FileResource($class->getFileName())); } while ($class = $class->getParentClass()); return $this; } /** * Loads the configuration for an extension. * * @param string $extension The extension alias or namespace * @param array $values An array of values that customizes the extension * * @return ContainerBuilder The current instance * * @throws BadMethodCallException When this ContainerBuilder is frozen * @throws \LogicException if the container is frozen * * @api */ public function loadFromExtension($extension, array $values = array()) { if ($this->isFrozen()) { throw new BadMethodCallException('Cannot load from an extension on a frozen container.'); } $namespace = $this->getExtension($extension)->getAlias(); $this->extensionConfigs[$namespace][] = $values; return $this; } /** * Adds a compiler pass. * * @param CompilerPassInterface $pass A compiler pass * @param string $type The type of compiler pass * * @return ContainerBuilder The current instance * * @api */ public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) { $this->getCompiler()->addPass($pass, $type); $this->addObjectResource($pass); return $this; } /** * Returns the compiler pass config which can then be modified. * * @return PassConfig The compiler pass config * * @api */ public function getCompilerPassConfig() { return $this->getCompiler()->getPassConfig(); } /** * Returns the compiler. * * @return Compiler The compiler * * @api */ public function getCompiler() { if (null === $this->compiler) { $this->compiler = new Compiler(); } return $this->compiler; } /** * Returns all Scopes. * * @return array An array of scopes * * @api */ public function getScopes() { return $this->scopes; } /** * Returns all Scope children. * * @return array An array of scope children. * * @api */ public function getScopeChildren() { return $this->scopeChildren; } /** * Sets a service. * * @param string $id The service identifier * @param object $service The service instance * @param string $scope The scope * * @throws BadMethodCallException When this ContainerBuilder is frozen * * @api */ public function set($id, $service, $scope = self::SCOPE_CONTAINER) { $id = strtolower($id); if ($this->isFrozen()) { // setting a synthetic service on a frozen container is alright if ( (!isset($this->definitions[$id]) && !isset($this->obsoleteDefinitions[$id])) || (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic()) || (isset($this->obsoleteDefinitions[$id]) && !$this->obsoleteDefinitions[$id]->isSynthetic()) ) { throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id)); } } if (isset($this->definitions[$id])) { $this->obsoleteDefinitions[$id] = $this->definitions[$id]; } unset($this->definitions[$id], $this->aliasDefinitions[$id]); parent::set($id, $service, $scope); if (isset($this->obsoleteDefinitions[$id]) && $this->obsoleteDefinitions[$id]->isSynchronized()) { $this->synchronize($id); } } /** * Removes a service definition. * * @param string $id The service identifier * * @api */ public function removeDefinition($id) { unset($this->definitions[strtolower($id)]); } /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return bool true if the service is defined, false otherwise * * @api */ public function has($id) { $id = strtolower($id); return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id); } /** * Gets a service. * * @param string $id The service identifier * @param int $invalidBehavior The behavior when the service does not exist * * @return object The associated service * * @throws InvalidArgumentException when no definitions are available * @throws InactiveScopeException when the current scope is not active * @throws LogicException when a circular dependency is detected * @throws \Exception * * @see Reference * * @api */ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { $id = strtolower($id); if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { return $service; } if (!array_key_exists($id, $this->definitions) && isset($this->aliasDefinitions[$id])) { return $this->get($this->aliasDefinitions[$id]); } try { $definition = $this->getDefinition($id); } catch (InvalidArgumentException $e) { if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return; } throw $e; } $this->loading[$id] = true; try { $service = $this->createService($definition, $id); } catch (\Exception $e) { unset($this->loading[$id]); if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return; } throw $e; } unset($this->loading[$id]); return $service; } /** * Merges a ContainerBuilder with the current ContainerBuilder configuration. * * Service definitions overrides the current defined ones. * * But for parameters, they are overridden by the current ones. It allows * the parameters passed to the container constructor to have precedence * over the loaded ones. * * $container = new ContainerBuilder(array('foo' => 'bar')); * $loader = new LoaderXXX($container); * $loader->load('resource_name'); * $container->register('foo', new stdClass()); * * In the above example, even if the loaded resource defines a foo * parameter, the value will still be 'bar' as defined in the ContainerBuilder * constructor. * * @param ContainerBuilder $container The ContainerBuilder instance to merge. * * @throws BadMethodCallException When this ContainerBuilder is frozen * * @api */ public function merge(ContainerBuilder $container) { if ($this->isFrozen()) { throw new BadMethodCallException('Cannot merge on a frozen container.'); } $this->addDefinitions($container->getDefinitions()); $this->addAliases($container->getAliases()); $this->getParameterBag()->add($container->getParameterBag()->all()); if ($this->trackResources) { foreach ($container->getResources() as $resource) { $this->addResource($resource); } } foreach ($this->extensions as $name => $extension) { if (!isset($this->extensionConfigs[$name])) { $this->extensionConfigs[$name] = array(); } $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name)); } } /** * Returns the configuration array for the given extension. * * @param string $name The name of the extension * * @return array An array of configuration * * @api */ public function getExtensionConfig($name) { if (!isset($this->extensionConfigs[$name])) { $this->extensionConfigs[$name] = array(); } return $this->extensionConfigs[$name]; } /** * Prepends a config array to the configs of the given extension. * * @param string $name The name of the extension * @param array $config The config to set */ public function prependExtensionConfig($name, array $config) { if (!isset($this->extensionConfigs[$name])) { $this->extensionConfigs[$name] = array(); } array_unshift($this->extensionConfigs[$name], $config); } /** * Compiles the container. * * This method passes the container to compiler * passes whose job is to manipulate and optimize * the container. * * The main compiler passes roughly do four things: * * * The extension configurations are merged; * * Parameter values are resolved; * * The parameter bag is frozen; * * Extension loading is disabled. * * @api */ public function compile() { $compiler = $this->getCompiler(); if ($this->trackResources) { foreach ($compiler->getPassConfig()->getPasses() as $pass) { $this->addObjectResource($pass); } } $compiler->compile($this); if ($this->trackResources) { foreach ($this->definitions as $definition) { if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) { $this->addClassResource(new \ReflectionClass($class)); } } } $this->extensionConfigs = array(); parent::compile(); } /** * Gets all service ids. * * @return array An array of all defined service ids */ public function getServiceIds() { return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds())); } /** * Adds the service aliases. * * @param array $aliases An array of aliases * * @api */ public function addAliases(array $aliases) { foreach ($aliases as $alias => $id) { $this->setAlias($alias, $id); } } /** * Sets the service aliases. * * @param array $aliases An array of aliases * * @api */ public function setAliases(array $aliases) { $this->aliasDefinitions = array(); $this->addAliases($aliases); } /** * Sets an alias for an existing service. * * @param string $alias The alias to create * @param string|Alias $id The service to alias * * @throws InvalidArgumentException if the id is not a string or an Alias * @throws InvalidArgumentException if the alias is for itself * * @api */ public function setAlias($alias, $id) { $alias = strtolower($alias); if (is_string($id)) { $id = new Alias($id); } elseif (!$id instanceof Alias) { throw new InvalidArgumentException('$id must be a string, or an Alias object.'); } if ($alias === (string) $id) { throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias)); } unset($this->definitions[$alias]); $this->aliasDefinitions[$alias] = $id; } /** * Removes an alias. * * @param string $alias The alias to remove * * @api */ public function removeAlias($alias) { unset($this->aliasDefinitions[strtolower($alias)]); } /** * Returns true if an alias exists under the given identifier. * * @param string $id The service identifier * * @return bool true if the alias exists, false otherwise * * @api */ public function hasAlias($id) { return isset($this->aliasDefinitions[strtolower($id)]); } /** * Gets all defined aliases. * * @return Alias[] An array of aliases * * @api */ public function getAliases() { return $this->aliasDefinitions; } /** * Gets an alias. * * @param string $id The service identifier * * @return Alias An Alias instance * * @throws InvalidArgumentException if the alias does not exist * * @api */ public function getAlias($id) { $id = strtolower($id); if (!isset($this->aliasDefinitions[$id])) { throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id)); } return $this->aliasDefinitions[$id]; } /** * Registers a service definition. * * This methods allows for simple registration of service definition * with a fluid interface. * * @param string $id The service identifier * @param string $class The service class * * @return Definition A Definition instance * * @api */ public function register($id, $class = null) { return $this->setDefinition($id, new Definition($class)); } /** * Adds the service definitions. * * @param Definition[] $definitions An array of service definitions * * @api */ public function addDefinitions(array $definitions) { foreach ($definitions as $id => $definition) { $this->setDefinition($id, $definition); } } /** * Sets the service definitions. * * @param Definition[] $definitions An array of service definitions * * @api */ public function setDefinitions(array $definitions) { $this->definitions = array(); $this->addDefinitions($definitions); } /** * Gets all service definitions. * * @return Definition[] An array of Definition instances * * @api */ public function getDefinitions() { return $this->definitions; } /** * Sets a service definition. * * @param string $id The service identifier * @param Definition $definition A Definition instance * * @return Definition the service definition * * @throws BadMethodCallException When this ContainerBuilder is frozen * * @api */ public function setDefinition($id, Definition $definition) { if ($this->isFrozen()) { throw new BadMethodCallException('Adding definition to a frozen container is not allowed'); } $id = strtolower($id); unset($this->aliasDefinitions[$id]); return $this->definitions[$id] = $definition; } /** * Returns true if a service definition exists under the given identifier. * * @param string $id The service identifier * * @return bool true if the service definition exists, false otherwise * * @api */ public function hasDefinition($id) { return array_key_exists(strtolower($id), $this->definitions); } /** * Gets a service definition. * * @param string $id The service identifier * * @return Definition A Definition instance * * @throws InvalidArgumentException if the service definition does not exist * * @api */ public function getDefinition($id) { $id = strtolower($id); if (!array_key_exists($id, $this->definitions)) { throw new InvalidArgumentException(sprintf('The service definition "%s" does not exist.', $id)); } return $this->definitions[$id]; } /** * Gets a service definition by id or alias. * * The method "unaliases" recursively to return a Definition instance. * * @param string $id The service identifier or alias * * @return Definition A Definition instance * * @throws InvalidArgumentException if the service definition does not exist * * @api */ public function findDefinition($id) { $id = strtolower($id); while (isset($this->aliasDefinitions[$id])) { $id = (string) $this->aliasDefinitions[$id]; } return $this->getDefinition($id); } /** * Creates a service for a service definition. * * @param Definition $definition A service definition instance * @param string $id The service identifier * @param bool $tryProxy Whether to try proxying the service with a lazy proxy * * @return object The service described by the service definition * * @throws RuntimeException When the scope is inactive * @throws RuntimeException When the factory definition is incomplete * @throws RuntimeException When the service is a synthetic service * @throws InvalidArgumentException When configure callable is not callable * * @internal this method is public because of PHP 5.3 limitations, do not use it explicitly in your code */ public function createService(Definition $definition, $id, $tryProxy = true) { if ($definition->isSynthetic()) { throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); } if ($tryProxy && $definition->isLazy()) { $container = $this; $proxy = $this ->getProxyInstantiator() ->instantiateProxy( $container, $definition, $id, function () use ($definition, $id, $container) { return $container->createService($definition, $id, false); } ); $this->shareService($definition, $proxy, $id); return $proxy; } $parameterBag = $this->getParameterBag(); if (null !== $definition->getFile()) { require_once $parameterBag->resolveValue($definition->getFile()); } $arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments()))); if (null !== $factory = $definition->getFactory()) { if (is_array($factory)) { $factory = array($this->resolveServices($parameterBag->resolveValue($factory[0])), $factory[1]); } elseif (!is_string($factory)) { throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id)); } $service = call_user_func_array($factory, $arguments); } elseif (null !== $definition->getFactoryMethod()) { if (null !== $definition->getFactoryClass()) { $factory = $parameterBag->resolveValue($definition->getFactoryClass()); } elseif (null !== $definition->getFactoryService()) { $factory = $this->get($parameterBag->resolveValue($definition->getFactoryService())); } else { throw new RuntimeException(sprintf('Cannot create service "%s" from factory method without a factory service or factory class.', $id)); } $service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments); } else { $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass())); $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); } if ($tryProxy || !$definition->isLazy()) { // share only if proxying failed, or if not a proxy $this->shareService($definition, $service, $id); } foreach ($definition->getMethodCalls() as $call) { $this->callMethod($service, $call); } $properties = $this->resolveServices($parameterBag->resolveValue($definition->getProperties())); foreach ($properties as $name => $value) { $service->$name = $value; } if ($callable = $definition->getConfigurator()) { if (is_array($callable)) { $callable[0] = $callable[0] instanceof Reference ? $this->get((string) $callable[0]) : $parameterBag->resolveValue($callable[0]); } if (!is_callable($callable)) { throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service))); } call_user_func($callable, $service); } return $service; } /** * Replaces service references by the real service instance and evaluates expressions. * * @param mixed $value A value * * @return mixed The same value with all service references replaced by * the real service instances and all expressions evaluated */ public function resolveServices($value) { if (is_array($value)) { $value = array_map(array($this, 'resolveServices'), $value); } elseif ($value instanceof Reference) { $value = $this->get((string) $value, $value->getInvalidBehavior()); } elseif ($value instanceof Definition) { $value = $this->createService($value, null); } elseif ($value instanceof Expression) { $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this)); } return $value; } /** * Returns service ids for a given tag. * * Example: * * $container->register('foo')->addTag('my.tag', array('hello' => 'world')); * * $serviceIds = $container->findTaggedServiceIds('my.tag'); * foreach ($serviceIds as $serviceId => $tags) { * foreach ($tags as $tag) { * echo $tag['hello']; * } * } * * @param string $name The tag name * * @return array An array of tags with the tagged service as key, holding a list of attribute arrays. * * @api */ public function findTaggedServiceIds($name) { $tags = array(); foreach ($this->getDefinitions() as $id => $definition) { if ($definition->hasTag($name)) { $tags[$id] = $definition->getTag($name); } } return $tags; } /** * Returns all tags the defined services use. * * @return array An array of tags */ public function findTags() { $tags = array(); foreach ($this->getDefinitions() as $id => $definition) { $tags = array_merge(array_keys($definition->getTags()), $tags); } return array_unique($tags); } public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) { $this->expressionLanguageProviders[] = $provider; } /** * @return ExpressionFunctionProviderInterface[] */ public function getExpressionLanguageProviders() { return $this->expressionLanguageProviders; } /** * Returns the Service Conditionals. * * @param mixed $value An array of conditionals to return. * * @return array An array of Service conditionals */ public static function getServiceConditionals($value) { $services = array(); if (is_array($value)) { foreach ($value as $v) { $services = array_unique(array_merge($services, self::getServiceConditionals($v))); } } elseif ($value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE) { $services[] = (string) $value; } return $services; } /** * Retrieves the currently set proxy instantiator or instantiates one. * * @return InstantiatorInterface */ private function getProxyInstantiator() { if (!$this->proxyInstantiator) { $this->proxyInstantiator = new RealServiceInstantiator(); } return $this->proxyInstantiator; } /** * Synchronizes a service change. * * This method updates all services that depend on the given * service by calling all methods referencing it. * * @param string $id A service id */ private function synchronize($id) { foreach ($this->definitions as $definitionId => $definition) { // only check initialized services if (!$this->initialized($definitionId)) { continue; } foreach ($definition->getMethodCalls() as $call) { foreach ($call[1] as $argument) { if ($argument instanceof Reference && $id == (string) $argument) { $this->callMethod($this->get($definitionId), $call); } } } } } private function callMethod($service, $call) { $services = self::getServiceConditionals($call[1]); foreach ($services as $s) { if (!$this->has($s)) { return; } } call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1]))); } /** * Shares a given service in the container. * * @param Definition $definition * @param mixed $service * @param string $id * * @throws InactiveScopeException */ private function shareService(Definition $definition, $service, $id) { if (self::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) { throw new InactiveScopeException($id, $scope); } $this->services[$lowerId = strtolower($id)] = $service; if (self::SCOPE_CONTAINER !== $scope) { $this->scopedServices[$scope][$lowerId] = $service; } } } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); } return $this->expressionLanguage; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; /** * ConfigurationExtensionInterface is the interface implemented by container extension classes. * * @author Kevin Bond */ interface ConfigurationExtensionInterface { /** * Returns extension configuration. * * @param array $config An array of configuration values * @param ContainerBuilder $container A ContainerBuilder instance * * @return ConfigurationInterface|null The configuration or null */ public function getConfiguration(array $config, ContainerBuilder $container); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Config\Definition\ConfigurationInterface; /** * Provides useful features shared by many extensions. * * @author Fabien Potencier */ abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface { /** * Returns the base path for the XSD files. * * @return string The XSD base path */ public function getXsdValidationBasePath() { return false; } /** * Returns the namespace to be used for this extension (XML namespace). * * @return string The XML namespace */ public function getNamespace() { return 'http://example.org/schema/dic/'.$this->getAlias(); } /** * Returns the recommended alias to use in XML. * * This alias is also the mandatory prefix to use when using YAML. * * This convention is to remove the "Extension" postfix from the class * name and then lowercase and underscore the result. So: * * AcmeHelloExtension * * becomes * * acme_hello * * This can be overridden in a sub-class to specify the alias manually. * * @return string The alias * * @throws BadMethodCallException When the extension name does not follow conventions */ public function getAlias() { $className = get_class($this); if (substr($className, -9) != 'Extension') { throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.'); } $classBaseName = substr(strrchr($className, '\\'), 1, -9); return Container::underscore($classBaseName); } /** * {@inheritdoc} */ public function getConfiguration(array $config, ContainerBuilder $container) { $reflected = new \ReflectionClass($this); $namespace = $reflected->getNamespaceName(); $class = $namespace.'\\Configuration'; if (class_exists($class)) { $r = new \ReflectionClass($class); $container->addResource(new FileResource($r->getFileName())); if (!method_exists($class, '__construct')) { $configuration = new $class(); return $configuration; } } } final protected function processConfiguration(ConfigurationInterface $configuration, array $configs) { $processor = new Processor(); return $processor->processConfiguration($configuration, $configs); } /** * @param ContainerBuilder $container * @param array $config * * @return bool Whether the configuration is enabled * * @throws InvalidArgumentException When the config is not enableable */ protected function isConfigEnabled(ContainerBuilder $container, array $config) { if (!array_key_exists('enabled', $config)) { throw new InvalidArgumentException("The config array has no 'enabled' key."); } return (bool) $container->getParameterBag()->resolveValue($config['enabled']); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; interface PrependExtensionInterface { /** * Allow an extension to prepend the extension configurations. * * @param ContainerBuilder $container */ public function prepend(ContainerBuilder $container); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * ExtensionInterface is the interface implemented by container extension classes. * * @author Fabien Potencier * * @api */ interface ExtensionInterface { /** * Loads a specific configuration. * * @param array $config An array of configuration values * @param ContainerBuilder $container A ContainerBuilder instance * * @throws \InvalidArgumentException When provided tag is not defined in this extension * * @api */ public function load(array $config, ContainerBuilder $container); /** * Returns the namespace to be used for this extension (XML namespace). * * @return string The XML namespace * * @api */ public function getNamespace(); /** * Returns the base path for the XSD files. * * @return string The XSD base path * * @api */ public function getXsdValidationBasePath(); /** * Returns the recommended alias to use in XML. * * This alias is also the mandatory prefix to use when using YAML. * * @return string The alias * * @api */ public function getAlias(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * ContainerAware trait. * * @author Fabien Potencier */ trait ContainerAwareTrait { /** * @var ContainerInterface */ protected $container; /** * Sets the Container associated with this Controller. * * @param ContainerInterface $container A ContainerInterface instance */ public function setContainer(ContainerInterface $container = null) { $this->container = $container; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * @api */ class Alias { private $id; private $public; /** * Constructor. * * @param string $id Alias identifier * @param bool $public If this alias is public * * @api */ public function __construct($id, $public = true) { $this->id = strtolower($id); $this->public = $public; } /** * Checks if this DI Alias should be public or not. * * @return bool * * @api */ public function isPublic() { return $this->public; } /** * Sets if this Alias is public. * * @param bool $boolean If this Alias should be public * * @api */ public function setPublic($boolean) { $this->public = (bool) $boolean; } /** * Returns the Id of this alias. * * @return string The alias id * * @api */ public function __toString() { return $this->id; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Scope Interface. * * @author Johannes M. Schmitt * * @api */ interface ScopeInterface { /** * @api */ public function getName(); /** * @api */ public function getParentName(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Parameter represents a parameter reference. * * @author Fabien Potencier * * @api */ class Parameter { private $id; /** * Constructor. * * @param string $id The parameter key */ public function __construct($id) { $this->id = $id; } /** * __toString. * * @return string The parameter key */ public function __toString() { return (string) $this->id; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Represents a variable. * * $var = new Variable('a'); * * will be dumped as * * $a * * by the PHP dumper. * * @author Johannes M. Schmitt */ class Variable { private $name; /** * Constructor. * * @param string $name */ public function __construct($name) { $this->name = $name; } /** * Converts the object to a string. * * @return string */ public function __toString() { return $this->name; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * Scope class. * * @author Johannes M. Schmitt * * @api */ class Scope implements ScopeInterface { private $name; private $parentName; /** * @api */ public function __construct($name, $parentName = ContainerInterface::SCOPE_CONTAINER) { $this->name = $name; $this->parentName = $parentName; } /** * @api */ public function getName() { return $this->name; } /** * @api */ public function getParentName() { return $this->parentName; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; /** * Definition represents a service definition. * * @author Fabien Potencier * * @api */ class Definition { private $class; private $file; private $factory; private $factoryClass; private $factoryMethod; private $factoryService; private $scope = ContainerInterface::SCOPE_CONTAINER; private $properties = array(); private $calls = array(); private $configurator; private $tags = array(); private $public = true; private $synthetic = false; private $abstract = false; private $synchronized = false; private $lazy = false; private $decoratedService; protected $arguments; /** * Constructor. * * @param string|null $class The service class * @param array $arguments An array of arguments to pass to the service constructor * * @api */ public function __construct($class = null, array $arguments = array()) { $this->class = $class; $this->arguments = $arguments; } /** * Sets a factory. * * @param string|array $factory A PHP function or an array containing a class/Reference and a method to call * * @return Definition The current instance */ public function setFactory($factory) { if (is_string($factory) && strpos($factory, '::') !== false) { $factory = explode('::', $factory, 2); } $this->factory = $factory; return $this; } /** * Gets the factory. * * @return string|array The PHP function or an array containing a class/Reference and a method to call */ public function getFactory() { return $this->factory; } /** * Sets the name of the class that acts as a factory using the factory method, * which will be invoked statically. * * @param string $factoryClass The factory class name * * @return Definition The current instance * * @api * @deprecated Deprecated since version 2.6, to be removed in 3.0. */ public function setFactoryClass($factoryClass) { $this->factoryClass = $factoryClass; return $this; } /** * Gets the factory class. * * @return string|null The factory class name * * @api * @deprecated Deprecated since version 2.6, to be removed in 3.0. */ public function getFactoryClass() { return $this->factoryClass; } /** * Sets the factory method able to create an instance of this class. * * @param string $factoryMethod The factory method name * * @return Definition The current instance * * @api * @deprecated Deprecated since version 2.6, to be removed in 3.0. */ public function setFactoryMethod($factoryMethod) { $this->factoryMethod = $factoryMethod; return $this; } /** * Sets the service that this service is decorating. * * @param null|string $id The decorated service id, use null to remove decoration * @param null|string $renamedId The new decorated service id * * @return Definition The current instance * * @throws InvalidArgumentException In case the decorated service id and the new decorated service id are equals. */ public function setDecoratedService($id, $renamedId = null) { if ($renamedId && $id == $renamedId) { throw new \InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id)); } if (null === $id) { $this->decoratedService = null; } else { $this->decoratedService = array($id, $renamedId); } return $this; } /** * Gets the service that decorates this service. * * @return null|array An array composed of the decorated service id and the new id for it, null if no service is decorated */ public function getDecoratedService() { return $this->decoratedService; } /** * Gets the factory method. * * @return string|null The factory method name * * @api * @deprecated Deprecated since version 2.6, to be removed in 3.0. */ public function getFactoryMethod() { return $this->factoryMethod; } /** * Sets the name of the service that acts as a factory using the factory method. * * @param string $factoryService The factory service id * * @return Definition The current instance * * @api * @deprecated Deprecated since version 2.6, to be removed in 3.0. */ public function setFactoryService($factoryService) { $this->factoryService = $factoryService; return $this; } /** * Gets the factory service id. * * @return string|null The factory service id * * @api * @deprecated Deprecated since version 2.6, to be removed in 3.0. */ public function getFactoryService() { return $this->factoryService; } /** * Sets the service class. * * @param string $class The service class * * @return Definition The current instance * * @api */ public function setClass($class) { $this->class = $class; return $this; } /** * Gets the service class. * * @return string|null The service class * * @api */ public function getClass() { return $this->class; } /** * Sets the arguments to pass to the service constructor/factory method. * * @param array $arguments An array of arguments * * @return Definition The current instance * * @api */ public function setArguments(array $arguments) { $this->arguments = $arguments; return $this; } /** * @api */ public function setProperties(array $properties) { $this->properties = $properties; return $this; } /** * @api */ public function getProperties() { return $this->properties; } /** * @api */ public function setProperty($name, $value) { $this->properties[$name] = $value; return $this; } /** * Adds an argument to pass to the service constructor/factory method. * * @param mixed $argument An argument * * @return Definition The current instance * * @api */ public function addArgument($argument) { $this->arguments[] = $argument; return $this; } /** * Sets a specific argument. * * @param int $index * @param mixed $argument * * @return Definition The current instance * * @throws OutOfBoundsException When the replaced argument does not exist * * @api */ public function replaceArgument($index, $argument) { if ($index < 0 || $index > count($this->arguments) - 1) { throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1)); } $this->arguments[$index] = $argument; return $this; } /** * Gets the arguments to pass to the service constructor/factory method. * * @return array The array of arguments * * @api */ public function getArguments() { return $this->arguments; } /** * Gets an argument to pass to the service constructor/factory method. * * @param int $index * * @return mixed The argument value * * @throws OutOfBoundsException When the argument does not exist * * @api */ public function getArgument($index) { if ($index < 0 || $index > count($this->arguments) - 1) { throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1)); } return $this->arguments[$index]; } /** * Sets the methods to call after service initialization. * * @param array $calls An array of method calls * * @return Definition The current instance * * @api */ public function setMethodCalls(array $calls = array()) { $this->calls = array(); foreach ($calls as $call) { $this->addMethodCall($call[0], $call[1]); } return $this; } /** * Adds a method to call after service initialization. * * @param string $method The method name to call * @param array $arguments An array of arguments to pass to the method call * * @return Definition The current instance * * @throws InvalidArgumentException on empty $method param * * @api */ public function addMethodCall($method, array $arguments = array()) { if (empty($method)) { throw new InvalidArgumentException(sprintf('Method name cannot be empty.')); } $this->calls[] = array($method, $arguments); return $this; } /** * Removes a method to call after service initialization. * * @param string $method The method name to remove * * @return Definition The current instance * * @api */ public function removeMethodCall($method) { foreach ($this->calls as $i => $call) { if ($call[0] === $method) { unset($this->calls[$i]); break; } } return $this; } /** * Check if the current definition has a given method to call after service initialization. * * @param string $method The method name to search for * * @return bool * * @api */ public function hasMethodCall($method) { foreach ($this->calls as $call) { if ($call[0] === $method) { return true; } } return false; } /** * Gets the methods to call after service initialization. * * @return array An array of method calls * * @api */ public function getMethodCalls() { return $this->calls; } /** * Sets tags for this definition. * * @param array $tags * * @return Definition the current instance * * @api */ public function setTags(array $tags) { $this->tags = $tags; return $this; } /** * Returns all tags. * * @return array An array of tags * * @api */ public function getTags() { return $this->tags; } /** * Gets a tag by name. * * @param string $name The tag name * * @return array An array of attributes * * @api */ public function getTag($name) { return isset($this->tags[$name]) ? $this->tags[$name] : array(); } /** * Adds a tag for this definition. * * @param string $name The tag name * @param array $attributes An array of attributes * * @return Definition The current instance * * @api */ public function addTag($name, array $attributes = array()) { $this->tags[$name][] = $attributes; return $this; } /** * Whether this definition has a tag with the given name. * * @param string $name * * @return bool * * @api */ public function hasTag($name) { return isset($this->tags[$name]); } /** * Clears all tags for a given name. * * @param string $name The tag name * * @return Definition */ public function clearTag($name) { if (isset($this->tags[$name])) { unset($this->tags[$name]); } return $this; } /** * Clears the tags for this definition. * * @return Definition The current instance * * @api */ public function clearTags() { $this->tags = array(); return $this; } /** * Sets a file to require before creating the service. * * @param string $file A full pathname to include * * @return Definition The current instance * * @api */ public function setFile($file) { $this->file = $file; return $this; } /** * Gets the file to require before creating the service. * * @return string|null The full pathname to include * * @api */ public function getFile() { return $this->file; } /** * Sets the scope of the service. * * @param string $scope Whether the service must be shared or not * * @return Definition The current instance * * @api */ public function setScope($scope) { $this->scope = $scope; return $this; } /** * Returns the scope of the service. * * @return string * * @api */ public function getScope() { return $this->scope; } /** * Sets the visibility of this service. * * @param bool $boolean * * @return Definition The current instance * * @api */ public function setPublic($boolean) { $this->public = (bool) $boolean; return $this; } /** * Whether this service is public facing. * * @return bool * * @api */ public function isPublic() { return $this->public; } /** * Sets the synchronized flag of this service. * * @param bool $boolean * * @return Definition The current instance * * @api */ public function setSynchronized($boolean) { $this->synchronized = (bool) $boolean; return $this; } /** * Whether this service is synchronized. * * @return bool * * @api */ public function isSynchronized() { return $this->synchronized; } /** * Sets the lazy flag of this service. * * @param bool $lazy * * @return Definition The current instance */ public function setLazy($lazy) { $this->lazy = (bool) $lazy; return $this; } /** * Whether this service is lazy. * * @return bool */ public function isLazy() { return $this->lazy; } /** * Sets whether this definition is synthetic, that is not constructed by the * container, but dynamically injected. * * @param bool $boolean * * @return Definition the current instance * * @api */ public function setSynthetic($boolean) { $this->synthetic = (bool) $boolean; return $this; } /** * Whether this definition is synthetic, that is not constructed by the * container, but dynamically injected. * * @return bool * * @api */ public function isSynthetic() { return $this->synthetic; } /** * Whether this definition is abstract, that means it merely serves as a * template for other definitions. * * @param bool $boolean * * @return Definition the current instance * * @api */ public function setAbstract($boolean) { $this->abstract = (bool) $boolean; return $this; } /** * Whether this definition is abstract, that means it merely serves as a * template for other definitions. * * @return bool * * @api */ public function isAbstract() { return $this->abstract; } /** * Sets a configurator to call after the service is fully initialized. * * @param callable $callable A PHP callable * * @return Definition The current instance * * @api */ public function setConfigurator($callable) { $this->configurator = $callable; return $this; } /** * Gets the configurator to call after the service is fully initialized. * * @return callable|null The PHP callable to call * * @api */ public function getConfigurator() { return $this->configurator; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; /** * DumperInterface is the interface implemented by service container dumper classes. * * @author Fabien Potencier * * @api */ interface DumperInterface { /** * Dumps the service container. * * @param array $options An array of options * * @return string The representation of the service container * * @api */ public function dump(array $options = array()); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\Variable; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; use Symfony\Component\DependencyInjection\ExpressionLanguage; use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; /** * PhpDumper dumps a service container as a PHP class. * * @author Fabien Potencier * @author Johannes M. Schmitt * * @api */ class PhpDumper extends Dumper { /** * Characters that might appear in the generated variable name as first character. * * @var string */ const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz'; /** * Characters that might appear in the generated variable name as any but the first character. * * @var string */ const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_'; private $inlinedDefinitions; private $definitionVariables; private $referenceVariables; private $variableCount; private $reservedVariables = array('instance', 'class'); private $expressionLanguage; private $targetDirRegex; private $targetDirMaxMatches; /** * @var ExpressionFunctionProviderInterface[] */ private $expressionLanguageProviders = array(); /** * @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface */ private $proxyDumper; /** * {@inheritdoc} * * @api */ public function __construct(ContainerBuilder $container) { parent::__construct($container); $this->inlinedDefinitions = new \SplObjectStorage(); } /** * Sets the dumper to be used when dumping proxies in the generated container. * * @param ProxyDumper $proxyDumper */ public function setProxyDumper(ProxyDumper $proxyDumper) { $this->proxyDumper = $proxyDumper; } /** * Dumps the service container as a PHP class. * * Available options: * * * class: The class name * * base_class: The base class name * * namespace: The class namespace * * @param array $options An array of options * * @return string A PHP class representing of the service container * * @api */ public function dump(array $options = array()) { $this->targetDirRegex = null; $options = array_merge(array( 'class' => 'ProjectServiceContainer', 'base_class' => 'Container', 'namespace' => '', ), $options); if (!empty($options['file']) && is_dir($dir = dirname($options['file']))) { // Build a regexp where the first root dirs are mandatory, // but every other sub-dir is optional up to the full path in $dir // Mandate at least 2 root dirs and not more that 5 optional dirs. $dir = explode(DIRECTORY_SEPARATOR, realpath($dir)); $i = count($dir); if (3 <= $i) { $regex = ''; $lastOptionalDir = $i > 8 ? $i - 5 : 3; $this->targetDirMaxMatches = $i - $lastOptionalDir; while (--$i >= $lastOptionalDir) { $regex = sprintf('(%s%s)?', preg_quote(DIRECTORY_SEPARATOR.$dir[$i], '#'), $regex); } do { $regex = preg_quote(DIRECTORY_SEPARATOR.$dir[$i], '#').$regex; } while (0 < --$i); $this->targetDirRegex = '#'.preg_quote($dir[0], '#').$regex.'#'; } } $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']); if ($this->container->isFrozen()) { $code .= $this->addFrozenConstructor(); $code .= $this->addFrozenCompile(); } else { $code .= $this->addConstructor(); } $code .= $this->addServices(). $this->addDefaultParametersMethod(). $this->endClass(). $this->addProxyClasses() ; $this->targetDirRegex = null; return $code; } /** * Retrieves the currently set proxy dumper or instantiates one. * * @return ProxyDumper */ private function getProxyDumper() { if (!$this->proxyDumper) { $this->proxyDumper = new NullDumper(); } return $this->proxyDumper; } /** * Generates Service local temp variables. * * @param string $cId * @param string $definition * * @return string */ private function addServiceLocalTempVariables($cId, $definition) { static $template = " \$%s = %s;\n"; $localDefinitions = array_merge( array($definition), $this->getInlinedDefinitions($definition) ); $calls = $behavior = array(); foreach ($localDefinitions as $iDefinition) { $this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior); $this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior); $this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior); $this->getServiceCallsFromArguments(array($iDefinition->getConfigurator()), $calls, $behavior); $this->getServiceCallsFromArguments(array($iDefinition->getFactory()), $calls, $behavior); } $code = ''; foreach ($calls as $id => $callCount) { if ('service_container' === $id || $id === $cId) { continue; } if ($callCount > 1) { $name = $this->getNextVariableName(); $this->referenceVariables[$id] = new Variable($name); if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id]) { $code .= sprintf($template, $name, $this->getServiceCall($id)); } else { $code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, ContainerInterface::NULL_ON_INVALID_REFERENCE))); } } } if ('' !== $code) { $code .= "\n"; } return $code; } /** * Generates code for the proxies to be attached after the container class. * * @return string */ private function addProxyClasses() { /* @var $definitions Definition[] */ $definitions = array_filter( $this->container->getDefinitions(), array($this->getProxyDumper(), 'isProxyCandidate') ); $code = ''; foreach ($definitions as $definition) { $code .= "\n".$this->getProxyDumper()->getProxyCode($definition); } return $code; } /** * Generates the require_once statement for service includes. * * @param string $id The service id * @param Definition $definition * * @return string */ private function addServiceInclude($id, $definition) { $template = " require_once %s;\n"; $code = ''; if (null !== $file = $definition->getFile()) { $code .= sprintf($template, $this->dumpValue($file)); } foreach ($this->getInlinedDefinitions($definition) as $definition) { if (null !== $file = $definition->getFile()) { $code .= sprintf($template, $this->dumpValue($file)); } } if ('' !== $code) { $code .= "\n"; } return $code; } /** * Generates the inline definition of a service. * * @param string $id * @param Definition $definition * * @return string * * @throws RuntimeException When the factory definition is incomplete * @throws ServiceCircularReferenceException When a circular reference is detected */ private function addServiceInlinedDefinitions($id, $definition) { $code = ''; $variableMap = $this->definitionVariables; $nbOccurrences = new \SplObjectStorage(); $processed = new \SplObjectStorage(); $inlinedDefinitions = $this->getInlinedDefinitions($definition); foreach ($inlinedDefinitions as $definition) { if (false === $nbOccurrences->contains($definition)) { $nbOccurrences->offsetSet($definition, 1); } else { $i = $nbOccurrences->offsetGet($definition); $nbOccurrences->offsetSet($definition, $i + 1); } } foreach ($inlinedDefinitions as $sDefinition) { if ($processed->contains($sDefinition)) { continue; } $processed->offsetSet($sDefinition); $class = $this->dumpValue($sDefinition->getClass()); if ($nbOccurrences->offsetGet($sDefinition) > 1 || $sDefinition->getMethodCalls() || $sDefinition->getProperties() || null !== $sDefinition->getConfigurator() || false !== strpos($class, '$')) { $name = $this->getNextVariableName(); $variableMap->offsetSet($sDefinition, new Variable($name)); // a construct like: // $a = new ServiceA(ServiceB $b); $b = new ServiceB(ServiceA $a); // this is an indication for a wrong implementation, you can circumvent this problem // by setting up your service structure like this: // $b = new ServiceB(); // $a = new ServiceA(ServiceB $b); // $b->setServiceA(ServiceA $a); if ($this->hasReference($id, $sDefinition->getArguments())) { throw new ServiceCircularReferenceException($id, array($id)); } $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = '); if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) { $code .= $this->addServiceMethodCalls(null, $sDefinition, $name); $code .= $this->addServiceProperties(null, $sDefinition, $name); $code .= $this->addServiceConfigurator(null, $sDefinition, $name); } $code .= "\n"; } } return $code; } /** * Adds the service return statement. * * @param string $id Service id * @param Definition $definition * * @return string */ private function addServiceReturn($id, $definition) { if ($this->isSimpleInstance($id, $definition)) { return " }\n"; } return "\n return \$instance;\n }\n"; } /** * Generates the service instance. * * @param string $id * @param Definition $definition * * @return string * * @throws InvalidArgumentException * @throws RuntimeException */ private function addServiceInstance($id, $definition) { $class = $this->dumpValue($definition->getClass()); if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id)); } $simple = $this->isSimpleInstance($id, $definition); $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); $instantiation = ''; if (!$isProxyCandidate && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { $instantiation = "\$this->services['$id'] = ".($simple ? '' : '$instance'); } elseif (!$isProxyCandidate && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) { $instantiation = "\$this->services['$id'] = \$this->scopedServices['$scope']['$id'] = ".($simple ? '' : '$instance'); } elseif (!$simple) { $instantiation = '$instance'; } $return = ''; if ($simple) { $return = 'return '; } else { $instantiation .= ' = '; } $code = $this->addNewInstance($id, $definition, $return, $instantiation); if (!$simple) { $code .= "\n"; } return $code; } /** * Checks if the definition is a simple instance. * * @param string $id * @param Definition $definition * * @return bool */ private function isSimpleInstance($id, $definition) { foreach (array_merge(array($definition), $this->getInlinedDefinitions($definition)) as $sDefinition) { if ($definition !== $sDefinition && !$this->hasReference($id, $sDefinition->getMethodCalls())) { continue; } if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator()) { return false; } } return true; } /** * Adds method calls to a service definition. * * @param string $id * @param Definition $definition * @param string $variableName * * @return string */ private function addServiceMethodCalls($id, $definition, $variableName = 'instance') { $calls = ''; foreach ($definition->getMethodCalls() as $call) { $arguments = array(); foreach ($call[1] as $value) { $arguments[] = $this->dumpValue($value); } $calls .= $this->wrapServiceConditionals($call[1], sprintf(" \$%s->%s(%s);\n", $variableName, $call[0], implode(', ', $arguments))); } return $calls; } private function addServiceProperties($id, $definition, $variableName = 'instance') { $code = ''; foreach ($definition->getProperties() as $name => $value) { $code .= sprintf(" \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value)); } return $code; } /** * Generates the inline definition setup. * * @param string $id * @param Definition $definition * * @return string * * @throws ServiceCircularReferenceException when the container contains a circular reference */ private function addServiceInlinedDefinitionsSetup($id, $definition) { $this->referenceVariables[$id] = new Variable('instance'); $code = ''; $processed = new \SplObjectStorage(); foreach ($this->getInlinedDefinitions($definition) as $iDefinition) { if ($processed->contains($iDefinition)) { continue; } $processed->offsetSet($iDefinition); if (!$this->hasReference($id, $iDefinition->getMethodCalls(), true) && !$this->hasReference($id, $iDefinition->getProperties(), true)) { continue; } // if the instance is simple, the return statement has already been generated // so, the only possible way to get there is because of a circular reference if ($this->isSimpleInstance($id, $definition)) { throw new ServiceCircularReferenceException($id, array($id)); } $name = (string) $this->definitionVariables->offsetGet($iDefinition); $code .= $this->addServiceMethodCalls(null, $iDefinition, $name); $code .= $this->addServiceProperties(null, $iDefinition, $name); $code .= $this->addServiceConfigurator(null, $iDefinition, $name); } if ('' !== $code) { $code .= "\n"; } return $code; } /** * Adds configurator definition. * * @param string $id * @param Definition $definition * @param string $variableName * * @return string */ private function addServiceConfigurator($id, $definition, $variableName = 'instance') { if (!$callable = $definition->getConfigurator()) { return ''; } if (is_array($callable)) { if ($callable[0] instanceof Reference || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) { return sprintf(" %s->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); } $class = $this->dumpValue($callable[0]); // If the class is a string we can optimize call_user_func away if (strpos($class, "'") === 0) { return sprintf(" %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName); } return sprintf(" call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); } return sprintf(" %s(\$%s);\n", $callable, $variableName); } /** * Adds a service. * * @param string $id * @param Definition $definition * * @return string */ private function addService($id, $definition) { $this->definitionVariables = new \SplObjectStorage(); $this->referenceVariables = array(); $this->variableCount = 0; $return = array(); if ($definition->isSynthetic()) { $return[] = '@throws RuntimeException always since this service is expected to be injected dynamically'; } elseif ($class = $definition->getClass()) { $return[] = sprintf('@return %s A %s instance.', 0 === strpos($class, '%') ? 'object' : '\\'.$class, $class); } elseif ($definition->getFactory()) { $factory = $definition->getFactory(); if (is_string($factory)) { $return[] = sprintf('@return object An instance returned by %s().', $factory); } elseif (is_array($factory) && (is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) { if (is_string($factory[0]) || $factory[0] instanceof Reference) { $return[] = sprintf('@return object An instance returned by %s::%s().', (string) $factory[0], $factory[1]); } elseif ($factory[0] instanceof Definition) { $return[] = sprintf('@return object An instance returned by %s::%s().', $factory[0]->getClass(), $factory[1]); } } } elseif ($definition->getFactoryClass()) { $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryClass(), $definition->getFactoryMethod()); } elseif ($definition->getFactoryService()) { $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryService(), $definition->getFactoryMethod()); } $scope = $definition->getScope(); if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) { if ($return && 0 === strpos($return[count($return) - 1], '@return')) { $return[] = ''; } $return[] = sprintf("@throws InactiveScopeException when the '%s' service is requested while the '%s' scope is not active", $id, $scope); } $return = implode("\n * ", $return); $doc = ''; if (ContainerInterface::SCOPE_PROTOTYPE !== $scope) { $doc .= <<isPublic()) { $doc .= <<isLazy()) { $lazyInitialization = '$lazyLoad = true'; $lazyInitializationDoc = "\n * @param bool \$lazyLoad whether to try lazy-loading the service with a proxy\n *"; } else { $lazyInitialization = ''; $lazyInitializationDoc = ''; } // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); $visibility = $isProxyCandidate ? 'public' : 'protected'; $code = <<camelize($id)}Service($lazyInitialization) { EOF; $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id) : ''; if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) { $code .= <<scopedServices['$scope'])) { throw new InactiveScopeException('$id', '$scope'); } EOF; } if ($definition->isSynthetic()) { $code .= sprintf(" throw new RuntimeException('You have requested a synthetic service (\"%s\"). The DIC does not know how to construct this service.');\n }\n", $id); } else { $code .= $this->addServiceInclude($id, $definition). $this->addServiceLocalTempVariables($id, $definition). $this->addServiceInlinedDefinitions($id, $definition). $this->addServiceInstance($id, $definition). $this->addServiceInlinedDefinitionsSetup($id, $definition). $this->addServiceMethodCalls($id, $definition). $this->addServiceProperties($id, $definition). $this->addServiceConfigurator($id, $definition). $this->addServiceReturn($id, $definition) ; } $this->definitionVariables = null; $this->referenceVariables = null; return $code; } /** * Adds multiple services. * * @return string */ private function addServices() { $publicServices = $privateServices = $synchronizers = ''; $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { if ($definition->isPublic()) { $publicServices .= $this->addService($id, $definition); } else { $privateServices .= $this->addService($id, $definition); } $synchronizers .= $this->addServiceSynchronizer($id, $definition); } return $publicServices.$synchronizers.$privateServices; } /** * Adds synchronizer methods. * * @param string $id A service identifier * @param Definition $definition A Definition instance * * @return string|null */ private function addServiceSynchronizer($id, Definition $definition) { if (!$definition->isSynchronized()) { return; } $code = ''; foreach ($this->container->getDefinitions() as $definitionId => $definition) { foreach ($definition->getMethodCalls() as $call) { foreach ($call[1] as $argument) { if ($argument instanceof Reference && $id == (string) $argument) { $arguments = array(); foreach ($call[1] as $value) { $arguments[] = $this->dumpValue($value); } $call = $this->wrapServiceConditionals($call[1], sprintf("\$this->get('%s')->%s(%s);", $definitionId, $call[0], implode(', ', $arguments))); $code .= <<initialized('$definitionId')) { $call } EOF; } } } } if (!$code) { return; } return <<camelize($id)}Service() { $code } EOF; } private function addNewInstance($id, Definition $definition, $return, $instantiation) { $class = $this->dumpValue($definition->getClass()); $arguments = array(); foreach ($definition->getArguments() as $value) { $arguments[] = $this->dumpValue($value); } if (null !== $definition->getFactory()) { $callable = $definition->getFactory(); if (is_array($callable)) { if ($callable[0] instanceof Reference || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) { return sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : ''); } $class = $this->dumpValue($callable[0]); // If the class is a string we can optimize call_user_func away if (strpos($class, "'") === 0) { return sprintf(" $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : ''); } return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', '.implode(', ', $arguments) : ''); } return sprintf(" $return{$instantiation}\\%s(%s);\n", $callable, $arguments ? implode(', ', $arguments) : ''); } elseif (null !== $definition->getFactoryMethod()) { if (null !== $definition->getFactoryClass()) { $class = $this->dumpValue($definition->getFactoryClass()); // If the class is a string we can optimize call_user_func away if (strpos($class, "'") === 0) { return sprintf(" $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $definition->getFactoryMethod(), $arguments ? implode(', ', $arguments) : ''); } return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : ''); } if (null !== $definition->getFactoryService()) { return sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments)); } throw new RuntimeException(sprintf('Factory method requires a factory service or factory class in service definition for %s', $id)); } if (false !== strpos($class, '$')) { return sprintf(" \$class = %s;\n\n $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments)); } return sprintf(" $return{$instantiation}new %s(%s);\n", $this->dumpLiteralClass($class), implode(', ', $arguments)); } /** * Adds the class headers. * * @param string $class Class name * @param string $baseClass The name of the base class * @param string $namespace The class namespace * * @return string */ private function startClass($class, $baseClass, $namespace) { $bagClass = $this->container->isFrozen() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;'; $namespaceLine = $namespace ? "namespace $namespace;\n" : ''; return <<exportTargetDirs(); $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null; $code = <<container->getScopes()) > 0) { $code .= "\n"; $code .= ' $this->scopes = '.$this->dumpValue($scopes).";\n"; $code .= ' $this->scopeChildren = '.$this->dumpValue($this->container->getScopeChildren()).";\n"; } $code .= $this->addMethodMap(); $code .= $this->addAliases(); $code .= <<exportTargetDirs(); $code = <<container->getParameterBag()->all()) { $code .= "\n \$this->parameters = \$this->getDefaultParameters();\n"; } $code .= <<services = \$this->scopedServices = \$this->scopeStacks = array(); EOF; $code .= "\n"; if (count($scopes = $this->container->getScopes()) > 0) { $code .= ' $this->scopes = '.$this->dumpValue($scopes).";\n"; $code .= ' $this->scopeChildren = '.$this->dumpValue($this->container->getScopeChildren()).";\n"; } else { $code .= " \$this->scopes = array();\n"; $code .= " \$this->scopeChildren = array();\n"; } $code .= $this->addMethodMap(); $code .= $this->addAliases(); $code .= <<container->getDefinitions()) { return ''; } $code = " \$this->methodMap = array(\n"; ksort($definitions); foreach ($definitions as $id => $definition) { $code .= ' '.var_export($id, true).' => '.var_export('get'.$this->camelize($id).'Service', true).",\n"; } return $code." );\n"; } /** * Adds the aliases property definition. * * @return string */ private function addAliases() { if (!$aliases = $this->container->getAliases()) { if ($this->container->isFrozen()) { return "\n \$this->aliases = array();\n"; } else { return ''; } } $code = " \$this->aliases = array(\n"; ksort($aliases); foreach ($aliases as $alias => $id) { $id = (string) $id; while (isset($aliases[$id])) { $id = (string) $aliases[$id]; } $code .= ' '.var_export($alias, true).' => '.var_export($id, true).",\n"; } return $code." );\n"; } /** * Adds default parameters method. * * @return string */ private function addDefaultParametersMethod() { if (!$this->container->getParameterBag()->all()) { return ''; } $parameters = $this->exportParameters($this->container->getParameterBag()->all()); $code = ''; if ($this->container->isFrozen()) { $code .= <<parameters[\$name]) || array_key_exists(\$name, \$this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', \$name)); } return \$this->parameters[\$name]; } /** * {@inheritdoc} */ public function hasParameter(\$name) { \$name = strtolower(\$name); return isset(\$this->parameters[\$name]) || array_key_exists(\$name, \$this->parameters); } /** * {@inheritdoc} */ public function setParameter(\$name, \$value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } /** * {@inheritdoc} */ public function getParameterBag() { if (null === \$this->parameterBag) { \$this->parameterBag = new FrozenParameterBag(\$this->parameters); } return \$this->parameterBag; } EOF; } $code .= << $value) { if (is_array($value)) { $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4); } elseif ($value instanceof Variable) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key)); } elseif ($value instanceof Definition) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain service definitions. Definition for "%s" found in "%s".', $value->getClass(), $path.'/'.$key)); } elseif ($value instanceof Reference) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path.'/'.$key)); } elseif ($value instanceof Expression) { throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key)); } else { $value = $this->export($value); } $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), var_export($key, true), $value); } return sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', $indent - 4)); } /** * Ends the class definition. * * @return string */ private function endClass() { return <<has('%s')", $service); } // re-indent the wrapped code $code = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code))); return sprintf(" if (%s) {\n%s }\n", implode(' && ', $conditions), $code); } /** * Builds service calls from arguments. * * @param array $arguments * @param array &$calls By reference * @param array &$behavior By reference */ private function getServiceCallsFromArguments(array $arguments, array &$calls, array &$behavior) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->getServiceCallsFromArguments($argument, $calls, $behavior); } elseif ($argument instanceof Reference) { $id = (string) $argument; if (!isset($calls[$id])) { $calls[$id] = 0; } if (!isset($behavior[$id])) { $behavior[$id] = $argument->getInvalidBehavior(); } elseif (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior[$id]) { $behavior[$id] = $argument->getInvalidBehavior(); } ++$calls[$id]; } } } /** * Returns the inline definition. * * @param Definition $definition * * @return array */ private function getInlinedDefinitions(Definition $definition) { if (false === $this->inlinedDefinitions->contains($definition)) { $definitions = array_merge( $this->getDefinitionsFromArguments($definition->getArguments()), $this->getDefinitionsFromArguments($definition->getMethodCalls()), $this->getDefinitionsFromArguments($definition->getProperties()), $this->getDefinitionsFromArguments(array($definition->getConfigurator())), $this->getDefinitionsFromArguments(array($definition->getFactory())) ); $this->inlinedDefinitions->offsetSet($definition, $definitions); return $definitions; } return $this->inlinedDefinitions->offsetGet($definition); } /** * Gets the definition from arguments. * * @param array $arguments * * @return array */ private function getDefinitionsFromArguments(array $arguments) { $definitions = array(); foreach ($arguments as $argument) { if (is_array($argument)) { $definitions = array_merge($definitions, $this->getDefinitionsFromArguments($argument)); } elseif ($argument instanceof Definition) { $definitions = array_merge( $definitions, $this->getInlinedDefinitions($argument), array($argument) ); } } return $definitions; } /** * Checks if a service id has a reference. * * @param string $id * @param array $arguments * @param bool $deep * @param array $visited * * @return bool */ private function hasReference($id, array $arguments, $deep = false, array &$visited = array()) { foreach ($arguments as $argument) { if (is_array($argument)) { if ($this->hasReference($id, $argument, $deep, $visited)) { return true; } } elseif ($argument instanceof Reference) { $argumentId = (string) $argument; if ($id === $argumentId) { return true; } if ($deep && !isset($visited[$argumentId])) { $visited[$argumentId] = true; $service = $this->container->getDefinition($argumentId); $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties()); if ($this->hasReference($id, $arguments, $deep, $visited)) { return true; } } } } return false; } /** * Dumps values. * * @param mixed $value * @param bool $interpolate * * @return string * * @throws RuntimeException */ private function dumpValue($value, $interpolate = true) { if (is_array($value)) { $code = array(); foreach ($value as $k => $v) { $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)); } return sprintf('array(%s)', implode(', ', $code)); } elseif ($value instanceof Definition) { if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) { return $this->dumpValue($this->definitionVariables->offsetGet($value), $interpolate); } if (count($value->getMethodCalls()) > 0) { throw new RuntimeException('Cannot dump definitions which have method calls.'); } if (null !== $value->getConfigurator()) { throw new RuntimeException('Cannot dump definitions which have a configurator.'); } $arguments = array(); foreach ($value->getArguments() as $argument) { $arguments[] = $this->dumpValue($argument); } if (null !== $value->getFactory()) { $factory = $value->getFactory(); if (is_string($factory)) { return sprintf('\\%s(%s)', $factory, implode(', ', $arguments)); } if (is_array($factory)) { if (is_string($factory[0])) { return sprintf('\\%s::%s(%s)', $factory[0], $factory[1], implode(', ', $arguments)); } if ($factory[0] instanceof Definition) { return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($factory[0]), $factory[1], count($arguments) > 0 ? ', '.implode(', ', $arguments) : ''); } if ($factory[0] instanceof Reference) { return sprintf('%s->%s(%s)', $this->dumpValue($factory[0]), $factory[1], implode(', ', $arguments)); } } throw new RuntimeException('Cannot dump definition because of invalid factory'); } if (null !== $value->getFactoryMethod()) { if (null !== $value->getFactoryClass()) { return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($value->getFactoryClass()), $value->getFactoryMethod(), count($arguments) > 0 ? ', '.implode(', ', $arguments) : ''); } elseif (null !== $value->getFactoryService()) { $service = $this->dumpValue($value->getFactoryService()); return sprintf('%s->%s(%s)', 0 === strpos($service, '$') ? sprintf('$this->get(%s)', $service) : $this->getServiceCall($value->getFactoryService()), $value->getFactoryMethod(), implode(', ', $arguments)); } else { throw new RuntimeException('Cannot dump definitions which have factory method without factory service or factory class.'); } } $class = $value->getClass(); if (null === $class) { throw new RuntimeException('Cannot dump definitions which have no class nor factory.'); } $class = $this->dumpValue($class); if (false !== strpos($class, '$')) { throw new RuntimeException('Cannot dump definitions which have a variable class name.'); } return sprintf('new \\%s(%s)', substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments)); } elseif ($value instanceof Variable) { return '$'.$value; } elseif ($value instanceof Reference) { if (null !== $this->referenceVariables && isset($this->referenceVariables[$id = (string) $value])) { return $this->dumpValue($this->referenceVariables[$id], $interpolate); } return $this->getServiceCall((string) $value, $value); } elseif ($value instanceof Expression) { return $this->getExpressionLanguage()->compile((string) $value, array('this' => 'container')); } elseif ($value instanceof Parameter) { return $this->dumpParameter($value); } elseif (true === $interpolate && is_string($value)) { if (preg_match('/^%([^%]+)%$/', $value, $match)) { // we do this to deal with non string values (Boolean, integer, ...) // the preg_replace_callback converts them to strings return $this->dumpParameter(strtolower($match[1])); } else { $that = $this; $replaceParameters = function ($match) use ($that) { return "'.".$that->dumpParameter(strtolower($match[2])).".'"; }; $code = str_replace('%%', '%', preg_replace_callback('/(?export($value))); return $code; } } elseif (is_object($value) || is_resource($value)) { throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); } else { return $this->export($value); } } /** * Dumps a string to a literal (aka PHP Code) class value. * * @param string $class * * @return string */ private function dumpLiteralClass($class) { return '\\'.substr(str_replace('\\\\', '\\', $class), 1, -1); } /** * Dumps a parameter. * * @param string $name * * @return string */ public function dumpParameter($name) { if ($this->container->isFrozen() && $this->container->hasParameter($name)) { return $this->dumpValue($this->container->getParameter($name), false); } return sprintf("\$this->getParameter('%s')", strtolower($name)); } /** * @deprecated Deprecated since 2.6.2, to be removed in 3.0. Use Symfony\Component\DependencyInjection\ContainerBuilder::addExpressionLanguageProvider instead. * * @param ExpressionFunctionProviderInterface $provider */ public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) { $this->expressionLanguageProviders[] = $provider; } /** * Gets a service call. * * @param string $id * @param Reference $reference * * @return string */ private function getServiceCall($id, Reference $reference = null) { if ('service_container' === $id) { return '$this'; } if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { return sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); } else { if ($this->container->hasAlias($id)) { $id = (string) $this->container->getAlias($id); } return sprintf('$this->get(\'%s\')', $id); } } /** * Convert a service id to a valid PHP method name. * * @param string $id * * @return string * * @throws InvalidArgumentException */ private function camelize($id) { $name = Container::camelize($id); if (!preg_match('/^[a-zA-Z0-9_\x7f-\xff]+$/', $name)) { throw new InvalidArgumentException(sprintf('Service id "%s" cannot be converted to a valid PHP method name.', $id)); } return $name; } /** * Returns the next name to use. * * @return string */ private function getNextVariableName() { $firstChars = self::FIRST_CHARS; $firstCharsLength = strlen($firstChars); $nonFirstChars = self::NON_FIRST_CHARS; $nonFirstCharsLength = strlen($nonFirstChars); while (true) { $name = ''; $i = $this->variableCount; if ('' === $name) { $name .= $firstChars[$i % $firstCharsLength]; $i = (int) ($i / $firstCharsLength); } while ($i > 0) { --$i; $name .= $nonFirstChars[$i % $nonFirstCharsLength]; $i = (int) ($i / $nonFirstCharsLength); } ++$this->variableCount; // check that the name is not reserved if (in_array($name, $this->reservedVariables, true)) { continue; } return $name; } } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $providers = array_merge($this->container->getExpressionLanguageProviders(), $this->expressionLanguageProviders); $this->expressionLanguage = new ExpressionLanguage(null, $providers); if ($this->container->isTrackingResources()) { foreach ($providers as $provider) { $this->container->addObjectResource($provider); } } } return $this->expressionLanguage; } private function exportTargetDirs() { return null === $this->targetDirRegex ? '' : <<targetDirMaxMatches}; ++\$i) { \$this->targetDirs[\$i] = \$dir = dirname(\$dir); } EOF; } private function export($value) { if (null !== $this->targetDirRegex && is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) { $prefix = $matches[0][1] ? var_export(substr($value, 0, $matches[0][1]), true).'.' : ''; $suffix = $matches[0][1] + strlen($matches[0][0]); $suffix = isset($value[$suffix]) ? '.'.var_export(substr($value, $suffix), true) : ''; $dirname = '__DIR__'; if (0 < $offset = 1 + $this->targetDirMaxMatches - count($matches)) { $dirname = sprintf('$this->targetDirs[%d]', $offset); } if ($prefix || $suffix) { return sprintf('(%s%s%s)', $prefix, $dirname, $suffix); } return $dirname; } return var_export($value, true); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\Yaml\Dumper as YmlDumper; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\ExpressionLanguage\Expression; /** * YamlDumper dumps a service container as a YAML string. * * @author Fabien Potencier * * @api */ class YamlDumper extends Dumper { private $dumper; /** * Dumps the service container as an YAML string. * * @param array $options An array of options * * @return string A YAML string representing of the service container * * @api */ public function dump(array $options = array()) { if (!class_exists('Symfony\Component\Yaml\Dumper')) { throw new RuntimeException('Unable to dump the container as the Symfony Yaml Component is not installed.'); } if (null === $this->dumper) { $this->dumper = new YmlDumper(); } return $this->addParameters()."\n".$this->addServices(); } /** * Adds a service. * * @param string $id * @param Definition $definition * * @return string */ private function addService($id, $definition) { $code = " $id:\n"; if ($definition->getClass()) { $code .= sprintf(" class: %s\n", $definition->getClass()); } if (!$definition->isPublic()) { $code .= " public: false\n"; } $tagsCode = ''; foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $att = array(); foreach ($attributes as $key => $value) { $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value)); } $att = $att ? ', '.implode(', ', $att) : ''; $tagsCode .= sprintf(" - { name: %s%s }\n", $this->dumper->dump($name), $att); } } if ($tagsCode) { $code .= " tags:\n".$tagsCode; } if ($definition->getFile()) { $code .= sprintf(" file: %s\n", $definition->getFile()); } if ($definition->isSynthetic()) { $code .= sprintf(" synthetic: true\n"); } if ($definition->isSynchronized()) { $code .= sprintf(" synchronized: true\n"); } if ($definition->getFactoryClass()) { $code .= sprintf(" factory_class: %s\n", $definition->getFactoryClass()); } if ($definition->isLazy()) { $code .= sprintf(" lazy: true\n"); } if ($definition->getFactoryMethod()) { $code .= sprintf(" factory_method: %s\n", $definition->getFactoryMethod()); } if ($definition->getFactoryService()) { $code .= sprintf(" factory_service: %s\n", $definition->getFactoryService()); } if ($definition->getArguments()) { $code .= sprintf(" arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0)); } if ($definition->getProperties()) { $code .= sprintf(" properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0)); } if ($definition->getMethodCalls()) { $code .= sprintf(" calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12)); } if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope()) { $code .= sprintf(" scope: %s\n", $scope); } if (null !== $decorated = $definition->getDecoratedService()) { list($decorated, $renamedId) = $decorated; $code .= sprintf(" decorates: %s\n", $decorated); if (null !== $renamedId) { $code .= sprintf(" decoration_inner_name: %s\n", $renamedId); } } if ($callable = $definition->getFactory()) { $code .= sprintf(" factory: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0)); } if ($callable = $definition->getConfigurator()) { $code .= sprintf(" configurator: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0)); } return $code; } /** * Adds a service alias. * * @param string $alias * @param Alias $id * * @return string */ private function addServiceAlias($alias, $id) { if ($id->isPublic()) { return sprintf(" %s: @%s\n", $alias, $id); } else { return sprintf(" %s:\n alias: %s\n public: false", $alias, $id); } } /** * Adds services. * * @return string */ private function addServices() { if (!$this->container->getDefinitions()) { return ''; } $code = "services:\n"; foreach ($this->container->getDefinitions() as $id => $definition) { $code .= $this->addService($id, $definition); } $aliases = $this->container->getAliases(); foreach ($aliases as $alias => $id) { while (isset($aliases[(string) $id])) { $id = $aliases[(string) $id]; } $code .= $this->addServiceAlias($alias, $id); } return $code; } /** * Adds parameters. * * @return string */ private function addParameters() { if (!$this->container->getParameterBag()->all()) { return ''; } $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isFrozen()); return $this->dumper->dump(array('parameters' => $parameters), 2); } /** * Dumps callable to YAML format * * @param callable $callable * * @return callable */ private function dumpCallable($callable) { if (is_array($callable)) { if ($callable[0] instanceof Reference) { $callable = array($this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]); } else { $callable = array($callable[0], $callable[1]); } } return $callable; } /** * Dumps the value to YAML format. * * @param mixed $value * * @return mixed * * @throws RuntimeException When trying to dump object or resource */ private function dumpValue($value) { if (is_array($value)) { $code = array(); foreach ($value as $k => $v) { $code[$k] = $this->dumpValue($v); } return $code; } elseif ($value instanceof Reference) { return $this->getServiceCall((string) $value, $value); } elseif ($value instanceof Parameter) { return $this->getParameterCall((string) $value); } elseif ($value instanceof Expression) { return $this->getExpressionCall((string) $value); } elseif (is_object($value) || is_resource($value)) { throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); } return $value; } /** * Gets the service call. * * @param string $id * @param Reference $reference * * @return string */ private function getServiceCall($id, Reference $reference = null) { if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { return sprintf('@?%s', $id); } return sprintf('@%s', $id); } /** * Gets parameter call. * * @param string $id * * @return string */ private function getParameterCall($id) { return sprintf('%%%s%%', $id); } private function getExpressionCall($expression) { return sprintf('@=%s', $expression); } /** * Prepares parameters. * * @param array $parameters * @param bool $escape * * @return array */ private function prepareParameters($parameters, $escape = true) { $filtered = array(); foreach ($parameters as $key => $value) { if (is_array($value)) { $value = $this->prepareParameters($value, $escape); } elseif ($value instanceof Reference || is_string($value) && 0 === strpos($value, '@')) { $value = '@'.$value; } $filtered[$key] = $value; } return $escape ? $this->escape($filtered) : $filtered; } /** * Escapes arguments. * * @param array $arguments * * @return array */ private function escape($arguments) { $args = array(); foreach ($arguments as $k => $v) { if (is_array($v)) { $args[$k] = $this->escape($v); } elseif (is_string($v)) { $args[$k] = str_replace('%', '%%', $v); } else { $args[$k] = $v; } } return $args; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Dumper is the abstract class for all built-in dumpers. * * @author Fabien Potencier * * @api */ abstract class Dumper implements DumperInterface { protected $container; /** * Constructor. * * @param ContainerBuilder $container The service container to dump * * @api */ public function __construct(ContainerBuilder $container) { $this->container = $container; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Scope; /** * GraphvizDumper dumps a service container as a graphviz file. * * You can convert the generated dot file with the dot utility (http://www.graphviz.org/): * * dot -Tpng container.dot > foo.png * * @author Fabien Potencier */ class GraphvizDumper extends Dumper { private $nodes; private $edges; private $options = array( 'graph' => array('ratio' => 'compress'), 'node' => array('fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'), 'edge' => array('fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5), 'node.instance' => array('fillcolor' => '#9999ff', 'style' => 'filled'), 'node.definition' => array('fillcolor' => '#eeeeee'), 'node.missing' => array('fillcolor' => '#ff9999', 'style' => 'filled'), ); /** * Dumps the service container as a graphviz graph. * * Available options: * * * graph: The default options for the whole graph * * node: The default options for nodes * * edge: The default options for edges * * node.instance: The default options for services that are defined directly by object instances * * node.definition: The default options for services that are defined via service definition instances * * node.missing: The default options for missing services * * @param array $options An array of options * * @return string The dot representation of the service container */ public function dump(array $options = array()) { foreach (array('graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing') as $key) { if (isset($options[$key])) { $this->options[$key] = array_merge($this->options[$key], $options[$key]); } } $this->nodes = $this->findNodes(); $this->edges = array(); foreach ($this->container->getDefinitions() as $id => $definition) { $this->edges[$id] = array_merge( $this->findEdges($id, $definition->getArguments(), true, ''), $this->findEdges($id, $definition->getProperties(), false, '') ); foreach ($definition->getMethodCalls() as $call) { $this->edges[$id] = array_merge( $this->edges[$id], $this->findEdges($id, $call[1], false, $call[0].'()') ); } } return $this->startDot().$this->addNodes().$this->addEdges().$this->endDot(); } /** * Returns all nodes. * * @return string A string representation of all nodes */ private function addNodes() { $code = ''; foreach ($this->nodes as $id => $node) { $aliases = $this->getAliases($id); $code .= sprintf(" node_%s [label=\"%s\\n%s\\n\", shape=%s%s];\n", $this->dotize($id), $id.($aliases ? ' ('.implode(', ', $aliases).')' : ''), $node['class'], $this->options['node']['shape'], $this->addAttributes($node['attributes'])); } return $code; } /** * Returns all edges. * * @return string A string representation of all edges */ private function addEdges() { $code = ''; foreach ($this->edges as $id => $edges) { foreach ($edges as $edge) { $code .= sprintf(" node_%s -> node_%s [label=\"%s\" style=\"%s\"];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed'); } } return $code; } /** * Finds all edges belonging to a specific service id. * * @param string $id The service id used to find edges * @param array $arguments An array of arguments * @param bool $required * @param string $name * * @return array An array of edges */ private function findEdges($id, $arguments, $required, $name) { $edges = array(); foreach ($arguments as $argument) { if ($argument instanceof Parameter) { $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null; } elseif (is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) { $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null; } if ($argument instanceof Reference) { if (!$this->container->has((string) $argument)) { $this->nodes[(string) $argument] = array('name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']); } $edges[] = array('name' => $name, 'required' => $required, 'to' => $argument); } elseif (is_array($argument)) { $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name)); } } return $edges; } /** * Finds all nodes. * * @return array An array of all nodes */ private function findNodes() { $nodes = array(); $container = $this->cloneContainer(); foreach ($container->getDefinitions() as $id => $definition) { $className = $definition->getClass(); try { $className = $this->container->getParameterBag()->resolveValue($className); } catch (ParameterNotFoundException $e) { } $nodes[$id] = array('class' => str_replace('\\', '\\\\', $className), 'attributes' => array_merge($this->options['node.definition'], array('style' => ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope() ? 'filled' : 'dotted'))); $container->setDefinition($id, new Definition('stdClass')); } foreach ($container->getServiceIds() as $id) { $service = $container->get($id); if (array_key_exists($id, $container->getAliases())) { continue; } if (!$container->hasDefinition($id)) { $class = ('service_container' === $id) ? get_class($this->container) : get_class($service); $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => $this->options['node.instance']); } } return $nodes; } private function cloneContainer() { $parameterBag = new ParameterBag($this->container->getParameterBag()->all()); $container = new ContainerBuilder($parameterBag); $container->setDefinitions($this->container->getDefinitions()); $container->setAliases($this->container->getAliases()); $container->setResources($this->container->getResources()); foreach ($this->container->getScopes() as $scope => $parentScope) { $container->addScope(new Scope($scope, $parentScope)); } foreach ($this->container->getExtensions() as $extension) { $container->registerExtension($extension); } return $container; } /** * Returns the start dot. * * @return string The string representation of a start dot */ private function startDot() { return sprintf("digraph sc {\n %s\n node [%s];\n edge [%s];\n\n", $this->addOptions($this->options['graph']), $this->addOptions($this->options['node']), $this->addOptions($this->options['edge']) ); } /** * Returns the end dot. * * @return string */ private function endDot() { return "}\n"; } /** * Adds attributes. * * @param array $attributes An array of attributes * * @return string A comma separated list of attributes */ private function addAttributes($attributes) { $code = array(); foreach ($attributes as $k => $v) { $code[] = sprintf('%s="%s"', $k, $v); } return $code ? ', '.implode(', ', $code) : ''; } /** * Adds options. * * @param array $options An array of options * * @return string A space separated list of options */ private function addOptions($options) { $code = array(); foreach ($options as $k => $v) { $code[] = sprintf('%s="%s"', $k, $v); } return implode(' ', $code); } /** * Dotizes an identifier. * * @param string $id The identifier to dotize * * @return string A dotized string */ private function dotize($id) { return strtolower(preg_replace('/\W/i', '_', $id)); } /** * Compiles an array of aliases for a specified service id. * * @param string $id A service id * * @return array An array of aliases */ private function getAliases($id) { $aliases = array(); foreach ($this->container->getAliases() as $alias => $origin) { if ($id == $origin) { $aliases[] = $alias; } } return $aliases; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\ExpressionLanguage\Expression; /** * XmlDumper dumps a service container as an XML string. * * @author Fabien Potencier * @author Martin Hasoň * * @api */ class XmlDumper extends Dumper { /** * @var \DOMDocument */ private $document; /** * Dumps the service container as an XML string. * * @param array $options An array of options * * @return string An xml string representing of the service container * * @api */ public function dump(array $options = array()) { $this->document = new \DOMDocument('1.0', 'utf-8'); $this->document->formatOutput = true; $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container'); $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd'); $this->addParameters($container); $this->addServices($container); $this->document->appendChild($container); $xml = $this->document->saveXML(); $this->document = null; return $xml; } /** * Adds parameters. * * @param \DOMElement $parent */ private function addParameters(\DOMElement $parent) { $data = $this->container->getParameterBag()->all(); if (!$data) { return; } if ($this->container->isFrozen()) { $data = $this->escape($data); } $parameters = $this->document->createElement('parameters'); $parent->appendChild($parameters); $this->convertParameters($data, 'parameter', $parameters); } /** * Adds method calls. * * @param array $methodcalls * @param \DOMElement $parent */ private function addMethodCalls(array $methodcalls, \DOMElement $parent) { foreach ($methodcalls as $methodcall) { $call = $this->document->createElement('call'); $call->setAttribute('method', $methodcall[0]); if (count($methodcall[1])) { $this->convertParameters($methodcall[1], 'argument', $call); } $parent->appendChild($call); } } /** * Adds a service. * * @param Definition $definition * @param string $id * @param \DOMElement $parent */ private function addService($definition, $id, \DOMElement $parent) { $service = $this->document->createElement('service'); if (null !== $id) { $service->setAttribute('id', $id); } if ($definition->getClass()) { $service->setAttribute('class', $definition->getClass()); } if ($definition->getFactoryMethod()) { $service->setAttribute('factory-method', $definition->getFactoryMethod()); } if ($definition->getFactoryClass()) { $service->setAttribute('factory-class', $definition->getFactoryClass()); } if ($definition->getFactoryService()) { $service->setAttribute('factory-service', $definition->getFactoryService()); } if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope()) { $service->setAttribute('scope', $scope); } if (!$definition->isPublic()) { $service->setAttribute('public', 'false'); } if ($definition->isSynthetic()) { $service->setAttribute('synthetic', 'true'); } if ($definition->isSynchronized()) { $service->setAttribute('synchronized', 'true'); } if ($definition->isLazy()) { $service->setAttribute('lazy', 'true'); } if (null !== $decorated = $definition->getDecoratedService()) { list($decorated, $renamedId) = $decorated; $service->setAttribute('decorates', $decorated); if (null !== $renamedId) { $service->setAttribute('decoration-inner-name', $renamedId); } } foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $tag = $this->document->createElement('tag'); $tag->setAttribute('name', $name); foreach ($attributes as $key => $value) { $tag->setAttribute($key, $value); } $service->appendChild($tag); } } if ($definition->getFile()) { $file = $this->document->createElement('file'); $file->appendChild($this->document->createTextNode($definition->getFile())); $service->appendChild($file); } if ($parameters = $definition->getArguments()) { $this->convertParameters($parameters, 'argument', $service); } if ($parameters = $definition->getProperties()) { $this->convertParameters($parameters, 'property', $service, 'name'); } $this->addMethodCalls($definition->getMethodCalls(), $service); if ($callable = $definition->getFactory()) { $factory = $this->document->createElement('factory'); if (is_array($callable)) { $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $factory->setAttribute('method', $callable[1]); } else { $factory->setAttribute('function', $callable); } $service->appendChild($factory); } if ($callable = $definition->getConfigurator()) { $configurator = $this->document->createElement('configurator'); if (is_array($callable)) { $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $configurator->setAttribute('method', $callable[1]); } else { $configurator->setAttribute('function', $callable); } $service->appendChild($configurator); } $parent->appendChild($service); } /** * Adds a service alias. * * @param string $alias * @param Alias $id * @param \DOMElement $parent */ private function addServiceAlias($alias, Alias $id, \DOMElement $parent) { $service = $this->document->createElement('service'); $service->setAttribute('id', $alias); $service->setAttribute('alias', $id); if (!$id->isPublic()) { $service->setAttribute('public', 'false'); } $parent->appendChild($service); } /** * Adds services. * * @param \DOMElement $parent */ private function addServices(\DOMElement $parent) { $definitions = $this->container->getDefinitions(); if (!$definitions) { return; } $services = $this->document->createElement('services'); foreach ($definitions as $id => $definition) { $this->addService($definition, $id, $services); } $aliases = $this->container->getAliases(); foreach ($aliases as $alias => $id) { while (isset($aliases[(string) $id])) { $id = $aliases[(string) $id]; } $this->addServiceAlias($alias, $id, $services); } $parent->appendChild($services); } /** * Converts parameters. * * @param array $parameters * @param string $type * @param \DOMElement $parent * @param string $keyAttribute */ private function convertParameters($parameters, $type, \DOMElement $parent, $keyAttribute = 'key') { $withKeys = array_keys($parameters) !== range(0, count($parameters) - 1); foreach ($parameters as $key => $value) { $element = $this->document->createElement($type); if ($withKeys) { $element->setAttribute($keyAttribute, $key); } if (is_array($value)) { $element->setAttribute('type', 'collection'); $this->convertParameters($value, $type, $element, 'key'); } elseif ($value instanceof Reference) { $element->setAttribute('type', 'service'); $element->setAttribute('id', (string) $value); $behaviour = $value->getInvalidBehavior(); if ($behaviour == ContainerInterface::NULL_ON_INVALID_REFERENCE) { $element->setAttribute('on-invalid', 'null'); } elseif ($behaviour == ContainerInterface::IGNORE_ON_INVALID_REFERENCE) { $element->setAttribute('on-invalid', 'ignore'); } if (!$value->isStrict()) { $element->setAttribute('strict', 'false'); } } elseif ($value instanceof Definition) { $element->setAttribute('type', 'service'); $this->addService($value, null, $element); } elseif ($value instanceof Expression) { $element->setAttribute('type', 'expression'); $text = $this->document->createTextNode(self::phpToXml((string) $value)); $element->appendChild($text); } else { if (in_array($value, array('null', 'true', 'false'), true)) { $element->setAttribute('type', 'string'); } $text = $this->document->createTextNode(self::phpToXml($value)); $element->appendChild($text); } $parent->appendChild($element); } } /** * Escapes arguments. * * @param array $arguments * * @return array */ private function escape($arguments) { $args = array(); foreach ($arguments as $k => $v) { if (is_array($v)) { $args[$k] = $this->escape($v); } elseif (is_string($v)) { $args[$k] = str_replace('%', '%%', $v); } else { $args[$k] = $v; } } return $args; } /** * Converts php types to xml types. * * @param mixed $value Value to convert * * @return string * * @throws RuntimeException When trying to dump object or resource */ public static function phpToXml($value) { switch (true) { case null === $value: return 'null'; case true === $value: return 'true'; case false === $value: return 'false'; case $value instanceof Parameter: return '%'.$value.'%'; case is_object($value) || is_resource($value): throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); default: return (string) $value; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; /** * Container is a dependency injection container. * * It gives access to object instances (services). * * Services and parameters are simple key/pair stores. * * Parameter and service keys are case insensitive. * * A service id can contain lowercased letters, digits, underscores, and dots. * Underscores are used to separate words, and dots to group services * under namespaces: * *
    *
  • request
  • *
  • mysql_session_storage
  • *
  • symfony.mysql_session_storage
  • *
* * A service can also be defined by creating a method named * getXXXService(), where XXX is the camelized version of the id: * *
    *
  • request -> getRequestService()
  • *
  • mysql_session_storage -> getMysqlSessionStorageService()
  • *
  • symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()
  • *
* * The container can have three possible behaviors when a service does not exist: * * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) * * NULL_ON_INVALID_REFERENCE: Returns null * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference * (for instance, ignore a setter if the service does not exist) * * @author Fabien Potencier * @author Johannes M. Schmitt * * @api */ class Container implements IntrospectableContainerInterface { /** * @var ParameterBagInterface */ protected $parameterBag; protected $services = array(); protected $methodMap = array(); protected $aliases = array(); protected $scopes = array(); protected $scopeChildren = array(); protected $scopedServices = array(); protected $scopeStacks = array(); protected $loading = array(); private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_'); /** * Constructor. * * @param ParameterBagInterface $parameterBag A ParameterBagInterface instance * * @api */ public function __construct(ParameterBagInterface $parameterBag = null) { $this->parameterBag = $parameterBag ?: new ParameterBag(); } /** * Compiles the container. * * This method does two things: * * * Parameter values are resolved; * * The parameter bag is frozen. * * @api */ public function compile() { $this->parameterBag->resolve(); $this->parameterBag = new FrozenParameterBag($this->parameterBag->all()); } /** * Returns true if the container parameter bag are frozen. * * @return bool true if the container parameter bag are frozen, false otherwise * * @api */ public function isFrozen() { return $this->parameterBag instanceof FrozenParameterBag; } /** * Gets the service container parameter bag. * * @return ParameterBagInterface A ParameterBagInterface instance * * @api */ public function getParameterBag() { return $this->parameterBag; } /** * Gets a parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws InvalidArgumentException if the parameter is not defined * * @api */ public function getParameter($name) { return $this->parameterBag->get($name); } /** * Checks if a parameter exists. * * @param string $name The parameter name * * @return bool The presence of parameter in container * * @api */ public function hasParameter($name) { return $this->parameterBag->has($name); } /** * Sets a parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function setParameter($name, $value) { $this->parameterBag->set($name, $value); } /** * Sets a service. * * Setting a service to null resets the service: has() returns false and get() * behaves in the same way as if the service was never created. * * @param string $id The service identifier * @param object $service The service instance * @param string $scope The scope of the service * * @throws RuntimeException When trying to set a service in an inactive scope * @throws InvalidArgumentException When trying to set a service in the prototype scope * * @api */ public function set($id, $service, $scope = self::SCOPE_CONTAINER) { if (self::SCOPE_PROTOTYPE === $scope) { throw new InvalidArgumentException(sprintf('You cannot set service "%s" of scope "prototype".', $id)); } $id = strtolower($id); if ('service_container' === $id) { // BC: 'service_container' is no longer a self-reference but always // $this, so ignore this call. // @todo Throw InvalidArgumentException in next major release. return; } if (self::SCOPE_CONTAINER !== $scope) { if (!isset($this->scopedServices[$scope])) { throw new RuntimeException(sprintf('You cannot set service "%s" of inactive scope.', $id)); } $this->scopedServices[$scope][$id] = $service; } $this->services[$id] = $service; if (method_exists($this, $method = 'synchronize'.strtr($id, $this->underscoreMap).'Service')) { $this->$method(); } if (null === $service) { if (self::SCOPE_CONTAINER !== $scope) { unset($this->scopedServices[$scope][$id]); } unset($this->services[$id]); } } /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return bool true if the service is defined, false otherwise * * @api */ public function has($id) { for ($i = 2;;) { if ('service_container' === $id || isset($this->aliases[$id]) || isset($this->services[$id]) || array_key_exists($id, $this->services) ) { return true; } if (--$i && $id !== $lcId = strtolower($id)) { $id = $lcId; } else { return method_exists($this, 'get'.strtr($id, $this->underscoreMap).'Service'); } } } /** * Gets a service. * * If a service is defined both through a set() method and * with a get{$id}Service() method, the former has always precedence. * * @param string $id The service identifier * @param int $invalidBehavior The behavior when the service does not exist * * @return object The associated service * * @throws ServiceCircularReferenceException When a circular reference is detected * @throws ServiceNotFoundException When the service is not defined * @throws \Exception if an exception has been thrown when the service has been resolved * * @see Reference * * @api */ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE) { // Attempt to retrieve the service by checking first aliases then // available services. Service IDs are case insensitive, however since // this method can be called thousands of times during a request, avoid // calling strtolower() unless necessary. for ($i = 2;;) { if ('service_container' === $id) { return $this; } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } // Re-use shared service instance if it exists. if (isset($this->services[$id]) || array_key_exists($id, $this->services)) { return $this->services[$id]; } if (isset($this->loading[$id])) { throw new ServiceCircularReferenceException($id, array_keys($this->loading)); } if (isset($this->methodMap[$id])) { $method = $this->methodMap[$id]; } elseif (--$i && $id !== $lcId = strtolower($id)) { $id = $lcId; continue; } elseif (method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) { // $method is set to the right value, proceed } else { if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { if (!$id) { throw new ServiceNotFoundException($id); } $alternatives = array(); foreach ($this->services as $key => $associatedService) { $lev = levenshtein($id, $key); if ($lev <= strlen($id) / 3 || false !== strpos($key, $id)) { $alternatives[] = $key; } } throw new ServiceNotFoundException($id, null, null, $alternatives); } return; } $this->loading[$id] = true; try { $service = $this->$method(); } catch (\Exception $e) { unset($this->loading[$id]); if (array_key_exists($id, $this->services)) { unset($this->services[$id]); } if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { return; } throw $e; } unset($this->loading[$id]); return $service; } } /** * Returns true if the given service has actually been initialized. * * @param string $id The service identifier * * @return bool true if service has already been initialized, false otherwise */ public function initialized($id) { $id = strtolower($id); if ('service_container' === $id) { // BC: 'service_container' was a synthetic service previously. // @todo Change to false in next major release. return true; } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } return isset($this->services[$id]) || array_key_exists($id, $this->services); } /** * Gets all service ids. * * @return array An array of all defined service ids */ public function getServiceIds() { $ids = array(); $r = new \ReflectionClass($this); foreach ($r->getMethods() as $method) { if (preg_match('/^get(.+)Service$/', $method->name, $match)) { $ids[] = self::underscore($match[1]); } } $ids[] = 'service_container'; return array_unique(array_merge($ids, array_keys($this->services))); } /** * This is called when you enter a scope. * * @param string $name * * @throws RuntimeException When the parent scope is inactive * @throws InvalidArgumentException When the scope does not exist * * @api */ public function enterScope($name) { if (!isset($this->scopes[$name])) { throw new InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name)); } if (self::SCOPE_CONTAINER !== $this->scopes[$name] && !isset($this->scopedServices[$this->scopes[$name]])) { throw new RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name])); } // check if a scope of this name is already active, if so we need to // remove all services of this scope, and those of any of its child // scopes from the global services map if (isset($this->scopedServices[$name])) { $services = array($this->services, $name => $this->scopedServices[$name]); unset($this->scopedServices[$name]); foreach ($this->scopeChildren[$name] as $child) { if (isset($this->scopedServices[$child])) { $services[$child] = $this->scopedServices[$child]; unset($this->scopedServices[$child]); } } // update global map $this->services = call_user_func_array('array_diff_key', $services); array_shift($services); // add stack entry for this scope so we can restore the removed services later if (!isset($this->scopeStacks[$name])) { $this->scopeStacks[$name] = new \SplStack(); } $this->scopeStacks[$name]->push($services); } $this->scopedServices[$name] = array(); } /** * This is called to leave the current scope, and move back to the parent * scope. * * @param string $name The name of the scope to leave * * @throws InvalidArgumentException if the scope is not active * * @api */ public function leaveScope($name) { if (!isset($this->scopedServices[$name])) { throw new InvalidArgumentException(sprintf('The scope "%s" is not active.', $name)); } // remove all services of this scope, or any of its child scopes from // the global service map $services = array($this->services, $this->scopedServices[$name]); unset($this->scopedServices[$name]); foreach ($this->scopeChildren[$name] as $child) { if (isset($this->scopedServices[$child])) { $services[] = $this->scopedServices[$child]; unset($this->scopedServices[$child]); } } // update global map $this->services = call_user_func_array('array_diff_key', $services); // check if we need to restore services of a previous scope of this type if (isset($this->scopeStacks[$name]) && count($this->scopeStacks[$name]) > 0) { $services = $this->scopeStacks[$name]->pop(); $this->scopedServices += $services; if ($this->scopeStacks[$name]->isEmpty()) { unset($this->scopeStacks[$name]); } foreach ($services as $array) { foreach ($array as $id => $service) { $this->set($id, $service, $name); } } } } /** * Adds a scope to the container. * * @param ScopeInterface $scope * * @throws InvalidArgumentException * * @api */ public function addScope(ScopeInterface $scope) { $name = $scope->getName(); $parentScope = $scope->getParentName(); if (self::SCOPE_CONTAINER === $name || self::SCOPE_PROTOTYPE === $name) { throw new InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name)); } if (isset($this->scopes[$name])) { throw new InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name)); } if (self::SCOPE_CONTAINER !== $parentScope && !isset($this->scopes[$parentScope])) { throw new InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope)); } $this->scopes[$name] = $parentScope; $this->scopeChildren[$name] = array(); // normalize the child relations while ($parentScope !== self::SCOPE_CONTAINER) { $this->scopeChildren[$parentScope][] = $name; $parentScope = $this->scopes[$parentScope]; } } /** * Returns whether this container has a certain scope. * * @param string $name The name of the scope * * @return bool * * @api */ public function hasScope($name) { return isset($this->scopes[$name]); } /** * Returns whether this scope is currently active. * * This does not actually check if the passed scope actually exists. * * @param string $name * * @return bool * * @api */ public function isScopeActive($name) { return isset($this->scopedServices[$name]); } /** * Camelizes a string. * * @param string $id A string to camelize * * @return string The camelized string */ public static function camelize($id) { return strtr(ucwords(strtr($id, array('_' => ' ', '.' => '_ ', '\\' => '_ '))), array(' ' => '')); } /** * A string to underscore. * * @param string $id The string to underscore * * @return string The underscored string */ public static function underscore($id) { return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($id, '_', '.'))); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\ExpressionLanguage\ExpressionFunction; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; /** * Define some ExpressionLanguage functions. * * To get a service, use service('request'). * To get a parameter, use parameter('kernel.debug'). * * @author Fabien Potencier */ class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface { public function getFunctions() { return array( new ExpressionFunction('service', function ($arg) { return sprintf('$this->get(%s)', $arg); }, function (array $variables, $value) { return $variables['container']->get($value); }), new ExpressionFunction('parameter', function ($arg) { return sprintf('$this->getParameter(%s)', $arg); }, function (array $variables, $value) { return $variables['container']->getParameter($value); }), ); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; /** * This definition decorates another definition. * * @author Johannes M. Schmitt * * @api */ class DefinitionDecorator extends Definition { private $parent; private $changes = array(); /** * Constructor. * * @param string $parent The id of Definition instance to decorate. * * @api */ public function __construct($parent) { parent::__construct(); $this->parent = $parent; } /** * Returns the Definition being decorated. * * @return string * * @api */ public function getParent() { return $this->parent; } /** * Returns all changes tracked for the Definition object. * * @return array An array of changes for this Definition * * @api */ public function getChanges() { return $this->changes; } /** * {@inheritdoc} * * @api */ public function setClass($class) { $this->changes['class'] = true; return parent::setClass($class); } /** * {@inheritdoc} */ public function setFactory($callable) { $this->changes['factory'] = true; return parent::setFactory($callable); } /** * {@inheritdoc} * * @api */ public function setFactoryClass($class) { $this->changes['factory_class'] = true; return parent::setFactoryClass($class); } /** * {@inheritdoc} * * @api */ public function setFactoryMethod($method) { $this->changes['factory_method'] = true; return parent::setFactoryMethod($method); } /** * {@inheritdoc} * * @api */ public function setFactoryService($service) { $this->changes['factory_service'] = true; return parent::setFactoryService($service); } /** * {@inheritdoc} * * @api */ public function setConfigurator($callable) { $this->changes['configurator'] = true; return parent::setConfigurator($callable); } /** * {@inheritdoc} * * @api */ public function setFile($file) { $this->changes['file'] = true; return parent::setFile($file); } /** * {@inheritdoc} * * @api */ public function setPublic($boolean) { $this->changes['public'] = true; return parent::setPublic($boolean); } /** * {@inheritdoc} * * @api */ public function setLazy($boolean) { $this->changes['lazy'] = true; return parent::setLazy($boolean); } /** * {@inheritdoc} */ public function setDecoratedService($id, $renamedId = null) { $this->changes['decorated_service'] = true; return parent::setDecoratedService($id, $renamedId); } /** * Gets an argument to pass to the service constructor/factory method. * * If replaceArgument() has been used to replace an argument, this method * will return the replacement value. * * @param int $index * * @return mixed The argument value * * @throws OutOfBoundsException When the argument does not exist * * @api */ public function getArgument($index) { if (array_key_exists('index_'.$index, $this->arguments)) { return $this->arguments['index_'.$index]; } $lastIndex = count(array_filter(array_keys($this->arguments), 'is_int')) - 1; if ($index < 0 || $index > $lastIndex) { throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, $lastIndex)); } return $this->arguments[$index]; } /** * You should always use this method when overwriting existing arguments * of the parent definition. * * If you directly call setArguments() keep in mind that you must follow * certain conventions when you want to overwrite the arguments of the * parent definition, otherwise your arguments will only be appended. * * @param int $index * @param mixed $value * * @return DefinitionDecorator the current instance * * @throws InvalidArgumentException when $index isn't an integer * * @api */ public function replaceArgument($index, $value) { if (!is_int($index)) { throw new InvalidArgumentException('$index must be an integer.'); } $this->arguments['index_'.$index] = $value; return $this; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\ParameterBag; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; /** * ParameterBagInterface. * * @author Fabien Potencier * * @api */ interface ParameterBagInterface { /** * Clears all parameters. * * @api */ public function clear(); /** * Adds parameters to the service container parameters. * * @param array $parameters An array of parameters * * @api */ public function add(array $parameters); /** * Gets the service container parameters. * * @return array An array of parameters * * @api */ public function all(); /** * Gets a service container parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws ParameterNotFoundException if the parameter is not defined * * @api */ public function get($name); /** * Sets a service container parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function set($name, $value); /** * Returns true if a parameter name is defined. * * @param string $name The parameter name * * @return bool true if the parameter name is defined, false otherwise * * @api */ public function has($name); /** * Replaces parameter placeholders (%name%) by their values for all parameters. */ public function resolve(); /** * Replaces parameter placeholders (%name%) by their values. * * @param mixed $value A value * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist */ public function resolveValue($value); /** * Escape parameter placeholders %. * * @param mixed $value * * @return mixed */ public function escapeValue($value); /** * Unescape parameter placeholders %. * * @param mixed $value * * @return mixed */ public function unescapeValue($value); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\ParameterBag; use Symfony\Component\DependencyInjection\Exception\LogicException; /** * Holds read-only parameters. * * @author Fabien Potencier * * @api */ class FrozenParameterBag extends ParameterBag { /** * Constructor. * * For performance reasons, the constructor assumes that * all keys are already lowercased. * * This is always the case when used internally. * * @param array $parameters An array of parameters * * @api */ public function __construct(array $parameters = array()) { $this->parameters = $parameters; $this->resolved = true; } /** * {@inheritdoc} * * @api */ public function clear() { throw new LogicException('Impossible to call clear() on a frozen ParameterBag.'); } /** * {@inheritdoc} * * @api */ public function add(array $parameters) { throw new LogicException('Impossible to call add() on a frozen ParameterBag.'); } /** * {@inheritdoc} * * @api */ public function set($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } /** * {@inheritdoc} * * @api */ public function remove($name) { throw new LogicException('Impossible to call remove() on a frozen ParameterBag.'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\ParameterBag; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * Holds parameters. * * @author Fabien Potencier * * @api */ class ParameterBag implements ParameterBagInterface { protected $parameters = array(); protected $resolved = false; /** * Constructor. * * @param array $parameters An array of parameters * * @api */ public function __construct(array $parameters = array()) { $this->add($parameters); } /** * Clears all parameters. * * @api */ public function clear() { $this->parameters = array(); } /** * Adds parameters to the service container parameters. * * @param array $parameters An array of parameters * * @api */ public function add(array $parameters) { foreach ($parameters as $key => $value) { $this->parameters[strtolower($key)] = $value; } } /** * Gets the service container parameters. * * @return array An array of parameters * * @api */ public function all() { return $this->parameters; } /** * Gets a service container parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws ParameterNotFoundException if the parameter is not defined * * @api */ public function get($name) { $name = strtolower($name); if (!array_key_exists($name, $this->parameters)) { if (!$name) { throw new ParameterNotFoundException($name); } $alternatives = array(); foreach ($this->parameters as $key => $parameterValue) { $lev = levenshtein($name, $key); if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) { $alternatives[] = $key; } } throw new ParameterNotFoundException($name, null, null, null, $alternatives); } return $this->parameters[$name]; } /** * Sets a service container parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function set($name, $value) { $this->parameters[strtolower($name)] = $value; } /** * Returns true if a parameter name is defined. * * @param string $name The parameter name * * @return bool true if the parameter name is defined, false otherwise * * @api */ public function has($name) { return array_key_exists(strtolower($name), $this->parameters); } /** * Removes a parameter. * * @param string $name The parameter name * * @api */ public function remove($name) { unset($this->parameters[strtolower($name)]); } /** * Replaces parameter placeholders (%name%) by their values for all parameters. */ public function resolve() { if ($this->resolved) { return; } $parameters = array(); foreach ($this->parameters as $key => $value) { try { $value = $this->resolveValue($value); $parameters[$key] = $this->unescapeValue($value); } catch (ParameterNotFoundException $e) { $e->setSourceKey($key); throw $e; } } $this->parameters = $parameters; $this->resolved = true; } /** * Replaces parameter placeholders (%name%) by their values. * * @param mixed $value A value * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) * * @return mixed The resolved value * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist * @throws ParameterCircularReferenceException if a circular reference if detected * @throws RuntimeException when a given parameter has a type problem. */ public function resolveValue($value, array $resolving = array()) { if (is_array($value)) { $args = array(); foreach ($value as $k => $v) { $args[$this->resolveValue($k, $resolving)] = $this->resolveValue($v, $resolving); } return $args; } if (!is_string($value)) { return $value; } return $this->resolveString($value, $resolving); } /** * Resolves parameters inside a string. * * @param string $value The string to resolve * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) * * @return string The resolved string * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist * @throws ParameterCircularReferenceException if a circular reference if detected * @throws RuntimeException when a given parameter has a type problem. */ public function resolveString($value, array $resolving = array()) { // we do this to deal with non string values (Boolean, integer, ...) // as the preg_replace_callback throw an exception when trying // a non-string in a parameter value if (preg_match('/^%([^%\s]+)%$/', $value, $match)) { $key = strtolower($match[1]); if (isset($resolving[$key])) { throw new ParameterCircularReferenceException(array_keys($resolving)); } $resolving[$key] = true; return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving); } $self = $this; return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($self, $resolving, $value) { // skip %% if (!isset($match[1])) { return '%%'; } $key = strtolower($match[1]); if (isset($resolving[$key])) { throw new ParameterCircularReferenceException(array_keys($resolving)); } $resolved = $self->get($key); if (!is_string($resolved) && !is_numeric($resolved)) { throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".', $key, gettype($resolved), $value)); } $resolved = (string) $resolved; $resolving[$key] = true; return $self->isResolved() ? $resolved : $self->resolveString($resolved, $resolving); }, $value); } public function isResolved() { return $this->resolved; } /** * {@inheritdoc} */ public function escapeValue($value) { if (is_string($value)) { return str_replace('%', '%%', $value); } if (is_array($value)) { $result = array(); foreach ($value as $k => $v) { $result[$k] = $this->escapeValue($v); } return $result; } return $value; } public function unescapeValue($value) { if (is_string($value)) { return str_replace('%%', '%', $value); } if (is_array($value)) { $result = array(); foreach ($value as $k => $v) { $result[$k] = $this->unescapeValue($v); } return $result; } return $value; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * TaggedContainerInterface is the interface implemented when a container knows how to deals with tags. * * @author Fabien Potencier * * @api */ interface TaggedContainerInterface extends ContainerInterface { /** * Returns service ids for a given tag. * * @param string $name The tag name * * @return array An array of tags * * @api */ public function findTaggedServiceIds($name); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * IntrospectableContainerInterface defines additional introspection functionality * for containers, allowing logic to be implemented based on a Container's state. * * @author Evan Villemez */ interface IntrospectableContainerInterface extends ContainerInterface { /** * Check for whether or not a service has been initialized. * * @param string $id * * @return bool true if the service has been initialized, false otherwise */ public function initialized($id); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; /** * {@inheritdoc} * * Noop proxy instantiator - simply produces the real service instead of a proxy instance. * * @author Marco Pivetta */ class RealServiceInstantiator implements InstantiatorInterface { /** * {@inheritdoc} */ public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator) { return call_user_func($realInstantiator); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; /** * Lazy proxy instantiator, capable of instantiating a proxy given a container, the * service definitions and a callback that produces the real service instance. * * @author Marco Pivetta */ interface InstantiatorInterface { /** * Instantiates a proxy object. * * @param ContainerInterface $container the container from which the service is being requested * @param Definition $definition the definition of the requested service * @param string $id identifier of the requested service * @param callable $realInstantiator zero-argument callback that is capable of producing the real * service instance * * @return object */ public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; use Symfony\Component\DependencyInjection\Definition; /** * Lazy proxy dumper capable of generating the instantiation logic PHP code for proxied services. * * @author Marco Pivetta */ interface DumperInterface { /** * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container. * * @param Definition $definition * * @return bool */ public function isProxyCandidate(Definition $definition); /** * Generates the code to be used to instantiate a proxy in the dumped factory code. * * @param Definition $definition * @param string $id service identifier * * @return string */ public function getProxyFactoryCode(Definition $definition, $id); /** * Generates the code for the lazy proxy. * * @param Definition $definition * * @return string */ public function getProxyCode(Definition $definition); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; use Symfony\Component\DependencyInjection\Definition; /** * Null dumper, negates any proxy code generation for any given service definition. * * @author Marco Pivetta */ class NullDumper implements DumperInterface { /** * {@inheritdoc} */ public function isProxyCandidate(Definition $definition) { return false; } /** * {@inheritdoc} */ public function getProxyFactoryCode(Definition $definition, $id) { return ''; } /** * {@inheritdoc} */ public function getProxyCode(Definition $definition) { return ''; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; /** * ContainerAwareInterface should be implemented by classes that depends on a Container. * * @author Fabien Potencier * * @api */ interface ContainerAwareInterface { /** * Sets the Container. * * @param ContainerInterface|null $container A ContainerInterface instance or null * * @api */ public function setContainer(ContainerInterface $container = null); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a non-existent parameter is used. * * @author Fabien Potencier */ class ParameterNotFoundException extends InvalidArgumentException { private $key; private $sourceId; private $sourceKey; private $alternatives; /** * Constructor. * * @param string $key The requested parameter key * @param string $sourceId The service id that references the non-existent parameter * @param string $sourceKey The parameter key that references the non-existent parameter * @param \Exception $previous The previous exception * @param string[] $alternatives Some parameter name alternatives */ public function __construct($key, $sourceId = null, $sourceKey = null, \Exception $previous = null, array $alternatives = array()) { $this->key = $key; $this->sourceId = $sourceId; $this->sourceKey = $sourceKey; $this->alternatives = $alternatives; parent::__construct('', 0, $previous); $this->updateRepr(); } public function updateRepr() { if (null !== $this->sourceId) { $this->message = sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key); } elseif (null !== $this->sourceKey) { $this->message = sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key); } else { $this->message = sprintf('You have requested a non-existent parameter "%s".', $this->key); } if ($this->alternatives) { if (1 == count($this->alternatives)) { $this->message .= ' Did you mean this: "'; } else { $this->message .= ' Did you mean one of these: "'; } $this->message .= implode('", "', $this->alternatives).'"?'; } } public function getKey() { return $this->key; } public function getSourceId() { return $this->sourceId; } public function getSourceKey() { return $this->sourceKey; } public function setSourceId($sourceId) { $this->sourceId = $sourceId; $this->updateRepr(); } public function setSourceKey($sourceKey) { $this->sourceKey = $sourceKey; $this->updateRepr(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base ExceptionInterface for Dependency Injection component. * * @author Fabien Potencier * @author Bulat Shakirzyanov */ interface ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a circular reference is detected. * * @author Johannes M. Schmitt */ class ServiceCircularReferenceException extends RuntimeException { private $serviceId; private $path; public function __construct($serviceId, array $path, \Exception $previous = null) { parent::__construct(sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)), 0, $previous); $this->serviceId = $serviceId; $this->path = $path; } public function getServiceId() { return $this->serviceId; } public function getPath() { return $this->path; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Thrown when a scope widening injection is detected. * * @author Johannes M. Schmitt */ class ScopeWideningInjectionException extends RuntimeException { private $sourceServiceId; private $sourceScope; private $destServiceId; private $destScope; public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null) { parent::__construct(sprintf( 'Scope Widening Injection detected: The definition "%s" references the service "%s" which belongs to a narrower scope. ' .'Generally, it is safer to either move "%s" to scope "%s" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "%s" each time it is needed. ' .'In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.', $sourceServiceId, $destServiceId, $sourceServiceId, $destScope, $destServiceId ), 0, $previous); $this->sourceServiceId = $sourceServiceId; $this->sourceScope = $sourceScope; $this->destServiceId = $destServiceId; $this->destScope = $destScope; } public function getSourceServiceId() { return $this->sourceServiceId; } public function getSourceScope() { return $this->sourceScope; } public function getDestServiceId() { return $this->destServiceId; } public function getDestScope() { return $this->destScope; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base InvalidArgumentException for Dependency Injection component. * * @author Bulat Shakirzyanov */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base LogicException for Dependency Injection component. */ class LogicException extends \LogicException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a non-existent service is requested. * * @author Johannes M. Schmitt */ class ServiceNotFoundException extends InvalidArgumentException { private $id; private $sourceId; public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = array()) { if (null === $sourceId) { $msg = sprintf('You have requested a non-existent service "%s".', $id); } else { $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id); } if ($alternatives) { if (1 == count($alternatives)) { $msg .= ' Did you mean this: "'; } else { $msg .= ' Did you mean one of these: "'; } $msg .= implode('", "', $alternatives).'"?'; } parent::__construct($msg, 0, $previous); $this->id = $id; $this->sourceId = $sourceId; } public function getId() { return $this->id; } public function getSourceId() { return $this->sourceId; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when you try to create a service of an inactive scope. * * @author Johannes M. Schmitt */ class InactiveScopeException extends RuntimeException { private $serviceId; private $scope; public function __construct($serviceId, $scope, \Exception $previous = null) { parent::__construct(sprintf('You cannot create a service ("%s") of an inactive scope ("%s").', $serviceId, $scope), 0, $previous); $this->serviceId = $serviceId; $this->scope = $scope; } public function getServiceId() { return $this->serviceId; } public function getScope() { return $this->scope; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base RuntimeException for Dependency Injection component. * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a circular reference in a parameter is detected. * * @author Fabien Potencier */ class ParameterCircularReferenceException extends RuntimeException { private $parameters; public function __construct($parameters, \Exception $previous = null) { parent::__construct(sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], implode('" > "', $parameters), $parameters[0]), 0, $previous); $this->parameters = $parameters; } public function getParameters() { return $this->parameters; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when the a scope crossing injection is detected. * * @author Johannes M. Schmitt */ class ScopeCrossingInjectionException extends RuntimeException { private $sourceServiceId; private $sourceScope; private $destServiceId; private $destScope; public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null) { parent::__construct(sprintf( 'Scope Crossing Injection detected: The definition "%s" references the service "%s" which belongs to another scope hierarchy. ' .'This service might not be available consistently. Generally, it is safer to either move the definition "%s" to scope "%s", or ' .'declare "%s" as a child scope of "%s". If you can be sure that the other scope is always active, you can set the reference to strict=false to get rid of this error.', $sourceServiceId, $destServiceId, $sourceServiceId, $destScope, $sourceScope, $destScope ), 0, $previous); $this->sourceServiceId = $sourceServiceId; $this->sourceScope = $sourceScope; $this->destServiceId = $destServiceId; $this->destScope = $destScope; } public function getSourceServiceId() { return $this->sourceServiceId; } public function getSourceScope() { return $this->sourceScope; } public function getDestServiceId() { return $this->destServiceId; } public function getDestScope() { return $this->destScope; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base BadMethodCallException for Dependency Injection component. */ class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Exception; /** * Base OutOfBoundsException for Dependency Injection component. */ class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Alias; /** * Represents a node in your service graph. * * Value is typically a definition, or an alias. * * @author Johannes M. Schmitt */ class ServiceReferenceGraphNode { private $id; private $inEdges = array(); private $outEdges = array(); private $value; /** * Constructor. * * @param string $id The node identifier * @param mixed $value The node value */ public function __construct($id, $value) { $this->id = $id; $this->value = $value; } /** * Adds an in edge to this node. * * @param ServiceReferenceGraphEdge $edge */ public function addInEdge(ServiceReferenceGraphEdge $edge) { $this->inEdges[] = $edge; } /** * Adds an out edge to this node. * * @param ServiceReferenceGraphEdge $edge */ public function addOutEdge(ServiceReferenceGraphEdge $edge) { $this->outEdges[] = $edge; } /** * Checks if the value of this node is an Alias. * * @return bool True if the value is an Alias instance */ public function isAlias() { return $this->value instanceof Alias; } /** * Checks if the value of this node is a Definition. * * @return bool True if the value is a Definition instance */ public function isDefinition() { return $this->value instanceof Definition; } /** * Returns the identifier. * * @return string */ public function getId() { return $this->id; } /** * Returns the in edges. * * @return array The in ServiceReferenceGraphEdge array */ public function getInEdges() { return $this->inEdges; } /** * Returns the out edges. * * @return array The out ServiceReferenceGraphEdge array */ public function getOutEdges() { return $this->outEdges; } /** * Returns the value of this Node. * * @return mixed The value */ public function getValue() { return $this->value; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * This class is used to remove circular dependencies between individual passes. * * @author Johannes M. Schmitt * * @api */ class Compiler { private $passConfig; private $log = array(); private $loggingFormatter; private $serviceReferenceGraph; /** * Constructor. */ public function __construct() { $this->passConfig = new PassConfig(); $this->serviceReferenceGraph = new ServiceReferenceGraph(); $this->loggingFormatter = new LoggingFormatter(); } /** * Returns the PassConfig. * * @return PassConfig The PassConfig instance * * @api */ public function getPassConfig() { return $this->passConfig; } /** * Returns the ServiceReferenceGraph. * * @return ServiceReferenceGraph The ServiceReferenceGraph instance * * @api */ public function getServiceReferenceGraph() { return $this->serviceReferenceGraph; } /** * Returns the logging formatter which can be used by compilation passes. * * @return LoggingFormatter */ public function getLoggingFormatter() { return $this->loggingFormatter; } /** * Adds a pass to the PassConfig. * * @param CompilerPassInterface $pass A compiler pass * @param string $type The type of the pass * * @api */ public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) { $this->passConfig->addPass($pass, $type); } /** * Adds a log message. * * @param string $string The log message */ public function addLogMessage($string) { $this->log[] = $string; } /** * Returns the log. * * @return array Log array */ public function getLog() { return $this->log; } /** * Run the Compiler and process all Passes. * * @param ContainerBuilder $container * * @api */ public function compile(ContainerBuilder $container) { foreach ($this->passConfig->getPasses() as $pass) { $pass->process($container); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Checks that all references are pointing to a valid service. * * @author Johannes M. Schmitt */ class CheckExceptionOnInvalidReferenceBehaviorPass implements CompilerPassInterface { private $container; private $sourceId; public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $id => $definition) { $this->sourceId = $id; $this->processDefinition($definition); } } private function processDefinition(Definition $definition) { $this->processReferences($definition->getArguments()); $this->processReferences($definition->getMethodCalls()); $this->processReferences($definition->getProperties()); } private function processReferences(array $arguments) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->processReferences($argument); } elseif ($argument instanceof Definition) { $this->processDefinition($argument); } elseif ($argument instanceof Reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $argument->getInvalidBehavior()) { $destId = (string) $argument; if (!$this->container->has($destId)) { throw new ServiceNotFoundException($destId, $this->sourceId); } } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; /** * Interface that must be implemented by passes that are run as part of an * RepeatedPass. * * @author Johannes M. Schmitt */ interface RepeatablePassInterface extends CompilerPassInterface { /** * Sets the RepeatedPass interface. * * @param RepeatedPass $repeatedPass */ public function setRepeatedPass(RepeatedPass $repeatedPass); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Remove private aliases from the container. They were only used to establish * dependencies between services, and these dependencies have been resolved in * one of the previous passes. * * @author Johannes M. Schmitt */ class RemovePrivateAliasesPass implements CompilerPassInterface { /** * Removes private aliases from the ContainerBuilder. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $compiler = $container->getCompiler(); $formatter = $compiler->getLoggingFormatter(); foreach ($container->getAliases() as $id => $alias) { if ($alias->isPublic()) { continue; } $container->removeAlias($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'private alias')); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Removes abstract Definitions. */ class RemoveAbstractDefinitionsPass implements CompilerPassInterface { /** * Removes abstract definitions from the ContainerBuilder. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $compiler = $container->getCompiler(); $formatter = $compiler->getLoggingFormatter(); foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isAbstract()) { $container->removeDefinition($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'abstract')); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * This is a directed graph of your services. * * This information can be used by your compiler passes instead of collecting * it themselves which improves performance quite a lot. * * @author Johannes M. Schmitt */ class ServiceReferenceGraph { /** * @var ServiceReferenceGraphNode[] */ private $nodes = array(); /** * Checks if the graph has a specific node. * * @param string $id Id to check * * @return bool */ public function hasNode($id) { return isset($this->nodes[$id]); } /** * Gets a node by identifier. * * @param string $id The id to retrieve * * @return ServiceReferenceGraphNode The node matching the supplied identifier * * @throws InvalidArgumentException if no node matches the supplied identifier */ public function getNode($id) { if (!isset($this->nodes[$id])) { throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id)); } return $this->nodes[$id]; } /** * Returns all nodes. * * @return ServiceReferenceGraphNode[] An array of all ServiceReferenceGraphNode objects */ public function getNodes() { return $this->nodes; } /** * Clears all nodes. */ public function clear() { $this->nodes = array(); } /** * Connects 2 nodes together in the Graph. * * @param string $sourceId * @param string $sourceValue * @param string $destId * @param string $destValue * @param string $reference */ public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null) { $sourceNode = $this->createNode($sourceId, $sourceValue); $destNode = $this->createNode($destId, $destValue); $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference); $sourceNode->addOutEdge($edge); $destNode->addInEdge($edge); } /** * Creates a graph node. * * @param string $id * @param string $value * * @return ServiceReferenceGraphNode */ private function createNode($id, $value) { if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) { return $this->nodes[$id]; } return $this->nodes[$id] = new ServiceReferenceGraphNode($id, $value); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * This replaces all DefinitionDecorator instances with their equivalent fully * merged Definition instance. * * @author Johannes M. Schmitt */ class ResolveDefinitionTemplatesPass implements CompilerPassInterface { private $container; private $compiler; private $formatter; /** * Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; $this->compiler = $container->getCompiler(); $this->formatter = $this->compiler->getLoggingFormatter(); foreach ($container->getDefinitions() as $id => $definition) { // yes, we are specifically fetching the definition from the // container to ensure we are not operating on stale data $definition = $container->getDefinition($id); if (!$definition instanceof DefinitionDecorator || $definition->isAbstract()) { continue; } $this->resolveDefinition($id, $definition); } } /** * Resolves the definition. * * @param string $id The definition identifier * @param DefinitionDecorator $definition * * @return Definition * * @throws \RuntimeException When the definition is invalid */ private function resolveDefinition($id, DefinitionDecorator $definition) { if (!$this->container->hasDefinition($parent = $definition->getParent())) { throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $id)); } $parentDef = $this->container->getDefinition($parent); if ($parentDef instanceof DefinitionDecorator) { $parentDef = $this->resolveDefinition($parent, $parentDef); } $this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $id, $parent)); $def = new Definition(); // merge in parent definition // purposely ignored attributes: scope, abstract, tags $def->setClass($parentDef->getClass()); $def->setArguments($parentDef->getArguments()); $def->setMethodCalls($parentDef->getMethodCalls()); $def->setProperties($parentDef->getProperties()); $def->setFactoryClass($parentDef->getFactoryClass()); $def->setFactoryMethod($parentDef->getFactoryMethod()); $def->setFactoryService($parentDef->getFactoryService()); $def->setFactory($parentDef->getFactory()); $def->setConfigurator($parentDef->getConfigurator()); $def->setFile($parentDef->getFile()); $def->setPublic($parentDef->isPublic()); $def->setLazy($parentDef->isLazy()); // overwrite with values specified in the decorator $changes = $definition->getChanges(); if (isset($changes['class'])) { $def->setClass($definition->getClass()); } if (isset($changes['factory_class'])) { $def->setFactoryClass($definition->getFactoryClass()); } if (isset($changes['factory_method'])) { $def->setFactoryMethod($definition->getFactoryMethod()); } if (isset($changes['factory_service'])) { $def->setFactoryService($definition->getFactoryService()); } if (isset($changes['factory'])) { $def->setFactory($definition->getFactory()); } if (isset($changes['configurator'])) { $def->setConfigurator($definition->getConfigurator()); } if (isset($changes['file'])) { $def->setFile($definition->getFile()); } if (isset($changes['public'])) { $def->setPublic($definition->isPublic()); } if (isset($changes['lazy'])) { $def->setLazy($definition->isLazy()); } if (isset($changes['decorated_service'])) { $decoratedService = $definition->getDecoratedService(); if (null === $decoratedService) { $def->setDecoratedService($decoratedService); } else { $def->setDecoratedService($decoratedService[0], $decoratedService[1]); } } // merge arguments foreach ($definition->getArguments() as $k => $v) { if (is_numeric($k)) { $def->addArgument($v); continue; } if (0 !== strpos($k, 'index_')) { throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k)); } $index = (int) substr($k, strlen('index_')); $def->replaceArgument($index, $v); } // merge properties foreach ($definition->getProperties() as $k => $v) { $def->setProperty($k, $v); } // append method calls if (count($calls = $definition->getMethodCalls()) > 0) { $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); } // these attributes are always taken from the child $def->setAbstract($definition->isAbstract()); $def->setScope($definition->getScope()); $def->setTags($definition->getTags()); // set new definition on container $this->container->setDefinition($id, $def); return $def; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Replaces all references to aliases with references to the actual service. * * @author Johannes M. Schmitt */ class ResolveReferencesToAliasesPass implements CompilerPassInterface { private $container; /** * Processes the ContainerBuilder to replace references to aliases with actual service references. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $definition->setArguments($this->processArguments($definition->getArguments())); $definition->setMethodCalls($this->processArguments($definition->getMethodCalls())); $definition->setProperties($this->processArguments($definition->getProperties())); } foreach ($container->getAliases() as $id => $alias) { $aliasId = (string) $alias; if ($aliasId !== $defId = $this->getDefinitionId($aliasId)) { $container->setAlias($id, new Alias($defId, $alias->isPublic())); } } } /** * Processes the arguments to replace aliases. * * @param array $arguments An array of References * * @return array An array of References */ private function processArguments(array $arguments) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->processArguments($argument); } elseif ($argument instanceof Reference) { $defId = $this->getDefinitionId($id = (string) $argument); if ($defId !== $id) { $arguments[$k] = new Reference($defId, $argument->getInvalidBehavior(), $argument->isStrict()); } } } return $arguments; } /** * Resolves an alias into a definition id. * * @param string $id The definition or alias id to resolve * * @return string The definition id with aliases resolved */ private function getDefinitionId($id) { $seen = array(); while ($this->container->hasAlias($id)) { if (isset($seen[$id])) { throw new ServiceCircularReferenceException($id, array_keys($seen)); } $seen[$id] = true; $id = (string) $this->container->getAlias($id); } return $id; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * A pass that might be run repeatedly. * * @author Johannes M. Schmitt */ class RepeatedPass implements CompilerPassInterface { /** * @var bool */ private $repeat = false; /** * @var RepeatablePassInterface[] */ private $passes; /** * Constructor. * * @param RepeatablePassInterface[] $passes An array of RepeatablePassInterface objects * * @throws InvalidArgumentException when the passes don't implement RepeatablePassInterface */ public function __construct(array $passes) { foreach ($passes as $pass) { if (!$pass instanceof RepeatablePassInterface) { throw new InvalidArgumentException('$passes must be an array of RepeatablePassInterface.'); } $pass->setRepeatedPass($this); } $this->passes = $passes; } /** * Process the repeatable passes that run more than once. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->repeat = false; foreach ($this->passes as $pass) { $pass->process($container); } if ($this->repeat) { $this->process($container); } } /** * Sets if the pass should repeat. */ public function setRepeat() { $this->repeat = true; } /** * Returns the passes. * * @return RepeatablePassInterface[] An array of RepeatablePassInterface objects */ public function getPasses() { return $this->passes; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; /** * Resolves all parameter placeholders "%somevalue%" to their real values. * * @author Johannes M. Schmitt */ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface { /** * Processes the ContainerBuilder to resolve parameter placeholders. * * @param ContainerBuilder $container * * @throws ParameterNotFoundException */ public function process(ContainerBuilder $container) { $parameterBag = $container->getParameterBag(); foreach ($container->getDefinitions() as $id => $definition) { try { $definition->setClass($parameterBag->resolveValue($definition->getClass())); $definition->setFile($parameterBag->resolveValue($definition->getFile())); $definition->setArguments($parameterBag->resolveValue($definition->getArguments())); $definition->setFactoryClass($parameterBag->resolveValue($definition->getFactoryClass())); $factory = $definition->getFactory(); if (is_array($factory) && isset($factory[0])) { $factory[0] = $parameterBag->resolveValue($factory[0]); $definition->setFactory($factory); } $calls = array(); foreach ($definition->getMethodCalls() as $name => $arguments) { $calls[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($arguments); } $definition->setMethodCalls($calls); $definition->setProperties($parameterBag->resolveValue($definition->getProperties())); } catch (ParameterNotFoundException $e) { $e->setSourceId($id); throw $e; } } $aliases = array(); foreach ($container->getAliases() as $name => $target) { $aliases[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($target); } $container->setAliases($aliases); $parameterBag->resolve(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException; use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException; /** * Checks the validity of references. * * The following checks are performed by this pass: * - target definitions are not abstract * - target definitions are of equal or wider scope * - target definitions are in the same scope hierarchy * * @author Johannes M. Schmitt */ class CheckReferenceValidityPass implements CompilerPassInterface { private $container; private $currentId; private $currentScope; private $currentScopeAncestors; private $currentScopeChildren; /** * Processes the ContainerBuilder to validate References. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; $children = $this->container->getScopeChildren(); $ancestors = array(); $scopes = $this->container->getScopes(); foreach ($scopes as $name => $parent) { $ancestors[$name] = array($parent); while (isset($scopes[$parent])) { $ancestors[$name][] = $parent = $scopes[$parent]; } } foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $this->currentId = $id; $this->currentDefinition = $definition; $this->currentScope = $scope = $definition->getScope(); if (ContainerInterface::SCOPE_CONTAINER === $scope) { $this->currentScopeChildren = array_keys($scopes); $this->currentScopeAncestors = array(); } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope) { $this->currentScopeChildren = isset($children[$scope]) ? $children[$scope] : array(); $this->currentScopeAncestors = isset($ancestors[$scope]) ? $ancestors[$scope] : array(); } $this->validateReferences($definition->getArguments()); $this->validateReferences($definition->getMethodCalls()); $this->validateReferences($definition->getProperties()); } } /** * Validates an array of References. * * @param array $arguments An array of Reference objects * * @throws RuntimeException when there is a reference to an abstract definition. */ private function validateReferences(array $arguments) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->validateReferences($argument); } elseif ($argument instanceof Reference) { $targetDefinition = $this->getDefinition((string) $argument); if (null !== $targetDefinition && $targetDefinition->isAbstract()) { throw new RuntimeException(sprintf( 'The definition "%s" has a reference to an abstract definition "%s". ' .'Abstract definitions cannot be the target of references.', $this->currentId, $argument )); } $this->validateScope($argument, $targetDefinition); } } } /** * Validates the scope of a single Reference. * * @param Reference $reference * @param Definition $definition * * @throws ScopeWideningInjectionException when the definition references a service of a narrower scope * @throws ScopeCrossingInjectionException when the definition references a service of another scope hierarchy */ private function validateScope(Reference $reference, Definition $definition = null) { if (ContainerInterface::SCOPE_PROTOTYPE === $this->currentScope) { return; } if (!$reference->isStrict()) { return; } if (null === $definition) { return; } if ($this->currentScope === $scope = $definition->getScope()) { return; } $id = (string) $reference; if (in_array($scope, $this->currentScopeChildren, true)) { throw new ScopeWideningInjectionException($this->currentId, $this->currentScope, $id, $scope); } if (!in_array($scope, $this->currentScopeAncestors, true)) { throw new ScopeCrossingInjectionException($this->currentId, $this->currentScope, $id, $scope); } } /** * Returns the Definition given an id. * * @param string $id Definition identifier * * @return Definition */ private function getDefinition($id) { if (!$this->container->hasDefinition($id)) { return; } return $this->container->getDefinition($id); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Alias; /** * Overwrites a service but keeps the overridden one. * * @author Christophe Coevoet * @author Fabien Potencier */ class DecoratorServicePass implements CompilerPassInterface { public function process(ContainerBuilder $container) { foreach ($container->getDefinitions() as $id => $definition) { if (!$decorated = $definition->getDecoratedService()) { continue; } $definition->setDecoratedService(null); list($inner, $renamedId) = $decorated; if (!$renamedId) { $renamedId = $id.'.inner'; } // we create a new alias/service for the service we are replacing // to be able to reference it in the new one if ($container->hasAlias($inner)) { $alias = $container->getAlias($inner); $public = $alias->isPublic(); $container->setAlias($renamedId, new Alias((string) $alias, false)); } else { $definition = $container->getDefinition($inner); $public = $definition->isPublic(); $definition->setPublic(false); $container->setDefinition($renamedId, $definition); } $container->setAlias($inner, new Alias($id, $public)); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; /** * Used to format logging messages during the compilation. * * @author Johannes M. Schmitt */ class LoggingFormatter { public function formatRemoveService(CompilerPassInterface $pass, $id, $reason) { return $this->format($pass, sprintf('Removed service "%s"; reason: %s', $id, $reason)); } public function formatInlineService(CompilerPassInterface $pass, $id, $target) { return $this->format($pass, sprintf('Inlined service "%s" to "%s".', $id, $target)); } public function formatUpdateReference(CompilerPassInterface $pass, $serviceId, $oldDestId, $newDestId) { return $this->format($pass, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $serviceId, $oldDestId, $newDestId)); } public function formatResolveInheritance(CompilerPassInterface $pass, $childId, $parentId) { return $this->format($pass, sprintf('Resolving inheritance for "%s" (parent: %s).', $childId, $parentId)); } public function format(CompilerPassInterface $pass, $message) { return sprintf('%s: %s', get_class($pass), $message); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * Compiler Pass Configuration. * * This class has a default configuration embedded. * * @author Johannes M. Schmitt * * @api */ class PassConfig { const TYPE_AFTER_REMOVING = 'afterRemoving'; const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization'; const TYPE_BEFORE_REMOVING = 'beforeRemoving'; const TYPE_OPTIMIZE = 'optimization'; const TYPE_REMOVE = 'removing'; private $mergePass; private $afterRemovingPasses = array(); private $beforeOptimizationPasses = array(); private $beforeRemovingPasses = array(); private $optimizationPasses; private $removingPasses; /** * Constructor. */ public function __construct() { $this->mergePass = new MergeExtensionConfigurationPass(); $this->optimizationPasses = array( new ResolveDefinitionTemplatesPass(), new DecoratorServicePass(), new ResolveParameterPlaceHoldersPass(), new CheckDefinitionValidityPass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), new AnalyzeServiceReferencesPass(true), new CheckCircularReferencesPass(), new CheckReferenceValidityPass(), ); $this->removingPasses = array( new RemovePrivateAliasesPass(), new RemoveAbstractDefinitionsPass(), new ReplaceAliasByActualDefinitionPass(), new RepeatedPass(array( new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass(), new AnalyzeServiceReferencesPass(), new RemoveUnusedDefinitionsPass(), )), new CheckExceptionOnInvalidReferenceBehaviorPass(), ); } /** * Returns all passes in order to be processed. * * @return array An array of all passes to process * * @api */ public function getPasses() { return array_merge( array($this->mergePass), $this->beforeOptimizationPasses, $this->optimizationPasses, $this->beforeRemovingPasses, $this->removingPasses, $this->afterRemovingPasses ); } /** * Adds a pass. * * @param CompilerPassInterface $pass A Compiler pass * @param string $type The pass type * * @throws InvalidArgumentException when a pass type doesn't exist * * @api */ public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION) { $property = $type.'Passes'; if (!isset($this->$property)) { throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type)); } $passes = &$this->$property; $passes[] = $pass; } /** * Gets all passes for the AfterRemoving pass. * * @return array An array of passes * * @api */ public function getAfterRemovingPasses() { return $this->afterRemovingPasses; } /** * Gets all passes for the BeforeOptimization pass. * * @return array An array of passes * * @api */ public function getBeforeOptimizationPasses() { return $this->beforeOptimizationPasses; } /** * Gets all passes for the BeforeRemoving pass. * * @return array An array of passes * * @api */ public function getBeforeRemovingPasses() { return $this->beforeRemovingPasses; } /** * Gets all passes for the Optimization pass. * * @return array An array of passes * * @api */ public function getOptimizationPasses() { return $this->optimizationPasses; } /** * Gets all passes for the Removing pass. * * @return array An array of passes * * @api */ public function getRemovingPasses() { return $this->removingPasses; } /** * Gets all passes for the Merge pass. * * @return array An array of passes * * @api */ public function getMergePass() { return $this->mergePass; } /** * Sets the Merge Pass. * * @param CompilerPassInterface $pass The merge pass * * @api */ public function setMergePass(CompilerPassInterface $pass) { $this->mergePass = $pass; } /** * Sets the AfterRemoving passes. * * @param array $passes An array of passes * * @api */ public function setAfterRemovingPasses(array $passes) { $this->afterRemovingPasses = $passes; } /** * Sets the BeforeOptimization passes. * * @param array $passes An array of passes * * @api */ public function setBeforeOptimizationPasses(array $passes) { $this->beforeOptimizationPasses = $passes; } /** * Sets the BeforeRemoving passes. * * @param array $passes An array of passes * * @api */ public function setBeforeRemovingPasses(array $passes) { $this->beforeRemovingPasses = $passes; } /** * Sets the Optimization passes. * * @param array $passes An array of passes * * @api */ public function setOptimizationPasses(array $passes) { $this->optimizationPasses = $passes; } /** * Sets the Removing passes. * * @param array $passes An array of passes * * @api */ public function setRemovingPasses(array $passes) { $this->removingPasses = $passes; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * Emulates the invalid behavior if the reference is not found within the * container. * * @author Johannes M. Schmitt */ class ResolveInvalidReferencesPass implements CompilerPassInterface { private $container; /** * Process the ContainerBuilder to resolve invalid references. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; foreach ($container->getDefinitions() as $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $definition->setArguments( $this->processArguments($definition->getArguments()) ); $calls = array(); foreach ($definition->getMethodCalls() as $call) { try { $calls[] = array($call[0], $this->processArguments($call[1], true)); } catch (RuntimeException $e) { // this call is simply removed } } $definition->setMethodCalls($calls); $properties = array(); foreach ($definition->getProperties() as $name => $value) { try { $value = $this->processArguments(array($value), true); $properties[$name] = reset($value); } catch (RuntimeException $e) { // ignore property } } $definition->setProperties($properties); } } /** * Processes arguments to determine invalid references. * * @param array $arguments An array of Reference objects * @param bool $inMethodCall * * @return array * * @throws RuntimeException When the config is invalid */ private function processArguments(array $arguments, $inMethodCall = false) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->processArguments($argument, $inMethodCall); } elseif ($argument instanceof Reference) { $id = (string) $argument; $invalidBehavior = $argument->getInvalidBehavior(); $exists = $this->container->has($id); // resolve invalid behavior if (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { $arguments[$k] = null; } elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) { if ($inMethodCall) { throw new RuntimeException('Method shouldn\'t be called.'); } $arguments[$k] = null; } } } return $arguments; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Removes unused service definitions from the container. * * @author Johannes M. Schmitt */ class RemoveUnusedDefinitionsPass implements RepeatablePassInterface { private $repeatedPass; /** * {@inheritdoc} */ public function setRepeatedPass(RepeatedPass $repeatedPass) { $this->repeatedPass = $repeatedPass; } /** * Processes the ContainerBuilder to remove unused definitions. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $compiler = $container->getCompiler(); $formatter = $compiler->getLoggingFormatter(); $graph = $compiler->getServiceReferenceGraph(); $hasChanged = false; foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isPublic()) { continue; } if ($graph->hasNode($id)) { $edges = $graph->getNode($id)->getInEdges(); $referencingAliases = array(); $sourceIds = array(); foreach ($edges as $edge) { $node = $edge->getSourceNode(); $sourceIds[] = $node->getId(); if ($node->isAlias()) { $referencingAliases[] = $node->getValue(); } } $isReferenced = (count(array_unique($sourceIds)) - count($referencingAliases)) > 0; } else { $referencingAliases = array(); $isReferenced = false; } if (1 === count($referencingAliases) && false === $isReferenced) { $container->setDefinition((string) reset($referencingAliases), $definition); $definition->setPublic(true); $container->removeDefinition($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'replaces alias '.reset($referencingAliases))); } elseif (0 === count($referencingAliases) && false === $isReferenced) { $container->removeDefinition($id); $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'unused')); $hasChanged = true; } } if ($hasChanged) { $this->repeatedPass->setRepeat(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; /** * Represents an edge in your service graph. * * Value is typically a reference. * * @author Johannes M. Schmitt */ class ServiceReferenceGraphEdge { private $sourceNode; private $destNode; private $value; /** * Constructor. * * @param ServiceReferenceGraphNode $sourceNode * @param ServiceReferenceGraphNode $destNode * @param string $value */ public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null) { $this->sourceNode = $sourceNode; $this->destNode = $destNode; $this->value = $value; } /** * Returns the value of the edge. * * @return ServiceReferenceGraphNode */ public function getValue() { return $this->value; } /** * Returns the source node. * * @return ServiceReferenceGraphNode */ public function getSourceNode() { return $this->sourceNode; } /** * Returns the destination node. * * @return ServiceReferenceGraphNode */ public function getDestNode() { return $this->destNode; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Inline service definitions where this is possible. * * @author Johannes M. Schmitt */ class InlineServiceDefinitionsPass implements RepeatablePassInterface { private $repeatedPass; private $graph; private $compiler; private $formatter; private $currentId; /** * {@inheritdoc} */ public function setRepeatedPass(RepeatedPass $repeatedPass) { $this->repeatedPass = $repeatedPass; } /** * Processes the ContainerBuilder for inline service definitions. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->compiler = $container->getCompiler(); $this->formatter = $this->compiler->getLoggingFormatter(); $this->graph = $this->compiler->getServiceReferenceGraph(); foreach ($container->getDefinitions() as $id => $definition) { $this->currentId = $id; $definition->setArguments( $this->inlineArguments($container, $definition->getArguments()) ); $definition->setMethodCalls( $this->inlineArguments($container, $definition->getMethodCalls()) ); $definition->setProperties( $this->inlineArguments($container, $definition->getProperties()) ); } } /** * Processes inline arguments. * * @param ContainerBuilder $container The ContainerBuilder * @param array $arguments An array of arguments * * @return array */ private function inlineArguments(ContainerBuilder $container, array $arguments) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->inlineArguments($container, $argument); } elseif ($argument instanceof Reference) { if (!$container->hasDefinition($id = (string) $argument)) { continue; } if ($this->isInlineableDefinition($container, $id, $definition = $container->getDefinition($id))) { $this->compiler->addLogMessage($this->formatter->formatInlineService($this, $id, $this->currentId)); if (ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope()) { $arguments[$k] = $definition; } else { $arguments[$k] = clone $definition; } } } elseif ($argument instanceof Definition) { $argument->setArguments($this->inlineArguments($container, $argument->getArguments())); $argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls())); $argument->setProperties($this->inlineArguments($container, $argument->getProperties())); } } return $arguments; } /** * Checks if the definition is inlineable. * * @param ContainerBuilder $container * @param string $id * @param Definition $definition * * @return bool If the definition is inlineable */ private function isInlineableDefinition(ContainerBuilder $container, $id, Definition $definition) { if (ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) { return true; } if ($definition->isPublic() || $definition->isLazy()) { return false; } if (!$this->graph->hasNode($id)) { return true; } if ($this->currentId == $id) { return false; } $ids = array(); foreach ($this->graph->getNode($id)->getInEdges() as $edge) { $ids[] = $edge->getSourceNode()->getId(); } if (count(array_unique($ids)) > 1) { return false; } if (count($ids) > 1 && is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) { return false; } if (count($ids) > 1 && $definition->getFactoryService()) { return false; } return $container->getDefinition(reset($ids))->getScope() === $definition->getScope(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * This pass validates each definition individually only taking the information * into account which is contained in the definition itself. * * Later passes can rely on the following, and specifically do not need to * perform these checks themselves: * * - non synthetic, non abstract services always have a class set * - synthetic services are always public * - synthetic services are always of non-prototype scope * * @author Johannes M. Schmitt */ class CheckDefinitionValidityPass implements CompilerPassInterface { /** * Processes the ContainerBuilder to validate the Definition. * * @param ContainerBuilder $container * * @throws RuntimeException When the Definition is invalid */ public function process(ContainerBuilder $container) { foreach ($container->getDefinitions() as $id => $definition) { // synthetic service is public if ($definition->isSynthetic() && !$definition->isPublic()) { throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id)); } // synthetic service has non-prototype scope if ($definition->isSynthetic() && ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) { throw new RuntimeException(sprintf('A synthetic service ("%s") cannot be of scope "prototype".', $id)); } if ($definition->getFactory() && ($definition->getFactoryClass() || $definition->getFactoryService() || $definition->getFactoryMethod())) { throw new RuntimeException(sprintf('A service ("%s") can use either the old or the new factory syntax, not both.', $id)); } // non-synthetic, non-abstract service has class if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) { if ($definition->getFactory() || $definition->getFactoryClass() || $definition->getFactoryService()) { throw new RuntimeException(sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id)); } throw new RuntimeException(sprintf( 'The definition for "%s" has no class. If you intend to inject ' .'this service dynamically at runtime, please mark it as synthetic=true. ' .'If this is an abstract definition solely used by child definitions, ' .'please add abstract=true, otherwise specify a class to get rid of this error.', $id )); } // tag attribute values must be scalars foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { foreach ($attributes as $attribute => $value) { if (!is_scalar($value) && null !== $value) { throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $name, $attribute)); } } } } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; /** * Merges extension configs into the container builder. * * @author Fabien Potencier */ class MergeExtensionConfigurationPass implements CompilerPassInterface { /** * {@inheritdoc} */ public function process(ContainerBuilder $container) { $parameters = $container->getParameterBag()->all(); $definitions = $container->getDefinitions(); $aliases = $container->getAliases(); $exprLangProviders = $container->getExpressionLanguageProviders(); foreach ($container->getExtensions() as $extension) { if ($extension instanceof PrependExtensionInterface) { $extension->prepend($container); } } foreach ($container->getExtensions() as $name => $extension) { if (!$config = $container->getExtensionConfig($name)) { // this extension was not called continue; } $config = $container->getParameterBag()->resolveValue($config); $tmpContainer = new ContainerBuilder($container->getParameterBag()); $tmpContainer->setResourceTracking($container->isTrackingResources()); $tmpContainer->addObjectResource($extension); foreach ($exprLangProviders as $provider) { $tmpContainer->addExpressionLanguageProvider($provider); } $extension->load($config, $tmpContainer); $container->merge($tmpContainer); $container->getParameterBag()->add($parameters); } $container->addDefinitions($definitions); $container->addAliases($aliases); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Run this pass before passes that need to know more about the relation of * your services. * * This class will populate the ServiceReferenceGraph with information. You can * retrieve the graph in other passes from the compiler. * * @author Johannes M. Schmitt */ class AnalyzeServiceReferencesPass implements RepeatablePassInterface { private $graph; private $container; private $currentId; private $currentDefinition; private $repeatedPass; private $onlyConstructorArguments; /** * Constructor. * * @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls */ public function __construct($onlyConstructorArguments = false) { $this->onlyConstructorArguments = (bool) $onlyConstructorArguments; } /** * {@inheritdoc} */ public function setRepeatedPass(RepeatedPass $repeatedPass) { $this->repeatedPass = $repeatedPass; } /** * Processes a ContainerBuilder object to populate the service reference graph. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->container = $container; $this->graph = $container->getCompiler()->getServiceReferenceGraph(); $this->graph->clear(); foreach ($container->getDefinitions() as $id => $definition) { if ($definition->isSynthetic() || $definition->isAbstract()) { continue; } $this->currentId = $id; $this->currentDefinition = $definition; $this->processArguments($definition->getArguments()); if ($definition->getFactoryService()) { $this->processArguments(array(new Reference($definition->getFactoryService()))); } if (is_array($definition->getFactory())) { $this->processArguments($definition->getFactory()); } if (!$this->onlyConstructorArguments) { $this->processArguments($definition->getMethodCalls()); $this->processArguments($definition->getProperties()); if ($definition->getConfigurator()) { $this->processArguments(array($definition->getConfigurator())); } } } foreach ($container->getAliases() as $id => $alias) { $this->graph->connect($id, $alias, (string) $alias, $this->getDefinition((string) $alias), null); } } /** * Processes service definitions for arguments to find relationships for the service graph. * * @param array $arguments An array of Reference or Definition objects relating to service definitions */ private function processArguments(array $arguments) { foreach ($arguments as $argument) { if (is_array($argument)) { $this->processArguments($argument); } elseif ($argument instanceof Reference) { $this->graph->connect( $this->currentId, $this->currentDefinition, $this->getDefinitionId((string) $argument), $this->getDefinition((string) $argument), $argument ); } elseif ($argument instanceof Definition) { $this->processArguments($argument->getArguments()); $this->processArguments($argument->getMethodCalls()); $this->processArguments($argument->getProperties()); if (is_array($argument->getFactory())) { $this->processArguments($argument->getFactory()); } if ($argument->getFactoryService()) { $this->processArguments(array(new Reference($argument->getFactoryService()))); } } } } /** * Returns a service definition given the full name or an alias. * * @param string $id A full id or alias for a service definition. * * @return Definition|null The definition related to the supplied id */ private function getDefinition($id) { $id = $this->getDefinitionId($id); return null === $id ? null : $this->container->getDefinition($id); } private function getDefinitionId($id) { while ($this->container->hasAlias($id)) { $id = (string) $this->container->getAlias($id); } if (!$this->container->hasDefinition($id)) { return; } return $id; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Checks your services for circular references. * * References from method calls are ignored since we might be able to resolve * these references depending on the order in which services are called. * * Circular reference from method calls will only be detected at run-time. * * @author Johannes M. Schmitt */ class CheckCircularReferencesPass implements CompilerPassInterface { private $currentPath; private $checkedNodes; /** * Checks the ContainerBuilder object for circular references. * * @param ContainerBuilder $container The ContainerBuilder instances */ public function process(ContainerBuilder $container) { $graph = $container->getCompiler()->getServiceReferenceGraph(); $this->checkedNodes = array(); foreach ($graph->getNodes() as $id => $node) { $this->currentPath = array($id); $this->checkOutEdges($node->getOutEdges()); } } /** * Checks for circular references. * * @param ServiceReferenceGraphEdge[] $edges An array of Edges * * @throws ServiceCircularReferenceException When a circular reference is found. */ private function checkOutEdges(array $edges) { foreach ($edges as $edge) { $node = $edge->getDestNode(); $id = $node->getId(); if (empty($this->checkedNodes[$id])) { $searchKey = array_search($id, $this->currentPath); $this->currentPath[] = $id; if (false !== $searchKey) { throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey)); } $this->checkOutEdges($node->getOutEdges()); $this->checkedNodes[$id] = true; array_pop($this->currentPath); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; /** * Replaces aliases with actual service definitions, effectively removing these * aliases. * * @author Johannes M. Schmitt */ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface { private $compiler; private $formatter; private $sourceId; /** * Process the Container to replace aliases with service definitions. * * @param ContainerBuilder $container * * @throws InvalidArgumentException if the service definition does not exist */ public function process(ContainerBuilder $container) { $this->compiler = $container->getCompiler(); $this->formatter = $this->compiler->getLoggingFormatter(); foreach ($container->getAliases() as $id => $alias) { $aliasId = (string) $alias; try { $definition = $container->getDefinition($aliasId); } catch (InvalidArgumentException $e) { throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with "%s".', $alias, $id), null, $e); } if ($definition->isPublic()) { continue; } $definition->setPublic(true); $container->setDefinition($id, $definition); $container->removeDefinition($aliasId); $this->updateReferences($container, $aliasId, $id); // we have to restart the process due to concurrent modification of // the container $this->process($container); break; } } /** * Updates references to remove aliases. * * @param ContainerBuilder $container The container * @param string $currentId The alias identifier being replaced * @param string $newId The id of the service the alias points to */ private function updateReferences($container, $currentId, $newId) { foreach ($container->getAliases() as $id => $alias) { if ($currentId === (string) $alias) { $container->setAlias($id, $newId); } } foreach ($container->getDefinitions() as $id => $definition) { $this->sourceId = $id; $definition->setArguments( $this->updateArgumentReferences($definition->getArguments(), $currentId, $newId) ); $definition->setMethodCalls( $this->updateArgumentReferences($definition->getMethodCalls(), $currentId, $newId) ); $definition->setProperties( $this->updateArgumentReferences($definition->getProperties(), $currentId, $newId) ); } } /** * Updates argument references. * * @param array $arguments An array of Arguments * @param string $currentId The alias identifier * @param string $newId The identifier the alias points to * * @return array */ private function updateArgumentReferences(array $arguments, $currentId, $newId) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this->updateArgumentReferences($argument, $currentId, $newId); } elseif ($argument instanceof Reference) { if ($currentId === (string) $argument) { $arguments[$k] = new Reference($newId, $argument->getInvalidBehavior()); $this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $this->sourceId, $currentId, $newId)); } } } return $arguments; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Interface that must be implemented by compilation passes. * * @author Johannes M. Schmitt * * @api */ interface CompilerPassInterface { /** * You can modify the container here before it is dumped to PHP code. * * @param ContainerBuilder $container * * @api */ public function process(ContainerBuilder $container); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface; /** * Adds some function to the default ExpressionLanguage. * * @author Fabien Potencier * * @see ExpressionLanguageProvider */ class ExpressionLanguage extends BaseExpressionLanguage { public function __construct(ParserCacheInterface $cache = null, array $providers = array()) { // prepend the default provider to let users override it easily array_unshift($providers, new ExpressionLanguageProvider()); parent::__construct($cache, $providers); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; /** * ContainerInterface is the interface implemented by service container classes. * * @author Fabien Potencier * @author Johannes M. Schmitt * * @api */ interface ContainerInterface { const EXCEPTION_ON_INVALID_REFERENCE = 1; const NULL_ON_INVALID_REFERENCE = 2; const IGNORE_ON_INVALID_REFERENCE = 3; const SCOPE_CONTAINER = 'container'; const SCOPE_PROTOTYPE = 'prototype'; /** * Sets a service. * * @param string $id The service identifier * @param object $service The service instance * @param string $scope The scope of the service * * @api */ public function set($id, $service, $scope = self::SCOPE_CONTAINER); /** * Gets a service. * * @param string $id The service identifier * @param int $invalidBehavior The behavior when the service does not exist * * @return object The associated service * * @throws ServiceCircularReferenceException When a circular reference is detected * @throws ServiceNotFoundException When the service is not defined * * @see Reference * * @api */ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE); /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return bool true if the service is defined, false otherwise * * @api */ public function has($id); /** * Gets a parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws InvalidArgumentException if the parameter is not defined * * @api */ public function getParameter($name); /** * Checks if a parameter exists. * * @param string $name The parameter name * * @return bool The presence of parameter in container * * @api */ public function hasParameter($name); /** * Sets a parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @api */ public function setParameter($name, $value); /** * Enters the given scope. * * @param string $name * * @api */ public function enterScope($name); /** * Leaves the current scope, and re-enters the parent scope. * * @param string $name * * @api */ public function leaveScope($name); /** * Adds a scope to the container. * * @param ScopeInterface $scope * * @api */ public function addScope(ScopeInterface $scope); /** * Whether this container has the given scope. * * @param string $name * * @return bool * * @api */ public function hasScope($name); /** * Determines whether the given scope is currently active. * * It does however not check if the scope actually exists. * * @param string $name * * @return bool * * @api */ public function isScopeActive($name); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader; use Symfony\Component\Config\FileLocatorInterface; /** * FileLoader is the abstract class used by all built-in loaders that are file based. * * @author Fabien Potencier */ abstract class FileLoader extends BaseFileLoader { protected $container; /** * Constructor. * * @param ContainerBuilder $container A ContainerBuilder instance * @param FileLocatorInterface $locator A FileLocator instance */ public function __construct(ContainerBuilder $container, FileLocatorInterface $locator) { $this->container = $container; parent::__construct($locator); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\ExpressionLanguage\Expression; /** * XmlFileLoader loads XML files service definitions. * * @author Fabien Potencier */ class XmlFileLoader extends FileLoader { const NS = 'http://symfony.com/schema/dic/services'; /** * {@inheritdoc} */ public function load($resource, $type = null) { $path = $this->locator->locate($resource); $xml = $this->parseFileToDOM($path); $this->container->addResource(new FileResource($path)); // anonymous services $this->processAnonymousServices($xml, $path); // imports $this->parseImports($xml, $path); // parameters $this->parseParameters($xml); // extensions $this->loadFromExtensions($xml); // services $this->parseDefinitions($xml, $path); } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION); } /** * Parses parameters. * * @param \DOMDocument $xml */ private function parseParameters(\DOMDocument $xml) { if ($parameters = $this->getChildren($xml->documentElement, 'parameters')) { $this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter')); } } /** * Parses imports. * * @param \DOMDocument $xml * @param string $file */ private function parseImports(\DOMDocument $xml, $file) { $xpath = new \DOMXPath($xml); $xpath->registerNamespace('container', self::NS); if (false === $imports = $xpath->query('//container:imports/container:import')) { return; } foreach ($imports as $import) { $this->setCurrentDir(dirname($file)); $this->import($import->getAttribute('resource'), null, (bool) XmlUtils::phpize($import->getAttribute('ignore-errors')), $file); } } /** * Parses multiple definitions. * * @param \DOMDocument $xml * @param string $file */ private function parseDefinitions(\DOMDocument $xml, $file) { $xpath = new \DOMXPath($xml); $xpath->registerNamespace('container', self::NS); if (false === $services = $xpath->query('//container:services/container:service')) { return; } foreach ($services as $service) { $this->parseDefinition((string) $service->getAttribute('id'), $service, $file); } } /** * Parses an individual Definition. * * @param string $id * @param \DOMElement $service * @param string $file */ private function parseDefinition($id, \DOMElement $service, $file) { if ($alias = $service->getAttribute('alias')) { $public = true; if ($publicAttr = $service->getAttribute('public')) { $public = XmlUtils::phpize($publicAttr); } $this->container->setAlias($id, new Alias($alias, $public)); return; } if ($parent = $service->getAttribute('parent')) { $definition = new DefinitionDecorator($parent); } else { $definition = new Definition(); } foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'lazy', 'abstract') as $key) { if ($value = $service->getAttribute($key)) { $method = 'set'.str_replace('-', '', $key); $definition->$method(XmlUtils::phpize($value)); } } if ($files = $this->getChildren($service, 'file')) { $definition->setFile($files[0]->nodeValue); } $definition->setArguments($this->getArgumentsAsPhp($service, 'argument')); $definition->setProperties($this->getArgumentsAsPhp($service, 'property')); if ($factories = $this->getChildren($service, 'factory')) { $factory = $factories[0]; if ($function = $factory->getAttribute('function')) { $definition->setFactory($function); } else { if ($childService = $factory->getAttribute('service')) { $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false); } else { $class = $factory->getAttribute('class'); } $definition->setFactory(array($class, $factory->getAttribute('method'))); } } if ($configurators = $this->getChildren($service, 'configurator')) { $configurator = $configurators[0]; if ($function = $configurator->getAttribute('function')) { $definition->setConfigurator($function); } else { if ($childService = $configurator->getAttribute('service')) { $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false); } else { $class = $configurator->getAttribute('class'); } $definition->setConfigurator(array($class, $configurator->getAttribute('method'))); } } foreach ($this->getChildren($service, 'call') as $call) { $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument')); } foreach ($this->getChildren($service, 'tag') as $tag) { $parameters = array(); foreach ($tag->attributes as $name => $node) { if ('name' === $name) { continue; } if (false !== strpos($name, '-') && false === strpos($name, '_') && !array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) { $parameters[$normalizedName] = XmlUtils::phpize($node->nodeValue); } // keep not normalized key for BC too $parameters[$name] = XmlUtils::phpize($node->nodeValue); } $definition->addTag($tag->getAttribute('name'), $parameters); } if ($value = $service->getAttribute('decorates')) { $renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null; $definition->setDecoratedService($value, $renameId); } $this->container->setDefinition($id, $definition); } /** * Parses a XML file to a \DOMDocument * * @param string $file Path to a file * * @return \DOMDocument * * @throws InvalidArgumentException When loading of XML file returns error */ private function parseFileToDOM($file) { try { $dom = XmlUtils::loadFile($file, array($this, 'validateSchema')); } catch (\InvalidArgumentException $e) { throw new InvalidArgumentException(sprintf('Unable to parse file "%s".', $file), $e->getCode(), $e); } $this->validateExtensions($dom, $file); return $dom; } /** * Processes anonymous services. * * @param \DOMDocument $xml * @param string $file */ private function processAnonymousServices(\DOMDocument $xml, $file) { $definitions = array(); $count = 0; $xpath = new \DOMXPath($xml); $xpath->registerNamespace('container', self::NS); // anonymous services as arguments/properties if (false !== $nodes = $xpath->query('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]')) { foreach ($nodes as $node) { // give it a unique name $id = sprintf('%s_%d', hash('sha256', $file), ++$count); $node->setAttribute('id', $id); if ($services = $this->getChildren($node, 'service')) { $definitions[$id] = array($services[0], $file, false); $services[0]->setAttribute('id', $id); } } } // anonymous services "in the wild" if (false !== $nodes = $xpath->query('//container:services/container:service[not(@id)]')) { foreach ($nodes as $node) { // give it a unique name $id = sprintf('%s_%d', hash('sha256', $file), ++$count); $node->setAttribute('id', $id); if ($services = $this->getChildren($node, 'service')) { $definitions[$id] = array($node, $file, true); $services[0]->setAttribute('id', $id); } } } // resolve definitions krsort($definitions); foreach ($definitions as $id => $def) { list($domElement, $file, $wild) = $def; // anonymous services are always private // we could not use the constant false here, because of XML parsing $domElement->setAttribute('public', 'false'); $this->parseDefinition($id, $domElement, $file); if (true === $wild) { $tmpDomElement = new \DOMElement('_services', null, self::NS); $domElement->parentNode->replaceChild($tmpDomElement, $domElement); $tmpDomElement->setAttribute('id', $id); } else { $domElement->parentNode->removeChild($domElement); } } } /** * Returns arguments as valid php types. * * @param \DOMElement $node * @param string $name * @param bool $lowercase * * @return mixed */ private function getArgumentsAsPhp(\DOMElement $node, $name, $lowercase = true) { $arguments = array(); foreach ($this->getChildren($node, $name) as $arg) { if ($arg->hasAttribute('name')) { $arg->setAttribute('key', $arg->getAttribute('name')); } if (!$arg->hasAttribute('key')) { $key = !$arguments ? 0 : max(array_keys($arguments)) + 1; } else { $key = $arg->getAttribute('key'); } // parameter keys are case insensitive if ('parameter' == $name && $lowercase) { $key = strtolower($key); } // this is used by DefinitionDecorator to overwrite a specific // argument of the parent definition if ($arg->hasAttribute('index')) { $key = 'index_'.$arg->getAttribute('index'); } switch ($arg->getAttribute('type')) { case 'service': $onInvalid = $arg->getAttribute('on-invalid'); $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; if ('ignore' == $onInvalid) { $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; } elseif ('null' == $onInvalid) { $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; } if ($strict = $arg->getAttribute('strict')) { $strict = XmlUtils::phpize($strict); } else { $strict = true; } $arguments[$key] = new Reference($arg->getAttribute('id'), $invalidBehavior, $strict); break; case 'expression': $arguments[$key] = new Expression($arg->nodeValue); break; case 'collection': $arguments[$key] = $this->getArgumentsAsPhp($arg, $name, false); break; case 'string': $arguments[$key] = $arg->nodeValue; break; case 'constant': $arguments[$key] = constant($arg->nodeValue); break; default: $arguments[$key] = XmlUtils::phpize($arg->nodeValue); } } return $arguments; } /** * Get child elements by name * * @param \DOMNode $node * @param mixed $name * * @return array */ private function getChildren(\DOMNode $node, $name) { $children = array(); foreach ($node->childNodes as $child) { if ($child instanceof \DOMElement && $child->localName === $name && $child->namespaceURI === self::NS) { $children[] = $child; } } return $children; } /** * Validates a documents XML schema. * * @param \DOMDocument $dom * * @return bool * * @throws RuntimeException When extension references a non-existent XSD file */ public function validateSchema(\DOMDocument $dom) { $schemaLocations = array('http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd')); if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) { $items = preg_split('/\s+/', $element); for ($i = 0, $nb = count($items); $i < $nb; $i += 2) { if (!$this->container->hasExtension($items[$i])) { continue; } if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) { $path = str_replace($extension->getNamespace(), str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]); if (!is_file($path)) { throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s"', get_class($extension), $path)); } $schemaLocations[$items[$i]] = $path; } } } $tmpfiles = array(); $imports = ''; foreach ($schemaLocations as $namespace => $location) { $parts = explode('/', $location); if (0 === stripos($location, 'phar://')) { $tmpfile = tempnam(sys_get_temp_dir(), 'sf2'); if ($tmpfile) { copy($location, $tmpfile); $tmpfiles[] = $tmpfile; $parts = explode('/', str_replace('\\', '/', $tmpfile)); } } $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts)); $imports .= sprintf(' '."\n", $namespace, $location); } $source = << $imports EOF ; $valid = @$dom->schemaValidateSource($source); foreach ($tmpfiles as $tmpfile) { @unlink($tmpfile); } return $valid; } /** * Validates an extension. * * @param \DOMDocument $dom * @param string $file * * @throws InvalidArgumentException When no extension is found corresponding to a tag */ private function validateExtensions(\DOMDocument $dom, $file) { foreach ($dom->documentElement->childNodes as $node) { if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) { continue; } // can it be handled by an extension? if (!$this->container->hasExtension($node->namespaceURI)) { $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getNamespace(); }, $this->container->getExtensions())); throw new InvalidArgumentException(sprintf( 'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none' )); } } } /** * Loads from an extension. * * @param \DOMDocument $xml */ private function loadFromExtensions(\DOMDocument $xml) { foreach ($xml->documentElement->childNodes as $node) { if (!$node instanceof \DOMElement || $node->namespaceURI === self::NS) { continue; } $values = static::convertDomElementToArray($node); if (!is_array($values)) { $values = array(); } $this->container->loadFromExtension($node->namespaceURI, $values); } } /** * Converts a \DomElement object to a PHP array. * * The following rules applies during the conversion: * * * Each tag is converted to a key value or an array * if there is more than one "value" * * * The content of a tag is set under a "value" key (bar) * if the tag also has some nested tags * * * The attributes are converted to keys () * * * The nested-tags are converted to keys (bar) * * @param \DomElement $element A \DomElement instance * * @return array A PHP array */ public static function convertDomElementToArray(\DomElement $element) { return XmlUtils::convertDomElementToArray($element); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\ExpressionLanguage\Expression; /** * YamlFileLoader loads YAML files service definitions. * * The YAML format does not support anonymous services (cf. the XML loader). * * @author Fabien Potencier */ class YamlFileLoader extends FileLoader { private $yamlParser; /** * {@inheritdoc} */ public function load($resource, $type = null) { $path = $this->locator->locate($resource); $content = $this->loadFile($path); $this->container->addResource(new FileResource($path)); // empty file if (null === $content) { return; } // imports $this->parseImports($content, $path); // parameters if (isset($content['parameters'])) { if (!is_array($content['parameters'])) { throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $resource)); } foreach ($content['parameters'] as $key => $value) { $this->container->setParameter($key, $this->resolveServices($value)); } } // extensions $this->loadFromExtensions($content); // services $this->parseDefinitions($content, $resource); } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return is_string($resource) && in_array(pathinfo($resource, PATHINFO_EXTENSION), array('yml', 'yaml'), true); } /** * Parses all imports. * * @param array $content * @param string $file */ private function parseImports($content, $file) { if (!isset($content['imports'])) { return; } if (!is_array($content['imports'])) { throw new InvalidArgumentException(sprintf('The "imports" key should contain an array in %s. Check your YAML syntax.', $file)); } foreach ($content['imports'] as $import) { if (!is_array($import)) { throw new InvalidArgumentException(sprintf('The values in the "imports" key should be arrays in %s. Check your YAML syntax.', $file)); } $this->setCurrentDir(dirname($file)); $this->import($import['resource'], null, isset($import['ignore_errors']) ? (bool) $import['ignore_errors'] : false, $file); } } /** * Parses definitions. * * @param array $content * @param string $file */ private function parseDefinitions($content, $file) { if (!isset($content['services'])) { return; } if (!is_array($content['services'])) { throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file)); } foreach ($content['services'] as $id => $service) { $this->parseDefinition($id, $service, $file); } } /** * Parses a definition. * * @param string $id * @param array $service * @param string $file * * @throws InvalidArgumentException When tags are invalid */ private function parseDefinition($id, $service, $file) { if (is_string($service) && 0 === strpos($service, '@')) { $this->container->setAlias($id, substr($service, 1)); return; } if (!is_array($service)) { throw new InvalidArgumentException(sprintf('A service definition must be an array or a string starting with "@" but %s found for service "%s" in %s. Check your YAML syntax.', gettype($service), $id, $file)); } if (isset($service['alias'])) { $public = !array_key_exists('public', $service) || (bool) $service['public']; $this->container->setAlias($id, new Alias($service['alias'], $public)); return; } if (isset($service['parent'])) { $definition = new DefinitionDecorator($service['parent']); } else { $definition = new Definition(); } if (isset($service['class'])) { $definition->setClass($service['class']); } if (isset($service['scope'])) { $definition->setScope($service['scope']); } if (isset($service['synthetic'])) { $definition->setSynthetic($service['synthetic']); } if (isset($service['synchronized'])) { $definition->setSynchronized($service['synchronized']); } if (isset($service['lazy'])) { $definition->setLazy($service['lazy']); } if (isset($service['public'])) { $definition->setPublic($service['public']); } if (isset($service['abstract'])) { $definition->setAbstract($service['abstract']); } if (isset($service['factory'])) { if (is_string($service['factory'])) { if (strpos($service['factory'], ':') !== false && strpos($service['factory'], '::') === false) { $parts = explode(':', $service['factory']); $definition->setFactory(array($this->resolveServices('@'.$parts[0]), $parts[1])); } else { $definition->setFactory($service['factory']); } } else { $definition->setFactory(array($this->resolveServices($service['factory'][0]), $service['factory'][1])); } } if (isset($service['factory_class'])) { $definition->setFactoryClass($service['factory_class']); } if (isset($service['factory_method'])) { $definition->setFactoryMethod($service['factory_method']); } if (isset($service['factory_service'])) { $definition->setFactoryService($service['factory_service']); } if (isset($service['file'])) { $definition->setFile($service['file']); } if (isset($service['arguments'])) { $definition->setArguments($this->resolveServices($service['arguments'])); } if (isset($service['properties'])) { $definition->setProperties($this->resolveServices($service['properties'])); } if (isset($service['configurator'])) { if (is_string($service['configurator'])) { $definition->setConfigurator($service['configurator']); } else { $definition->setConfigurator(array($this->resolveServices($service['configurator'][0]), $service['configurator'][1])); } } if (isset($service['calls'])) { if (!is_array($service['calls'])) { throw new InvalidArgumentException(sprintf('Parameter "calls" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); } foreach ($service['calls'] as $call) { $args = isset($call[1]) ? $this->resolveServices($call[1]) : array(); $definition->addMethodCall($call[0], $args); } } if (isset($service['tags'])) { if (!is_array($service['tags'])) { throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); } foreach ($service['tags'] as $tag) { if (!is_array($tag)) { throw new InvalidArgumentException(sprintf('A "tags" entry must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); } if (!isset($tag['name'])) { throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file)); } $name = $tag['name']; unset($tag['name']); foreach ($tag as $attribute => $value) { if (!is_scalar($value) && null !== $value) { throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in %s. Check your YAML syntax.', $id, $name, $attribute, $file)); } } $definition->addTag($name, $tag); } } if (isset($service['decorates'])) { $renameId = isset($service['decoration_inner_name']) ? $service['decoration_inner_name'] : null; $definition->setDecoratedService($service['decorates'], $renameId); } $this->container->setDefinition($id, $definition); } /** * Loads a YAML file. * * @param string $file * * @return array The file content * * @throws InvalidArgumentException when the given file is not a local file or when it does not exist */ protected function loadFile($file) { if (!class_exists('Symfony\Component\Yaml\Parser')) { throw new RuntimeException('Unable to load YAML config files as the Symfony Yaml Component is not installed.'); } if (!stream_is_local($file)) { throw new InvalidArgumentException(sprintf('This is not a local file "%s".', $file)); } if (!file_exists($file)) { throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } return $this->validate($this->yamlParser->parse(file_get_contents($file)), $file); } /** * Validates a YAML file. * * @param mixed $content * @param string $file * * @return array * * @throws InvalidArgumentException When service file is not valid */ private function validate($content, $file) { if (null === $content) { return $content; } if (!is_array($content)) { throw new InvalidArgumentException(sprintf('The service file "%s" is not valid. It should contain an array. Check your YAML syntax.', $file)); } foreach ($content as $namespace => $data) { if (in_array($namespace, array('imports', 'parameters', 'services'))) { continue; } if (!$this->container->hasExtension($namespace)) { $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getAlias(); }, $this->container->getExtensions())); throw new InvalidArgumentException(sprintf( 'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $namespace, $file, $namespace, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none' )); } } return $content; } /** * Resolves services. * * @param string|array $value * * @return array|string|Reference */ private function resolveServices($value) { if (is_array($value)) { $value = array_map(array($this, 'resolveServices'), $value); } elseif (is_string($value) && 0 === strpos($value, '@=')) { return new Expression(substr($value, 2)); } elseif (is_string($value) && 0 === strpos($value, '@')) { if (0 === strpos($value, '@@')) { $value = substr($value, 1); $invalidBehavior = null; } elseif (0 === strpos($value, '@?')) { $value = substr($value, 2); $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; } else { $value = substr($value, 1); $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; } if ('=' === substr($value, -1)) { $value = substr($value, 0, -1); $strict = false; } else { $strict = true; } if (null !== $invalidBehavior) { $value = new Reference($value, $invalidBehavior, $strict); } } return $value; } /** * Loads from Extensions. * * @param array $content */ private function loadFromExtensions($content) { foreach ($content as $namespace => $values) { if (in_array($namespace, array('imports', 'parameters', 'services'))) { continue; } if (!is_array($values)) { $values = array(); } $this->container->loadFromExtension($namespace, $values); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\Config\Resource\FileResource; /** * PhpFileLoader loads service definitions from a PHP file. * * The PHP file is required and the $container variable can be * used within the file to change the container. * * @author Fabien Potencier */ class PhpFileLoader extends FileLoader { /** * {@inheritdoc} */ public function load($resource, $type = null) { // the container and loader variables are exposed to the included file below $container = $this->container; $loader = $this; $path = $this->locator->locate($resource); $this->setCurrentDir(dirname($path)); $this->container->addResource(new FileResource($path)); include $path; } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\Loader\Loader; /** * ClosureLoader loads service definitions from a PHP closure. * * The Closure has access to the container as its first argument. * * @author Fabien Potencier */ class ClosureLoader extends Loader { private $container; /** * Constructor. * * @param ContainerBuilder $container A ContainerBuilder instance */ public function __construct(ContainerBuilder $container) { $this->container = $container; } /** * {@inheritdoc} */ public function load($resource, $type = null) { call_user_func($resource, $this->container); } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return $resource instanceof \Closure; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; /** * IniFileLoader loads parameters from INI files. * * @author Fabien Potencier */ class IniFileLoader extends FileLoader { /** * {@inheritdoc} */ public function load($resource, $type = null) { $path = $this->locator->locate($resource); $this->container->addResource(new FileResource($path)); $result = parse_ini_file($path, true); if (false === $result || array() === $result) { throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $resource)); } if (isset($result['parameters']) && is_array($result['parameters'])) { foreach ($result['parameters'] as $key => $value) { $this->container->setParameter($key, $value); } } } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return is_string($resource) && 'ini' === pathinfo($resource, PATHINFO_EXTENSION); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console; /** * Contains all events dispatched by an Application. * * @author Francesco Levorato */ final class ConsoleEvents { /** * The COMMAND event allows you to attach listeners before any command is * executed by the console. It also allows you to modify the command, input and output * before they are handled to the command. * * The event listener method receives a Symfony\Component\Console\Event\ConsoleCommandEvent * instance. * * @Event * * @var string */ const COMMAND = 'console.command'; /** * The TERMINATE event allows you to attach listeners after a command is * executed by the console. * * The event listener method receives a Symfony\Component\Console\Event\ConsoleTerminateEvent * instance. * * @Event * * @var string */ const TERMINATE = 'console.terminate'; /** * The EXCEPTION event occurs when an uncaught exception appears. * * This event allows you to deal with the exception or * to modify the thrown exception. The event listener method receives * a Symfony\Component\Console\Event\ConsoleExceptionEvent * instance. * * @Event * * @var string */ const EXCEPTION = 'console.exception'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * Markdown descriptor. * * @author Jean-François Simon * * @internal */ class MarkdownDescriptor extends Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { $this->write( '**'.$argument->getName().':**'."\n\n" .'* Name: '.($argument->getName() ?: '')."\n" .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" .'* Description: '.($argument->getDescription() ?: '')."\n" .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' ); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { $this->write( '**'.$option->getName().':**'."\n\n" .'* Name: `--'.$option->getName().'`'."\n" .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '')."\n" .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" .'* Description: '.($option->getDescription() ?: '')."\n" .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' ); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { if ($showArguments = count($definition->getArguments()) > 0) { $this->write('### Arguments:'); foreach ($definition->getArguments() as $argument) { $this->write("\n\n"); $this->write($this->describeInputArgument($argument)); } } if (count($definition->getOptions()) > 0) { if ($showArguments) { $this->write("\n\n"); } $this->write('### Options:'); foreach ($definition->getOptions() as $option) { $this->write("\n\n"); $this->write($this->describeInputOption($option)); } } } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $command->getSynopsis(); $command->mergeApplicationDefinition(false); $this->write( $command->getName()."\n" .str_repeat('-', strlen($command->getName()))."\n\n" .'* Description: '.($command->getDescription() ?: '')."\n" .'* Usage: `'.$command->getSynopsis().'`'."\n" .'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '') ); if ($help = $command->getProcessedHelp()) { $this->write("\n\n"); $this->write($help); } if ($command->getNativeDefinition()) { $this->write("\n\n"); $this->describeInputDefinition($command->getNativeDefinition()); } } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); $this->write($application->getName()."\n".str_repeat('=', strlen($application->getName()))); foreach ($description->getNamespaces() as $namespace) { if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { $this->write("\n\n"); $this->write('**'.$namespace['id'].':**'); } $this->write("\n\n"); $this->write(implode("\n", array_map(function ($commandName) { return '* '.$commandName; }, $namespace['commands']))); } foreach ($description->getCommands() as $command) { $this->write("\n\n"); $this->write($this->describeCommand($command)); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Output\OutputInterface; /** * Descriptor interface. * * @author Jean-François Simon */ interface DescriptorInterface { /** * Describes an InputArgument instance. * * @param OutputInterface $output * @param object $object * @param array $options */ public function describe(OutputInterface $output, $object, array $options = array()); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; /** * @author Jean-François Simon * * @internal */ class ApplicationDescription { const GLOBAL_NAMESPACE = '_global'; /** * @var Application */ private $application; /** * @var null|string */ private $namespace; /** * @var array */ private $namespaces; /** * @var Command[] */ private $commands; /** * @var Command[] */ private $aliases; /** * Constructor. * * @param Application $application * @param string|null $namespace */ public function __construct(Application $application, $namespace = null) { $this->application = $application; $this->namespace = $namespace; } /** * @return array */ public function getNamespaces() { if (null === $this->namespaces) { $this->inspectApplication(); } return $this->namespaces; } /** * @return Command[] */ public function getCommands() { if (null === $this->commands) { $this->inspectApplication(); } return $this->commands; } /** * @param string $name * * @return Command * * @throws \InvalidArgumentException */ public function getCommand($name) { if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name)); } return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; } private function inspectApplication() { $this->commands = array(); $this->namespaces = array(); $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); foreach ($this->sortCommands($all) as $namespace => $commands) { $names = array(); /** @var Command $command */ foreach ($commands as $name => $command) { if (!$command->getName()) { continue; } if ($command->getName() === $name) { $this->commands[$name] = $command; } else { $this->aliases[$name] = $command; } $names[] = $name; } $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names); } } /** * @param array $commands * * @return array */ private function sortCommands(array $commands) { $namespacedCommands = array(); foreach ($commands as $name => $command) { $key = $this->application->extractNamespace($name, 1); if (!$key) { $key = '_global'; } $namespacedCommands[$key][$name] = $command; } ksort($namespacedCommands); foreach ($namespacedCommands as &$commandsSet) { ksort($commandsSet); } // unset reference to keep scope clear unset($commandsSet); return $namespacedCommands; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * @author Jean-François Simon * * @internal */ abstract class Descriptor implements DescriptorInterface { /** * @var OutputInterface */ private $output; /** * {@inheritdoc} */ public function describe(OutputInterface $output, $object, array $options = array()) { $this->output = $output; switch (true) { case $object instanceof InputArgument: $this->describeInputArgument($object, $options); break; case $object instanceof InputOption: $this->describeInputOption($object, $options); break; case $object instanceof InputDefinition: $this->describeInputDefinition($object, $options); break; case $object instanceof Command: $this->describeCommand($object, $options); break; case $object instanceof Application: $this->describeApplication($object, $options); break; default: throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object))); } } /** * Writes content to output. * * @param string $content * @param bool $decorated */ protected function write($content, $decorated = false) { $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); } /** * Describes an InputArgument instance. * * @param InputArgument $argument * @param array $options * * @return string|mixed */ abstract protected function describeInputArgument(InputArgument $argument, array $options = array()); /** * Describes an InputOption instance. * * @param InputOption $option * @param array $options * * @return string|mixed */ abstract protected function describeInputOption(InputOption $option, array $options = array()); /** * Describes an InputDefinition instance. * * @param InputDefinition $definition * @param array $options * * @return string|mixed */ abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array()); /** * Describes a Command instance. * * @param Command $command * @param array $options * * @return string|mixed */ abstract protected function describeCommand(Command $command, array $options = array()); /** * Describes an Application instance. * * @param Application $application * @param array $options * * @return string|mixed */ abstract protected function describeApplication(Application $application, array $options = array()); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * Text descriptor. * * @author Jean-François Simon * * @internal */ class TextDescriptor extends Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) { $default = sprintf(' (default: %s)', $this->formatDefaultValue($argument->getDefault())); } else { $default = ''; } $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName()); $this->writeText(sprintf(" %-${nameWidth}s %s%s", $argument->getName(), str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription()), $default ), $options); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) { $default = sprintf(' (default: %s)', $this->formatDefaultValue($option->getDefault())); } else { $default = ''; } $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName()); $nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2; $this->writeText(sprintf(" %s %-${nameWithShortcutWidth}s%s%s%s", '--'.$option->getName(), $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()), $default, $option->isArray() ? ' (multiple values allowed)' : '' ), $options); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { $nameWidth = 0; foreach ($definition->getOptions() as $option) { $nameLength = strlen($option->getName()) + 2; if ($option->getShortcut()) { $nameLength += strlen($option->getShortcut()) + 3; } $nameWidth = max($nameWidth, $nameLength); } foreach ($definition->getArguments() as $argument) { $nameWidth = max($nameWidth, strlen($argument->getName())); } ++$nameWidth; if ($definition->getArguments()) { $this->writeText('Arguments:', $options); $this->writeText("\n"); foreach ($definition->getArguments() as $argument) { $this->describeInputArgument($argument, array_merge($options, array('name_width' => $nameWidth))); $this->writeText("\n"); } } if ($definition->getArguments() && $definition->getOptions()) { $this->writeText("\n"); } if ($definition->getOptions()) { $this->writeText('Options:', $options); $this->writeText("\n"); foreach ($definition->getOptions() as $option) { $this->describeInputOption($option, array_merge($options, array('name_width' => $nameWidth))); $this->writeText("\n"); } } } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $command->getSynopsis(); $command->mergeApplicationDefinition(false); $this->writeText('Usage:', $options); $this->writeText("\n"); $this->writeText(' '.$command->getSynopsis(), $options); $this->writeText("\n"); if (count($command->getAliases()) > 0) { $this->writeText("\n"); $this->writeText('Aliases: '.implode(', ', $command->getAliases()).'', $options); } if ($definition = $command->getNativeDefinition()) { $this->writeText("\n"); $this->describeInputDefinition($definition, $options); } $this->writeText("\n"); if ($help = $command->getProcessedHelp()) { $this->writeText('Help:', $options); $this->writeText("\n"); $this->writeText(' '.str_replace("\n", "\n ", $help), $options); $this->writeText("\n"); } } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); if (isset($options['raw_text']) && $options['raw_text']) { $width = $this->getColumnWidth($description->getCommands()); foreach ($description->getCommands() as $command) { $this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options); $this->writeText("\n"); } } else { if ('' != $help = $application->getHelp()) { $this->writeText("$help\n\n", $options); } $this->writeText("Usage:\n", $options); $this->writeText(" command [options] [arguments]\n\n", $options); $this->writeText('Options:', $options); $inputOptions = $application->getDefinition()->getOptions(); $width = 0; foreach ($inputOptions as $option) { $nameLength = strlen($option->getName()) + 2; if ($option->getShortcut()) { $nameLength += strlen($option->getShortcut()) + 3; } $width = max($width, $nameLength); } ++$width; foreach ($inputOptions as $option) { $this->writeText("\n", $options); $this->describeInputOption($option, array_merge($options, array('name_width' => $width))); } $this->writeText("\n\n", $options); $width = $this->getColumnWidth($description->getCommands()); if ($describedNamespace) { $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); } else { $this->writeText('Available commands:', $options); } // add commands by namespace foreach ($description->getNamespaces() as $namespace) { if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { $this->writeText("\n"); $this->writeText(''.$namespace['id'].'', $options); } foreach ($namespace['commands'] as $name) { $this->writeText("\n"); $this->writeText(sprintf(" %-${width}s %s", $name, $description->getCommand($name)->getDescription()), $options); } } $this->writeText("\n"); } } /** * {@inheritdoc} */ private function writeText($content, array $options = array()) { $this->write( isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, isset($options['raw_output']) ? !$options['raw_output'] : true ); } /** * Formats input option/argument default value. * * @param mixed $default * * @return string */ private function formatDefaultValue($default) { if (PHP_VERSION_ID < 50400) { return str_replace('\/', '/', json_encode($default)); } return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } /** * @param Command[] $commands * * @return int */ private function getColumnWidth(array $commands) { $width = 0; foreach ($commands as $command) { $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width; } return $width + 2; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * XML descriptor. * * @author Jean-François Simon * * @internal */ class XmlDescriptor extends Descriptor { /** * @param InputDefinition $definition * * @return \DOMDocument */ public function getInputDefinitionDocument(InputDefinition $definition) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($definitionXML = $dom->createElement('definition')); $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); foreach ($definition->getArguments() as $argument) { $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); } $definitionXML->appendChild($optionsXML = $dom->createElement('options')); foreach ($definition->getOptions() as $option) { $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); } return $dom; } /** * @param Command $command * * @return \DOMDocument */ public function getCommandDocument(Command $command) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($commandXML = $dom->createElement('command')); $command->getSynopsis(); $command->mergeApplicationDefinition(false); $commandXML->setAttribute('id', $command->getName()); $commandXML->setAttribute('name', $command->getName()); $commandXML->appendChild($usageXML = $dom->createElement('usage')); $usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), ''))); $commandXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); $commandXML->appendChild($helpXML = $dom->createElement('help')); $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); $commandXML->appendChild($aliasesXML = $dom->createElement('aliases')); foreach ($command->getAliases() as $alias) { $aliasesXML->appendChild($aliasXML = $dom->createElement('alias')); $aliasXML->appendChild($dom->createTextNode($alias)); } $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition()); $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); return $dom; } /** * @param Application $application * @param string|null $namespace * * @return \DOMDocument */ public function getApplicationDocument(Application $application, $namespace = null) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($rootXml = $dom->createElement('symfony')); if ($application->getName() !== 'UNKNOWN') { $rootXml->setAttribute('name', $application->getName()); if ($application->getVersion() !== 'UNKNOWN') { $rootXml->setAttribute('version', $application->getVersion()); } } $rootXml->appendChild($commandsXML = $dom->createElement('commands')); $description = new ApplicationDescription($application, $namespace); if ($namespace) { $commandsXML->setAttribute('namespace', $namespace); } foreach ($description->getCommands() as $command) { $this->appendDocument($commandsXML, $this->getCommandDocument($command)); } if (!$namespace) { $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); foreach ($description->getNamespaces() as $namespaceDescription) { $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); foreach ($namespaceDescription['commands'] as $name) { $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); $commandXML->appendChild($dom->createTextNode($name)); } } } return $dom; } /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { $this->writeDocument($this->getInputArgumentDocument($argument)); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { $this->writeDocument($this->getInputOptionDocument($option)); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { $this->writeDocument($this->getInputDefinitionDocument($definition)); } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $this->writeDocument($this->getCommandDocument($command)); } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null)); } /** * Appends document children to parent node. * * @param \DOMNode $parentNode * @param \DOMNode $importedParent */ private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) { foreach ($importedParent->childNodes as $childNode) { $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); } } /** * Writes DOM document. * * @param \DOMDocument $dom * * @return \DOMDocument|string */ private function writeDocument(\DOMDocument $dom) { $dom->formatOutput = true; $this->write($dom->saveXML()); } /** * @param InputArgument $argument * * @return \DOMDocument */ private function getInputArgumentDocument(InputArgument $argument) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($objectXML = $dom->createElement('argument')); $objectXML->setAttribute('name', $argument->getName()); $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); $objectXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array())); foreach ($defaults as $default) { $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); $defaultXML->appendChild($dom->createTextNode($default)); } return $dom; } /** * @param InputOption $option * * @return \DOMDocument */ private function getInputOptionDocument(InputOption $option) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($objectXML = $dom->createElement('option')); $objectXML->setAttribute('name', '--'.$option->getName()); $pos = strpos($option->getShortcut(), '|'); if (false !== $pos) { $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut()))); } else { $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); } $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); $objectXML->appendChild($descriptionXML = $dom->createElement('description')); $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); if ($option->acceptValue()) { $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array())); $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); if (!empty($defaults)) { foreach ($defaults as $default) { $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); $defaultXML->appendChild($dom->createTextNode($default)); } } } return $dom; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Descriptor; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; /** * JSON descriptor. * * @author Jean-François Simon * * @internal */ class JsonDescriptor extends Descriptor { /** * {@inheritdoc} */ protected function describeInputArgument(InputArgument $argument, array $options = array()) { $this->writeData($this->getInputArgumentData($argument), $options); } /** * {@inheritdoc} */ protected function describeInputOption(InputOption $option, array $options = array()) { $this->writeData($this->getInputOptionData($option), $options); } /** * {@inheritdoc} */ protected function describeInputDefinition(InputDefinition $definition, array $options = array()) { $this->writeData($this->getInputDefinitionData($definition), $options); } /** * {@inheritdoc} */ protected function describeCommand(Command $command, array $options = array()) { $this->writeData($this->getCommandData($command), $options); } /** * {@inheritdoc} */ protected function describeApplication(Application $application, array $options = array()) { $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; $description = new ApplicationDescription($application, $describedNamespace); $commands = array(); foreach ($description->getCommands() as $command) { $commands[] = $this->getCommandData($command); } $data = $describedNamespace ? array('commands' => $commands, 'namespace' => $describedNamespace) : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces())); $this->writeData($data, $options); } /** * Writes data as json. * * @param array $data * @param array $options * * @return array|string */ private function writeData(array $data, array $options) { $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0)); } /** * @param InputArgument $argument * * @return array */ private function getInputArgumentData(InputArgument $argument) { return array( 'name' => $argument->getName(), 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => $argument->getDescription(), 'default' => $argument->getDefault(), ); } /** * @param InputOption $option * * @return array */ private function getInputOptionData(InputOption $option) { return array( 'name' => '--'.$option->getName(), 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '', 'accept_value' => $option->acceptValue(), 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => $option->getDescription(), 'default' => $option->getDefault(), ); } /** * @param InputDefinition $definition * * @return array */ private function getInputDefinitionData(InputDefinition $definition) { $inputArguments = array(); foreach ($definition->getArguments() as $name => $argument) { $inputArguments[$name] = $this->getInputArgumentData($argument); } $inputOptions = array(); foreach ($definition->getOptions() as $name => $option) { $inputOptions[$name] = $this->getInputOptionData($option); } return array('arguments' => $inputArguments, 'options' => $inputOptions); } /** * @param Command $command * * @return array */ private function getCommandData(Command $command) { $command->getSynopsis(); $command->mergeApplicationDefinition(false); return array( 'name' => $command->getName(), 'usage' => $command->getSynopsis(), 'description' => $command->getDescription(), 'help' => $command->getProcessedHelp(), 'aliases' => $command->getAliases(), 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()), ); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; /** * @author Jean-François Simon */ class BufferedOutput extends Output { /** * @var string */ private $buffer = ''; /** * Empties buffer and returns its content. * * @return string */ public function fetch() { $content = $this->buffer; $this->buffer = ''; return $content; } /** * {@inheritdoc} */ protected function doWrite($message, $newline) { $this->buffer .= $message; if ($newline) { $this->buffer .= "\n"; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * OutputInterface is the interface implemented by all Output classes. * * @author Fabien Potencier * * @api */ interface OutputInterface { const VERBOSITY_QUIET = 0; const VERBOSITY_NORMAL = 1; const VERBOSITY_VERBOSE = 2; const VERBOSITY_VERY_VERBOSE = 3; const VERBOSITY_DEBUG = 4; const OUTPUT_NORMAL = 0; const OUTPUT_RAW = 1; const OUTPUT_PLAIN = 2; /** * Writes a message to the output. * * @param string|array $messages The message as an array of lines or a single string * @param bool $newline Whether to add a newline * @param int $type The type of output (one of the OUTPUT constants) * * @throws \InvalidArgumentException When unknown output type is given * * @api */ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL); /** * Writes a message to the output and adds a newline at the end. * * @param string|array $messages The message as an array of lines of a single string * @param int $type The type of output (one of the OUTPUT constants) * * @throws \InvalidArgumentException When unknown output type is given * * @api */ public function writeln($messages, $type = self::OUTPUT_NORMAL); /** * Sets the verbosity of the output. * * @param int $level The level of verbosity (one of the VERBOSITY constants) * * @api */ public function setVerbosity($level); /** * Gets the current verbosity of the output. * * @return int The current level of verbosity (one of the VERBOSITY constants) * * @api */ public function getVerbosity(); /** * Sets the decorated flag. * * @param bool $decorated Whether to decorate the messages * * @api */ public function setDecorated($decorated); /** * Gets the decorated flag. * * @return bool true if the output will decorate messages, false otherwise * * @api */ public function isDecorated(); /** * Sets output formatter. * * @param OutputFormatterInterface $formatter * * @api */ public function setFormatter(OutputFormatterInterface $formatter); /** * Returns current output formatter instance. * * @return OutputFormatterInterface * * @api */ public function getFormatter(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * NullOutput suppresses all output. * * $output = new NullOutput(); * * @author Fabien Potencier * @author Tobias Schultze * * @api */ class NullOutput implements OutputInterface { /** * {@inheritdoc} */ public function setFormatter(OutputFormatterInterface $formatter) { // do nothing } /** * {@inheritdoc} */ public function getFormatter() { // to comply with the interface we must return a OutputFormatterInterface return new OutputFormatter(); } /** * {@inheritdoc} */ public function setDecorated($decorated) { // do nothing } /** * {@inheritdoc} */ public function isDecorated() { return false; } /** * {@inheritdoc} */ public function setVerbosity($level) { // do nothing } /** * {@inheritdoc} */ public function getVerbosity() { return self::VERBOSITY_QUIET; } public function isQuiet() { return true; } public function isVerbose() { return false; } public function isVeryVerbose() { return false; } public function isDebug() { return false; } /** * {@inheritdoc} */ public function writeln($messages, $type = self::OUTPUT_NORMAL) { // do nothing } /** * {@inheritdoc} */ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) { // do nothing } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; /** * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. * This adds information about stderr output stream. * * @author Dariusz Górecki */ interface ConsoleOutputInterface extends OutputInterface { /** * Gets the OutputInterface for errors. * * @return OutputInterface */ public function getErrorOutput(); /** * Sets the OutputInterface used for errors. * * @param OutputInterface $error */ public function setErrorOutput(OutputInterface $error); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * StreamOutput writes the output to a given stream. * * Usage: * * $output = new StreamOutput(fopen('php://stdout', 'w')); * * As `StreamOutput` can use any stream, you can also use a file: * * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); * * @author Fabien Potencier * * @api */ class StreamOutput extends Output { private $stream; /** * Constructor. * * @param mixed $stream A stream resource * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) * * @throws \InvalidArgumentException When first argument is not a real stream * * @api */ public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) { if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) { throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); } $this->stream = $stream; if (null === $decorated) { $decorated = $this->hasColorSupport(); } parent::__construct($verbosity, $decorated, $formatter); } /** * Gets the stream attached to this StreamOutput instance. * * @return resource A stream resource */ public function getStream() { return $this->stream; } /** * {@inheritdoc} */ protected function doWrite($message, $newline) { if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) { // should never happen throw new \RuntimeException('Unable to write output.'); } fflush($this->stream); } /** * Returns true if the stream supports colorization. * * Colorization is disabled if not supported by the stream: * * - Windows without Ansicon and ConEmu * - non tty consoles * * @return bool true if the stream supports colorization, false otherwise */ protected function hasColorSupport() { if (DIRECTORY_SEPARATOR === '\\') { return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI'); } return function_exists('posix_isatty') && @posix_isatty($this->stream); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * ConsoleOutput is the default class for all CLI output. It uses STDOUT. * * This class is a convenient wrapper around `StreamOutput`. * * $output = new ConsoleOutput(); * * This is equivalent to: * * $output = new StreamOutput(fopen('php://stdout', 'w')); * * @author Fabien Potencier * * @api */ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface { /** * @var StreamOutput */ private $stderr; /** * Constructor. * * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) * * @api */ public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) { parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); } /** * {@inheritdoc} */ public function setDecorated($decorated) { parent::setDecorated($decorated); $this->stderr->setDecorated($decorated); } /** * {@inheritdoc} */ public function setFormatter(OutputFormatterInterface $formatter) { parent::setFormatter($formatter); $this->stderr->setFormatter($formatter); } /** * {@inheritdoc} */ public function setVerbosity($level) { parent::setVerbosity($level); $this->stderr->setVerbosity($level); } /** * {@inheritdoc} */ public function getErrorOutput() { return $this->stderr; } /** * {@inheritdoc} */ public function setErrorOutput(OutputInterface $error) { $this->stderr = $error; } /** * Returns true if current environment supports writing console output to * STDOUT. * * @return bool */ protected function hasStdoutSupport() { return false === $this->isRunningOS400(); } /** * Returns true if current environment supports writing console output to * STDERR. * * @return bool */ protected function hasStderrSupport() { return false === $this->isRunningOS400(); } /** * Checks if current executing environment is IBM iSeries (OS400), which * doesn't properly convert character-encodings between ASCII to EBCDIC. * * @return bool */ private function isRunningOS400() { return 'OS400' === php_uname('s'); } /** * @return resource */ private function openOutputStream() { $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output'; return @fopen($outputStream, 'w') ?: fopen('php://output', 'w'); } /** * @return resource */ private function openErrorStream() { $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output'; return fopen($errorStream, 'w'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Output; use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Formatter\OutputFormatter; /** * Base class for output classes. * * There are five levels of verbosity: * * * normal: no option passed (normal output) * * verbose: -v (more output) * * very verbose: -vv (highly extended output) * * debug: -vvv (all debug output) * * quiet: -q (no output) * * @author Fabien Potencier * * @api */ abstract class Output implements OutputInterface { private $verbosity; private $formatter; /** * Constructor. * * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool $decorated Whether to decorate messages * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) * * @api */ public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null) { $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; $this->formatter = $formatter ?: new OutputFormatter(); $this->formatter->setDecorated($decorated); } /** * {@inheritdoc} */ public function setFormatter(OutputFormatterInterface $formatter) { $this->formatter = $formatter; } /** * {@inheritdoc} */ public function getFormatter() { return $this->formatter; } /** * {@inheritdoc} */ public function setDecorated($decorated) { $this->formatter->setDecorated($decorated); } /** * {@inheritdoc} */ public function isDecorated() { return $this->formatter->isDecorated(); } /** * {@inheritdoc} */ public function setVerbosity($level) { $this->verbosity = (int) $level; } /** * {@inheritdoc} */ public function getVerbosity() { return $this->verbosity; } public function isQuiet() { return self::VERBOSITY_QUIET === $this->verbosity; } public function isVerbose() { return self::VERBOSITY_VERBOSE <= $this->verbosity; } public function isVeryVerbose() { return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; } public function isDebug() { return self::VERBOSITY_DEBUG <= $this->verbosity; } /** * {@inheritdoc} */ public function writeln($messages, $type = self::OUTPUT_NORMAL) { $this->write($messages, true, $type); } /** * {@inheritdoc} */ public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) { if (self::VERBOSITY_QUIET === $this->verbosity) { return; } $messages = (array) $messages; foreach ($messages as $message) { switch ($type) { case OutputInterface::OUTPUT_NORMAL: $message = $this->formatter->format($message); break; case OutputInterface::OUTPUT_RAW: break; case OutputInterface::OUTPUT_PLAIN: $message = strip_tags($this->formatter->format($message)); break; default: throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type)); } $this->doWrite($message, $newline); } } /** * Writes a message to the output. * * @param string $message A message to write to the output * @param bool $newline Whether to add a newline or not */ abstract protected function doWrite($message, $newline); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Logger; use Psr\Log\AbstractLogger; use Psr\Log\InvalidArgumentException; use Psr\Log\LogLevel; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\ConsoleOutputInterface; /** * PSR-3 compliant console logger * * @author Kévin Dunglas * @link http://www.php-fig.org/psr/psr-3/ */ class ConsoleLogger extends AbstractLogger { const INFO = 'info'; const ERROR = 'error'; /** * @var OutputInterface */ private $output; /** * @var array */ private $verbosityLevelMap = array( LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL, LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL, LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE, LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG, ); /** * @var array */ private $formatLevelMap = array( LogLevel::EMERGENCY => self::ERROR, LogLevel::ALERT => self::ERROR, LogLevel::CRITICAL => self::ERROR, LogLevel::ERROR => self::ERROR, LogLevel::WARNING => self::INFO, LogLevel::NOTICE => self::INFO, LogLevel::INFO => self::INFO, LogLevel::DEBUG => self::INFO, ); /** * @param OutputInterface $output * @param array $verbosityLevelMap * @param array $formatLevelMap */ public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array()) { $this->output = $output; $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap; $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap; } /** * {@inheritdoc} */ public function log($level, $message, array $context = array()) { if (!isset($this->verbosityLevelMap[$level])) { throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); } // Write to the error output if necessary and available if ($this->formatLevelMap[$level] === self::ERROR && $this->output instanceof ConsoleOutputInterface) { $output = $this->output->getErrorOutput(); } else { $output = $this->output; } if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) { $output->writeln(sprintf('<%1$s>[%2$s] %3$s', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context))); } } /** * Interpolates context values into the message placeholders * * @author PHP Framework Interoperability Group * * @param string $message * @param array $context * * @return string */ private function interpolate($message, array $context) { // build a replacement array with braces around the context keys $replace = array(); foreach ($context as $key => $val) { if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { $replace[sprintf('{%s}', $key)] = $val; } } // interpolate replacement values into the message and return return strtr($message, $replace); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * InputAwareInterface should be implemented by classes that depends on the * Console Input. * * @author Wouter J */ interface InputAwareInterface { /** * Sets the Console Input. * * @param InputInterface */ public function setInput(InputInterface $input); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * Input is the base class for all concrete Input classes. * * Three concrete classes are provided by default: * * * `ArgvInput`: The input comes from the CLI arguments (argv) * * `StringInput`: The input is provided as a string * * `ArrayInput`: The input is provided as an array * * @author Fabien Potencier */ abstract class Input implements InputInterface { /** * @var InputDefinition */ protected $definition; protected $options = array(); protected $arguments = array(); protected $interactive = true; /** * Constructor. * * @param InputDefinition $definition A InputDefinition instance */ public function __construct(InputDefinition $definition = null) { if (null === $definition) { $this->definition = new InputDefinition(); } else { $this->bind($definition); $this->validate(); } } /** * Binds the current Input instance with the given arguments and options. * * @param InputDefinition $definition A InputDefinition instance */ public function bind(InputDefinition $definition) { $this->arguments = array(); $this->options = array(); $this->definition = $definition; $this->parse(); } /** * Processes command line arguments. */ abstract protected function parse(); /** * Validates the input. * * @throws \RuntimeException When not enough arguments are given */ public function validate() { if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) { throw new \RuntimeException('Not enough arguments.'); } } /** * Checks if the input is interactive. * * @return bool Returns true if the input is interactive */ public function isInteractive() { return $this->interactive; } /** * Sets the input interactivity. * * @param bool $interactive If the input should be interactive */ public function setInteractive($interactive) { $this->interactive = (bool) $interactive; } /** * Returns the argument values. * * @return array An array of argument values */ public function getArguments() { return array_merge($this->definition->getArgumentDefaults(), $this->arguments); } /** * Returns the argument value for a given argument name. * * @param string $name The argument name * * @return mixed The argument value * * @throws \InvalidArgumentException When argument given doesn't exist */ public function getArgument($name) { if (!$this->definition->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); } /** * Sets an argument value by name. * * @param string $name The argument name * @param string $value The argument value * * @throws \InvalidArgumentException When argument given doesn't exist */ public function setArgument($name, $value) { if (!$this->definition->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } $this->arguments[$name] = $value; } /** * Returns true if an InputArgument object exists by name or position. * * @param string|int $name The InputArgument name or position * * @return bool true if the InputArgument object exists, false otherwise */ public function hasArgument($name) { return $this->definition->hasArgument($name); } /** * Returns the options values. * * @return array An array of option values */ public function getOptions() { return array_merge($this->definition->getOptionDefaults(), $this->options); } /** * Returns the option value for a given option name. * * @param string $name The option name * * @return mixed The option value * * @throws \InvalidArgumentException When option given doesn't exist */ public function getOption($name) { if (!$this->definition->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); } return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); } /** * Sets an option value by name. * * @param string $name The option name * @param string|bool $value The option value * * @throws \InvalidArgumentException When option given doesn't exist */ public function setOption($name, $value) { if (!$this->definition->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); } $this->options[$name] = $value; } /** * Returns true if an InputOption object exists by name. * * @param string $name The InputOption name * * @return bool true if the InputOption object exists, false otherwise */ public function hasOption($name) { return $this->definition->hasOption($name); } /** * Escapes a token through escapeshellarg if it contains unsafe chars. * * @param string $token * * @return string */ public function escapeToken($token) { return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Output\BufferedOutput; /** * A InputDefinition represents a set of valid command line arguments and options. * * Usage: * * $definition = new InputDefinition(array( * new InputArgument('name', InputArgument::REQUIRED), * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), * )); * * @author Fabien Potencier * * @api */ class InputDefinition { private $arguments; private $requiredCount; private $hasAnArrayArgument = false; private $hasOptional; private $options; private $shortcuts; /** * Constructor. * * @param array $definition An array of InputArgument and InputOption instance * * @api */ public function __construct(array $definition = array()) { $this->setDefinition($definition); } /** * Sets the definition of the input. * * @param array $definition The definition array * * @api */ public function setDefinition(array $definition) { $arguments = array(); $options = array(); foreach ($definition as $item) { if ($item instanceof InputOption) { $options[] = $item; } else { $arguments[] = $item; } } $this->setArguments($arguments); $this->setOptions($options); } /** * Sets the InputArgument objects. * * @param InputArgument[] $arguments An array of InputArgument objects * * @api */ public function setArguments($arguments = array()) { $this->arguments = array(); $this->requiredCount = 0; $this->hasOptional = false; $this->hasAnArrayArgument = false; $this->addArguments($arguments); } /** * Adds an array of InputArgument objects. * * @param InputArgument[] $arguments An array of InputArgument objects * * @api */ public function addArguments($arguments = array()) { if (null !== $arguments) { foreach ($arguments as $argument) { $this->addArgument($argument); } } } /** * Adds an InputArgument object. * * @param InputArgument $argument An InputArgument object * * @throws \LogicException When incorrect argument is given * * @api */ public function addArgument(InputArgument $argument) { if (isset($this->arguments[$argument->getName()])) { throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName())); } if ($this->hasAnArrayArgument) { throw new \LogicException('Cannot add an argument after an array argument.'); } if ($argument->isRequired() && $this->hasOptional) { throw new \LogicException('Cannot add a required argument after an optional one.'); } if ($argument->isArray()) { $this->hasAnArrayArgument = true; } if ($argument->isRequired()) { ++$this->requiredCount; } else { $this->hasOptional = true; } $this->arguments[$argument->getName()] = $argument; } /** * Returns an InputArgument by name or by position. * * @param string|int $name The InputArgument name or position * * @return InputArgument An InputArgument object * * @throws \InvalidArgumentException When argument given doesn't exist * * @api */ public function getArgument($name) { if (!$this->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; return $arguments[$name]; } /** * Returns true if an InputArgument object exists by name or position. * * @param string|int $name The InputArgument name or position * * @return bool true if the InputArgument object exists, false otherwise * * @api */ public function hasArgument($name) { $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; return isset($arguments[$name]); } /** * Gets the array of InputArgument objects. * * @return InputArgument[] An array of InputArgument objects * * @api */ public function getArguments() { return $this->arguments; } /** * Returns the number of InputArguments. * * @return int The number of InputArguments */ public function getArgumentCount() { return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments); } /** * Returns the number of required InputArguments. * * @return int The number of required InputArguments */ public function getArgumentRequiredCount() { return $this->requiredCount; } /** * Gets the default values. * * @return array An array of default values */ public function getArgumentDefaults() { $values = array(); foreach ($this->arguments as $argument) { $values[$argument->getName()] = $argument->getDefault(); } return $values; } /** * Sets the InputOption objects. * * @param InputOption[] $options An array of InputOption objects * * @api */ public function setOptions($options = array()) { $this->options = array(); $this->shortcuts = array(); $this->addOptions($options); } /** * Adds an array of InputOption objects. * * @param InputOption[] $options An array of InputOption objects * * @api */ public function addOptions($options = array()) { foreach ($options as $option) { $this->addOption($option); } } /** * Adds an InputOption object. * * @param InputOption $option An InputOption object * * @throws \LogicException When option given already exist * * @api */ public function addOption(InputOption $option) { if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName())); } if ($option->getShortcut()) { foreach (explode('|', $option->getShortcut()) as $shortcut) { if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut)); } } } $this->options[$option->getName()] = $option; if ($option->getShortcut()) { foreach (explode('|', $option->getShortcut()) as $shortcut) { $this->shortcuts[$shortcut] = $option->getName(); } } } /** * Returns an InputOption by name. * * @param string $name The InputOption name * * @return InputOption A InputOption object * * @throws \InvalidArgumentException When option given doesn't exist * * @api */ public function getOption($name) { if (!$this->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); } return $this->options[$name]; } /** * Returns true if an InputOption object exists by name. * * @param string $name The InputOption name * * @return bool true if the InputOption object exists, false otherwise * * @api */ public function hasOption($name) { return isset($this->options[$name]); } /** * Gets the array of InputOption objects. * * @return InputOption[] An array of InputOption objects * * @api */ public function getOptions() { return $this->options; } /** * Returns true if an InputOption object exists by shortcut. * * @param string $name The InputOption shortcut * * @return bool true if the InputOption object exists, false otherwise */ public function hasShortcut($name) { return isset($this->shortcuts[$name]); } /** * Gets an InputOption by shortcut. * * @param string $shortcut the Shortcut name * * @return InputOption An InputOption object */ public function getOptionForShortcut($shortcut) { return $this->getOption($this->shortcutToName($shortcut)); } /** * Gets an array of default values. * * @return array An array of all default values */ public function getOptionDefaults() { $values = array(); foreach ($this->options as $option) { $values[$option->getName()] = $option->getDefault(); } return $values; } /** * Returns the InputOption name given a shortcut. * * @param string $shortcut The shortcut * * @return string The InputOption name * * @throws \InvalidArgumentException When option given does not exist */ private function shortcutToName($shortcut) { if (!isset($this->shortcuts[$shortcut])) { throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); } return $this->shortcuts[$shortcut]; } /** * Gets the synopsis. * * @return string The synopsis */ public function getSynopsis() { $elements = array(); foreach ($this->getOptions() as $option) { $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName()); } foreach ($this->getArguments() as $argument) { $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : '')); if ($argument->isArray()) { $elements[] = sprintf('... [%sN]', $argument->getName()); } } return implode(' ', $elements); } /** * Returns a textual representation of the InputDefinition. * * @return string A string representing the InputDefinition * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asText() { $descriptor = new TextDescriptor(); $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); $descriptor->describe($output, $this, array('raw_output' => true)); return $output->fetch(); } /** * Returns an XML representation of the InputDefinition. * * @param bool $asDom Whether to return a DOM or an XML string * * @return string|\DOMDocument An XML string representing the InputDefinition * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asXml($asDom = false) { $descriptor = new XmlDescriptor(); if ($asDom) { return $descriptor->getInputDefinitionDocument($this); } $output = new BufferedOutput(); $descriptor->describe($output, $this); return $output->fetch(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * ArrayInput represents an input provided as an array. * * Usage: * * $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar')); * * @author Fabien Potencier * * @api */ class ArrayInput extends Input { private $parameters; /** * Constructor. * * @param array $parameters An array of parameters * @param InputDefinition $definition A InputDefinition instance * * @api */ public function __construct(array $parameters, InputDefinition $definition = null) { $this->parameters = $parameters; parent::__construct($definition); } /** * Returns the first argument from the raw parameters (not parsed). * * @return string The value of the first argument or null otherwise */ public function getFirstArgument() { foreach ($this->parameters as $key => $value) { if ($key && '-' === $key[0]) { continue; } return $value; } } /** * Returns true if the raw parameters (not parsed) contain a value. * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The values to look for in the raw parameters (can be an array) * * @return bool true if the value is contained in the raw parameters */ public function hasParameterOption($values) { $values = (array) $values; foreach ($this->parameters as $k => $v) { if (!is_int($k)) { $v = $k; } if (in_array($v, $values)) { return true; } } return false; } /** * Returns the value of a raw option (not parsed). * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found * * @return mixed The option value */ public function getParameterOption($values, $default = false) { $values = (array) $values; foreach ($this->parameters as $k => $v) { if (is_int($k)) { if (in_array($v, $values)) { return true; } } elseif (in_array($k, $values)) { return $v; } } return $default; } /** * Returns a stringified representation of the args passed to the command. * * @return string */ public function __toString() { $params = array(); foreach ($this->parameters as $param => $val) { if ($param && '-' === $param[0]) { $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); } else { $params[] = $this->escapeToken($val); } } return implode(' ', $params); } /** * Processes command line arguments. */ protected function parse() { foreach ($this->parameters as $key => $value) { if (0 === strpos($key, '--')) { $this->addLongOption(substr($key, 2), $value); } elseif ('-' === $key[0]) { $this->addShortOption(substr($key, 1), $value); } else { $this->addArgument($key, $value); } } } /** * Adds a short option value. * * @param string $shortcut The short option key * @param mixed $value The value for the option * * @throws \InvalidArgumentException When option given doesn't exist */ private function addShortOption($shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); } /** * Adds a long option value. * * @param string $name The long option key * @param mixed $value The value for the option * * @throws \InvalidArgumentException When option given doesn't exist * @throws \InvalidArgumentException When a required value is missing */ private function addLongOption($name, $value) { if (!$this->definition->hasOption($name)) { throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); } $option = $this->definition->getOption($name); if (null === $value) { if ($option->isValueRequired()) { throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name)); } $value = $option->isValueOptional() ? $option->getDefault() : true; } $this->options[$name] = $value; } /** * Adds an argument value. * * @param string $name The argument name * @param mixed $value The value for the argument * * @throws \InvalidArgumentException When argument given doesn't exist */ private function addArgument($name, $value) { if (!$this->definition->hasArgument($name)) { throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); } $this->arguments[$name] = $value; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * Represents a command line argument. * * @author Fabien Potencier * * @api */ class InputArgument { const REQUIRED = 1; const OPTIONAL = 2; const IS_ARRAY = 4; private $name; private $mode; private $default; private $description; /** * Constructor. * * @param string $name The argument name * @param int $mode The argument mode: self::REQUIRED or self::OPTIONAL * @param string $description A description text * @param mixed $default The default value (for self::OPTIONAL mode only) * * @throws \InvalidArgumentException When argument mode is not valid * * @api */ public function __construct($name, $mode = null, $description = '', $default = null) { if (null === $mode) { $mode = self::OPTIONAL; } elseif (!is_int($mode) || $mode > 7 || $mode < 1) { throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); } $this->name = $name; $this->mode = $mode; $this->description = $description; $this->setDefault($default); } /** * Returns the argument name. * * @return string The argument name */ public function getName() { return $this->name; } /** * Returns true if the argument is required. * * @return bool true if parameter mode is self::REQUIRED, false otherwise */ public function isRequired() { return self::REQUIRED === (self::REQUIRED & $this->mode); } /** * Returns true if the argument can take multiple values. * * @return bool true if mode is self::IS_ARRAY, false otherwise */ public function isArray() { return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); } /** * Sets the default value. * * @param mixed $default The default value * * @throws \LogicException When incorrect default value is given */ public function setDefault($default = null) { if (self::REQUIRED === $this->mode && null !== $default) { throw new \LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.'); } if ($this->isArray()) { if (null === $default) { $default = array(); } elseif (!is_array($default)) { throw new \LogicException('A default value for an array argument must be an array.'); } } $this->default = $default; } /** * Returns the default value. * * @return mixed The default value */ public function getDefault() { return $this->default; } /** * Returns the description text. * * @return string The description text */ public function getDescription() { return $this->description; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * InputInterface is the interface implemented by all input classes. * * @author Fabien Potencier */ interface InputInterface { /** * Returns the first argument from the raw parameters (not parsed). * * @return string The value of the first argument or null otherwise */ public function getFirstArgument(); /** * Returns true if the raw parameters (not parsed) contain a value. * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The values to look for in the raw parameters (can be an array) * * @return bool true if the value is contained in the raw parameters */ public function hasParameterOption($values); /** * Returns the value of a raw option (not parsed). * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found * * @return mixed The option value */ public function getParameterOption($values, $default = false); /** * Binds the current Input instance with the given arguments and options. * * @param InputDefinition $definition A InputDefinition instance */ public function bind(InputDefinition $definition); /** * Validates if arguments given are correct. * * Throws an exception when not enough arguments are given. * * @throws \RuntimeException */ public function validate(); /** * Returns all the given arguments merged with the default values. * * @return array */ public function getArguments(); /** * Gets argument by name. * * @param string $name The name of the argument * * @return mixed */ public function getArgument($name); /** * Sets an argument value by name. * * @param string $name The argument name * @param string $value The argument value * * @throws \InvalidArgumentException When argument given doesn't exist */ public function setArgument($name, $value); /** * Returns true if an InputArgument object exists by name or position. * * @param string|int $name The InputArgument name or position * * @return bool true if the InputArgument object exists, false otherwise */ public function hasArgument($name); /** * Returns all the given options merged with the default values. * * @return array */ public function getOptions(); /** * Gets an option by name. * * @param string $name The name of the option * * @return mixed */ public function getOption($name); /** * Sets an option value by name. * * @param string $name The option name * @param string|bool $value The option value * * @throws \InvalidArgumentException When option given doesn't exist */ public function setOption($name, $value); /** * Returns true if an InputOption object exists by name. * * @param string $name The InputOption name * * @return bool true if the InputOption object exists, false otherwise */ public function hasOption($name); /** * Is this input means interactive? * * @return bool */ public function isInteractive(); /** * Sets the input interactivity. * * @param bool $interactive If the input should be interactive */ public function setInteractive($interactive); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * ArgvInput represents an input coming from the CLI arguments. * * Usage: * * $input = new ArgvInput(); * * By default, the `$_SERVER['argv']` array is used for the input values. * * This can be overridden by explicitly passing the input values in the constructor: * * $input = new ArgvInput($_SERVER['argv']); * * If you pass it yourself, don't forget that the first element of the array * is the name of the running application. * * When passing an argument to the constructor, be sure that it respects * the same rules as the argv one. It's almost always better to use the * `StringInput` when you want to provide your own input. * * @author Fabien Potencier * * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 * * @api */ class ArgvInput extends Input { private $tokens; private $parsed; /** * Constructor. * * @param array $argv An array of parameters from the CLI (in the argv format) * @param InputDefinition $definition A InputDefinition instance * * @api */ public function __construct(array $argv = null, InputDefinition $definition = null) { if (null === $argv) { $argv = $_SERVER['argv']; } // strip the application name array_shift($argv); $this->tokens = $argv; parent::__construct($definition); } protected function setTokens(array $tokens) { $this->tokens = $tokens; } /** * Processes command line arguments. */ protected function parse() { $parseOptions = true; $this->parsed = $this->tokens; while (null !== $token = array_shift($this->parsed)) { if ($parseOptions && '' == $token) { $this->parseArgument($token); } elseif ($parseOptions && '--' == $token) { $parseOptions = false; } elseif ($parseOptions && 0 === strpos($token, '--')) { $this->parseLongOption($token); } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { $this->parseShortOption($token); } else { $this->parseArgument($token); } } } /** * Parses a short option. * * @param string $token The current token. */ private function parseShortOption($token) { $name = substr($token, 1); if (strlen($name) > 1) { if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { // an option with a value (with no space) $this->addShortOption($name[0], substr($name, 1)); } else { $this->parseShortOptionSet($name); } } else { $this->addShortOption($name, null); } } /** * Parses a short option set. * * @param string $name The current token * * @throws \RuntimeException When option given doesn't exist */ private function parseShortOptionSet($name) { $len = strlen($name); for ($i = 0; $i < $len; ++$i) { if (!$this->definition->hasShortcut($name[$i])) { throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i])); } $option = $this->definition->getOptionForShortcut($name[$i]); if ($option->acceptValue()) { $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); break; } else { $this->addLongOption($option->getName(), null); } } } /** * Parses a long option. * * @param string $token The current token */ private function parseLongOption($token) { $name = substr($token, 2); if (false !== $pos = strpos($name, '=')) { $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); } else { $this->addLongOption($name, null); } } /** * Parses an argument. * * @param string $token The current token * * @throws \RuntimeException When too many arguments are given */ private function parseArgument($token) { $c = count($this->arguments); // if input is expecting another argument, add it if ($this->definition->hasArgument($c)) { $arg = $this->definition->getArgument($c); $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token; // if last argument isArray(), append token to last argument } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { $arg = $this->definition->getArgument($c - 1); $this->arguments[$arg->getName()][] = $token; // unexpected argument } else { throw new \RuntimeException('Too many arguments.'); } } /** * Adds a short option value. * * @param string $shortcut The short option key * @param mixed $value The value for the option * * @throws \RuntimeException When option given doesn't exist */ private function addShortOption($shortcut, $value) { if (!$this->definition->hasShortcut($shortcut)) { throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); } $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); } /** * Adds a long option value. * * @param string $name The long option key * @param mixed $value The value for the option * * @throws \RuntimeException When option given doesn't exist */ private function addLongOption($name, $value) { if (!$this->definition->hasOption($name)) { throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name)); } $option = $this->definition->getOption($name); // Convert false values (from a previous call to substr()) to null if (false === $value) { $value = null; } if (null !== $value && !$option->acceptValue()) { throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); } if (null === $value && $option->acceptValue() && count($this->parsed)) { // if option accepts an optional or mandatory argument // let's see if there is one provided $next = array_shift($this->parsed); if (isset($next[0]) && '-' !== $next[0]) { $value = $next; } elseif (empty($next)) { $value = ''; } else { array_unshift($this->parsed, $next); } } if (null === $value) { if ($option->isValueRequired()) { throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); } if (!$option->isArray()) { $value = $option->isValueOptional() ? $option->getDefault() : true; } } if ($option->isArray()) { $this->options[$name][] = $value; } else { $this->options[$name] = $value; } } /** * Returns the first argument from the raw parameters (not parsed). * * @return string The value of the first argument or null otherwise */ public function getFirstArgument() { foreach ($this->tokens as $token) { if ($token && '-' === $token[0]) { continue; } return $token; } } /** * Returns true if the raw parameters (not parsed) contain a value. * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * * @return bool true if the value is contained in the raw parameters */ public function hasParameterOption($values) { $values = (array) $values; foreach ($this->tokens as $token) { foreach ($values as $value) { if ($token === $value || 0 === strpos($token, $value.'=')) { return true; } } } return false; } /** * Returns the value of a raw option (not parsed). * * This method is to be used to introspect the input parameters * before they have been validated. It must be used carefully. * * @param string|array $values The value(s) to look for in the raw parameters (can be an array) * @param mixed $default The default value to return if no result is found * * @return mixed The option value */ public function getParameterOption($values, $default = false) { $values = (array) $values; $tokens = $this->tokens; while (0 < count($tokens)) { $token = array_shift($tokens); foreach ($values as $value) { if ($token === $value || 0 === strpos($token, $value.'=')) { if (false !== $pos = strpos($token, '=')) { return substr($token, $pos + 1); } return array_shift($tokens); } } } return $default; } /** * Returns a stringified representation of the args passed to the command. * * @return string */ public function __toString() { $self = $this; $tokens = array_map(function ($token) use ($self) { if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { return $match[1].$self->escapeToken($match[2]); } if ($token && $token[0] !== '-') { return $self->escapeToken($token); } return $token; }, $this->tokens); return implode(' ', $tokens); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * Represents a command line option. * * @author Fabien Potencier * * @api */ class InputOption { const VALUE_NONE = 1; const VALUE_REQUIRED = 2; const VALUE_OPTIONAL = 4; const VALUE_IS_ARRAY = 8; private $name; private $shortcut; private $mode; private $default; private $description; /** * Constructor. * * @param string $name The option name * @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts * @param int $mode The option mode: One of the VALUE_* constants * @param string $description A description text * @param mixed $default The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE) * * @throws \InvalidArgumentException If option mode is invalid or incompatible * * @api */ public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null) { if (0 === strpos($name, '--')) { $name = substr($name, 2); } if (empty($name)) { throw new \InvalidArgumentException('An option name cannot be empty.'); } if (empty($shortcut)) { $shortcut = null; } if (null !== $shortcut) { if (is_array($shortcut)) { $shortcut = implode('|', $shortcut); } $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); $shortcuts = array_filter($shortcuts); $shortcut = implode('|', $shortcuts); if (empty($shortcut)) { throw new \InvalidArgumentException('An option shortcut cannot be empty.'); } } if (null === $mode) { $mode = self::VALUE_NONE; } elseif (!is_int($mode) || $mode > 15 || $mode < 1) { throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); } $this->name = $name; $this->shortcut = $shortcut; $this->mode = $mode; $this->description = $description; if ($this->isArray() && !$this->acceptValue()) { throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); } $this->setDefault($default); } /** * Returns the option shortcut. * * @return string The shortcut */ public function getShortcut() { return $this->shortcut; } /** * Returns the option name. * * @return string The name */ public function getName() { return $this->name; } /** * Returns true if the option accepts a value. * * @return bool true if value mode is not self::VALUE_NONE, false otherwise */ public function acceptValue() { return $this->isValueRequired() || $this->isValueOptional(); } /** * Returns true if the option requires a value. * * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise */ public function isValueRequired() { return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); } /** * Returns true if the option takes an optional value. * * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise */ public function isValueOptional() { return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); } /** * Returns true if the option can take multiple values. * * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise */ public function isArray() { return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); } /** * Sets the default value. * * @param mixed $default The default value * * @throws \LogicException When incorrect default value is given */ public function setDefault($default = null) { if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { throw new \LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); } if ($this->isArray()) { if (null === $default) { $default = array(); } elseif (!is_array($default)) { throw new \LogicException('A default value for an array option must be an array.'); } } $this->default = $this->acceptValue() ? $default : false; } /** * Returns the default value. * * @return mixed The default value */ public function getDefault() { return $this->default; } /** * Returns the description text. * * @return string The description text */ public function getDescription() { return $this->description; } /** * Checks whether the given option equals this one. * * @param InputOption $option option to compare * * @return bool */ public function equals(InputOption $option) { return $option->getName() === $this->getName() && $option->getShortcut() === $this->getShortcut() && $option->getDefault() === $this->getDefault() && $option->isArray() === $this->isArray() && $option->isValueRequired() === $this->isValueRequired() && $option->isValueOptional() === $this->isValueOptional() ; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Input; /** * StringInput represents an input provided as a string. * * Usage: * * $input = new StringInput('foo --bar="foobar"'); * * @author Fabien Potencier * * @api */ class StringInput extends ArgvInput { const REGEX_STRING = '([^\s]+?)(?:\s|(?setTokens($this->tokenize($input)); if (null !== $definition) { $this->bind($definition); } } /** * Tokenizes a string. * * @param string $input The input to tokenize * * @return array An array of tokens * * @throws \InvalidArgumentException When unable to parse input (should never happen) */ private function tokenize($input) { $tokens = array(); $length = strlen($input); $cursor = 0; while ($cursor < $length) { if (preg_match('/\s+/A', $input, $match, null, $cursor)) { } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2))); } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) { $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2)); } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) { $tokens[] = stripcslashes($match[1]); } else { // should never happen throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); } $cursor += strlen($match[0]); } return $tokens; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Question; /** * Represents a choice question. * * @author Fabien Potencier */ class ChoiceQuestion extends Question { private $choices; private $multiselect = false; private $prompt = ' > '; private $errorMessage = 'Value "%s" is invalid'; /** * Constructor. * * @param string $question The question to ask to the user * @param array $choices The list of available choices * @param mixed $default The default answer to return */ public function __construct($question, array $choices, $default = null) { parent::__construct($question, $default); $this->choices = $choices; $this->setValidator($this->getDefaultValidator()); $this->setAutocompleterValues(array_keys($choices)); } /** * Returns available choices. * * @return array */ public function getChoices() { return $this->choices; } /** * Sets multiselect option. * * When multiselect is set to true, multiple choices can be answered. * * @param bool $multiselect * * @return ChoiceQuestion The current instance */ public function setMultiselect($multiselect) { $this->multiselect = $multiselect; $this->setValidator($this->getDefaultValidator()); return $this; } /** * Gets the prompt for choices. * * @return string */ public function getPrompt() { return $this->prompt; } /** * Sets the prompt for choices. * * @param string $prompt * * @return ChoiceQuestion The current instance */ public function setPrompt($prompt) { $this->prompt = $prompt; return $this; } /** * Sets the error message for invalid values. * * The error message has a string placeholder (%s) for the invalid value. * * @param string $errorMessage * * @return ChoiceQuestion The current instance */ public function setErrorMessage($errorMessage) { $this->errorMessage = $errorMessage; $this->setValidator($this->getDefaultValidator()); return $this; } /** * Returns the default answer validator. * * @return callable */ private function getDefaultValidator() { $choices = $this->choices; $errorMessage = $this->errorMessage; $multiselect = $this->multiselect; return function ($selected) use ($choices, $errorMessage, $multiselect) { // Collapse all spaces. $selectedChoices = str_replace(' ', '', $selected); if ($multiselect) { // Check for a separated comma values if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) { throw new \InvalidArgumentException(sprintf($errorMessage, $selected)); } $selectedChoices = explode(',', $selectedChoices); } else { $selectedChoices = array($selected); } $multiselectChoices = array(); foreach ($selectedChoices as $value) { if (empty($choices[$value])) { throw new \InvalidArgumentException(sprintf($errorMessage, $value)); } $multiselectChoices[] = $choices[$value]; } if ($multiselect) { return $multiselectChoices; } return $choices[$selected]; }; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Question; /** * Represents a yes/no question. * * @author Fabien Potencier */ class ConfirmationQuestion extends Question { /** * Constructor. * * @param string $question The question to ask to the user * @param bool $default The default answer to return, true or false */ public function __construct($question, $default = true) { parent::__construct($question, (bool) $default); $this->setNormalizer($this->getDefaultNormalizer()); } /** * Returns the default answer normalizer. * * @return callable */ private function getDefaultNormalizer() { $default = $this->getDefault(); return function ($answer) use ($default) { if (is_bool($answer)) { return $answer; } if (false === $default) { return $answer && 'y' === strtolower($answer[0]); } return !$answer || 'y' === strtolower($answer[0]); }; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Question; /** * Represents a Question. * * @author Fabien Potencier */ class Question { private $question; private $attempts; private $hidden = false; private $hiddenFallback = true; private $autocompleterValues; private $validator; private $default; private $normalizer; /** * Constructor. * * @param string $question The question to ask to the user * @param mixed $default The default answer to return if the user enters nothing */ public function __construct($question, $default = null) { $this->question = $question; $this->default = $default; } /** * Returns the question. * * @return string */ public function getQuestion() { return $this->question; } /** * Returns the default answer. * * @return mixed */ public function getDefault() { return $this->default; } /** * Returns whether the user response must be hidden. * * @return bool */ public function isHidden() { return $this->hidden; } /** * Sets whether the user response must be hidden or not. * * @param bool $hidden * * @return Question The current instance * * @throws \LogicException In case the autocompleter is also used */ public function setHidden($hidden) { if ($this->autocompleterValues) { throw new \LogicException('A hidden question cannot use the autocompleter.'); } $this->hidden = (bool) $hidden; return $this; } /** * In case the response can not be hidden, whether to fallback on non-hidden question or not. * * @return bool */ public function isHiddenFallback() { return $this->hiddenFallback; } /** * Sets whether to fallback on non-hidden question if the response can not be hidden. * * @param bool $fallback * * @return Question The current instance */ public function setHiddenFallback($fallback) { $this->hiddenFallback = (bool) $fallback; return $this; } /** * Gets values for the autocompleter. * * @return null|array|\Traversable */ public function getAutocompleterValues() { return $this->autocompleterValues; } /** * Sets values for the autocompleter. * * @param null|array|\Traversable $values * * @return Question The current instance * * @throws \InvalidArgumentException * @throws \LogicException */ public function setAutocompleterValues($values) { if (null !== $values && !is_array($values)) { if (!$values instanceof \Traversable || $values instanceof \Countable) { throw new \InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.'); } } if ($this->hidden) { throw new \LogicException('A hidden question cannot use the autocompleter.'); } $this->autocompleterValues = $values; return $this; } /** * Sets a validator for the question. * * @param null|callable $validator * * @return Question The current instance */ public function setValidator($validator) { $this->validator = $validator; return $this; } /** * Gets the validator for the question. * * @return null|callable */ public function getValidator() { return $this->validator; } /** * Sets the maximum number of attempts. * * Null means an unlimited number of attempts. * * @param null|int $attempts * * @return Question The current instance * * @throws \InvalidArgumentException In case the number of attempts is invalid. */ public function setMaxAttempts($attempts) { if (null !== $attempts && $attempts < 1) { throw new \InvalidArgumentException('Maximum number of attempts must be a positive value.'); } $this->attempts = $attempts; return $this; } /** * Gets the maximum number of attempts. * * Null means an unlimited number of attempts. * * @return null|int */ public function getMaxAttempts() { return $this->attempts; } /** * Sets a normalizer for the response. * * The normalizer can be a callable (a string), a closure or a class implementing __invoke. * * @param string|\Closure $normalizer * * @return Question The current instance */ public function setNormalizer($normalizer) { $this->normalizer = $normalizer; return $this; } /** * Gets the normalizer for the response. * * The normalizer can ba a callable (a string), a closure or a class implementing __invoke. * * @return string|\Closure */ public function getNormalizer() { return $this->normalizer; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Allows to handle exception thrown in a command. * * @author Fabien Potencier */ class ConsoleExceptionEvent extends ConsoleEvent { private $exception; private $exitCode; public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode) { parent::__construct($command, $input, $output); $this->setException($exception); $this->exitCode = (int) $exitCode; } /** * Returns the thrown exception. * * @return \Exception The thrown exception */ public function getException() { return $this->exception; } /** * Replaces the thrown exception. * * This exception will be thrown if no response is set in the event. * * @param \Exception $exception The thrown exception */ public function setException(\Exception $exception) { $this->exception = $exception; } /** * Gets the exit code. * * @return int The command exit code */ public function getExitCode() { return $this->exitCode; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; /** * Allows to do things before the command is executed, like skipping the command or changing the input. * * @author Fabien Potencier */ class ConsoleCommandEvent extends ConsoleEvent { /** * The return code for skipped commands, this will also be passed into the terminate event */ const RETURN_CODE_DISABLED = 113; /** * Indicates if the command should be run or skipped * * @var bool */ private $commandShouldRun = true; /** * Disables the command, so it won't be run * * @return bool */ public function disableCommand() { return $this->commandShouldRun = false; } /** * Enables the command * * @return bool */ public function enableCommand() { return $this->commandShouldRun = true; } /** * Returns true if the command is runnable, false otherwise * * @return bool */ public function commandShouldRun() { return $this->commandShouldRun; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\EventDispatcher\Event; /** * Allows to inspect input and output of a command. * * @author Francesco Levorato */ class ConsoleEvent extends Event { protected $command; private $input; private $output; public function __construct(Command $command, InputInterface $input, OutputInterface $output) { $this->command = $command; $this->input = $input; $this->output = $output; } /** * Gets the command that is executed. * * @return Command A Command instance */ public function getCommand() { return $this->command; } /** * Gets the input instance. * * @return InputInterface An InputInterface instance */ public function getInput() { return $this->input; } /** * Gets the output instance. * * @return OutputInterface An OutputInterface instance */ public function getOutput() { return $this->output; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Allows to manipulate the exit code of a command after its execution. * * @author Francesco Levorato */ class ConsoleTerminateEvent extends ConsoleEvent { /** * The exit code of the command. * * @var int */ private $exitCode; public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode) { parent::__construct($command, $input, $output); $this->setExitCode($exitCode); } /** * Sets the exit code. * * @param int $exitCode The command exit code */ public function setExitCode($exitCode) { $this->exitCode = (int) $exitCode; } /** * Gets the exit code. * * @return int The command exit code */ public function getExitCode() { return $this->exitCode; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tester; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * Eases the testing of console commands. * * @author Fabien Potencier */ class CommandTester { private $command; private $input; private $output; private $statusCode; /** * Constructor. * * @param Command $command A Command instance to test. */ public function __construct(Command $command) { $this->command = $command; } /** * Executes the command. * * Available execution options: * * * interactive: Sets the input interactive flag * * decorated: Sets the output decorated flag * * verbosity: Sets the output verbosity flag * * @param array $input An array of command arguments and options * @param array $options An array of execution options * * @return int The command exit code */ public function execute(array $input, array $options = array()) { // set the command name automatically if the application requires // this argument and no command name was passed if (!isset($input['command']) && (null !== $application = $this->command->getApplication()) && $application->getDefinition()->hasArgument('command') ) { $input = array_merge(array('command' => $this->command->getName()), $input); } $this->input = new ArrayInput($input); if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); } $this->output = new StreamOutput(fopen('php://memory', 'w', false)); if (isset($options['decorated'])) { $this->output->setDecorated($options['decorated']); } if (isset($options['verbosity'])) { $this->output->setVerbosity($options['verbosity']); } return $this->statusCode = $this->command->run($this->input, $this->output); } /** * Gets the display returned by the last execution of the command. * * @param bool $normalize Whether to normalize end of lines to \n or not * * @return string The display */ public function getDisplay($normalize = false) { rewind($this->output->getStream()); $display = stream_get_contents($this->output->getStream()); if ($normalize) { $display = str_replace(PHP_EOL, "\n", $display); } return $display; } /** * Gets the input instance used by the last execution of the command. * * @return InputInterface The current input instance */ public function getInput() { return $this->input; } /** * Gets the output instance used by the last execution of the command. * * @return OutputInterface The current output instance */ public function getOutput() { return $this->output; } /** * Gets the status code returned by the last execution of the application. * * @return int The status code */ public function getStatusCode() { return $this->statusCode; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Tester; use Symfony\Component\Console\Application; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\StreamOutput; /** * Eases the testing of console applications. * * When testing an application, don't forget to disable the auto exit flag: * * $application = new Application(); * $application->setAutoExit(false); * * @author Fabien Potencier */ class ApplicationTester { private $application; private $input; private $output; private $statusCode; /** * Constructor. * * @param Application $application An Application instance to test. */ public function __construct(Application $application) { $this->application = $application; } /** * Executes the application. * * Available options: * * * interactive: Sets the input interactive flag * * decorated: Sets the output decorated flag * * verbosity: Sets the output verbosity flag * * @param array $input An array of arguments and options * @param array $options An array of options * * @return int The command exit code */ public function run(array $input, $options = array()) { $this->input = new ArrayInput($input); if (isset($options['interactive'])) { $this->input->setInteractive($options['interactive']); } $this->output = new StreamOutput(fopen('php://memory', 'w', false)); if (isset($options['decorated'])) { $this->output->setDecorated($options['decorated']); } if (isset($options['verbosity'])) { $this->output->setVerbosity($options['verbosity']); } return $this->statusCode = $this->application->run($this->input, $this->output); } /** * Gets the display returned by the last execution of the application. * * @param bool $normalize Whether to normalize end of lines to \n or not * * @return string The display */ public function getDisplay($normalize = false) { rewind($this->output->getStream()); $display = stream_get_contents($this->output->getStream()); if ($normalize) { $display = str_replace(PHP_EOL, "\n", $display); } return $display; } /** * Gets the input instance used by the last execution of the application. * * @return InputInterface The current input instance */ public function getInput() { return $this->input; } /** * Gets the output instance used by the last execution of the application. * * @return OutputInterface The current output instance */ public function getOutput() { return $this->output; } /** * Gets the status code returned by the last execution of the application. * * @return int The status code */ public function getStatusCode() { return $this->statusCode; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Application; use Symfony\Component\Console\Helper\HelperSet; /** * Base class for all commands. * * @author Fabien Potencier * * @api */ class Command { private $application; private $name; private $processTitle; private $aliases = array(); private $definition; private $help; private $description; private $ignoreValidationErrors = false; private $applicationDefinitionMerged = false; private $applicationDefinitionMergedWithArgs = false; private $code; private $synopsis; private $helperSet; /** * Constructor. * * @param string|null $name The name of the command; passing null means it must be set in configure() * * @throws \LogicException When the command name is empty * * @api */ public function __construct($name = null) { $this->definition = new InputDefinition(); if (null !== $name) { $this->setName($name); } $this->configure(); if (!$this->name) { throw new \LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this))); } } /** * Ignores validation errors. * * This is mainly useful for the help command. */ public function ignoreValidationErrors() { $this->ignoreValidationErrors = true; } /** * Sets the application instance for this command. * * @param Application $application An Application instance * * @api */ public function setApplication(Application $application = null) { $this->application = $application; if ($application) { $this->setHelperSet($application->getHelperSet()); } else { $this->helperSet = null; } } /** * Sets the helper set. * * @param HelperSet $helperSet A HelperSet instance */ public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; } /** * Gets the helper set. * * @return HelperSet A HelperSet instance */ public function getHelperSet() { return $this->helperSet; } /** * Gets the application instance for this command. * * @return Application An Application instance * * @api */ public function getApplication() { return $this->application; } /** * Checks whether the command is enabled or not in the current environment. * * Override this to check for x or y and return false if the command can not * run properly under the current conditions. * * @return bool */ public function isEnabled() { return true; } /** * Configures the current command. */ protected function configure() { } /** * Executes the current command. * * This method is not abstract because you can use this class * as a concrete class. In this case, instead of defining the * execute() method, you set the code to execute by passing * a Closure to the setCode() method. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * * @return null|int null or 0 if everything went fine, or an error code * * @throws \LogicException When this abstract method is not implemented * * @see setCode() */ protected function execute(InputInterface $input, OutputInterface $output) { throw new \LogicException('You must override the execute() method in the concrete command class.'); } /** * Interacts with the user. * * This method is executed before the InputDefinition is validated. * This means that this is the only place where the command can * interactively ask for values of missing required arguments. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ protected function interact(InputInterface $input, OutputInterface $output) { } /** * Initializes the command just after the input has been validated. * * This is mainly useful when a lot of commands extends one main command * where some things need to be initialized based on the input arguments and options. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ protected function initialize(InputInterface $input, OutputInterface $output) { } /** * Runs the command. * * The code to execute is either defined directly with the * setCode() method or by overriding the execute() method * in a sub-class. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * * @return int The command exit code * * @throws \Exception * * @see setCode() * @see execute() * * @api */ public function run(InputInterface $input, OutputInterface $output) { // force the creation of the synopsis before the merge with the app definition $this->getSynopsis(); // add the application arguments and options $this->mergeApplicationDefinition(); // bind the input against the command specific arguments/options try { $input->bind($this->definition); } catch (\Exception $e) { if (!$this->ignoreValidationErrors) { throw $e; } } $this->initialize($input, $output); if (null !== $this->processTitle) { if (function_exists('cli_set_process_title')) { cli_set_process_title($this->processTitle); } elseif (function_exists('setproctitle')) { setproctitle($this->processTitle); } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) { $output->writeln('Install the proctitle PECL to be able to change the process title.'); } } if ($input->isInteractive()) { $this->interact($input, $output); } $input->validate(); if ($this->code) { $statusCode = call_user_func($this->code, $input, $output); } else { $statusCode = $this->execute($input, $output); } return is_numeric($statusCode) ? (int) $statusCode : 0; } /** * Sets the code to execute when running this command. * * If this method is used, it overrides the code defined * in the execute() method. * * @param callable $code A callable(InputInterface $input, OutputInterface $output) * * @return Command The current instance * * @throws \InvalidArgumentException * * @see execute() * * @api */ public function setCode($code) { if (!is_callable($code)) { throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.'); } $this->code = $code; return $this; } /** * Merges the application definition with the command definition. * * This method is not part of public API and should not be used directly. * * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments */ public function mergeApplicationDefinition($mergeArgs = true) { if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) { return; } if ($mergeArgs) { $currentArguments = $this->definition->getArguments(); $this->definition->setArguments($this->application->getDefinition()->getArguments()); $this->definition->addArguments($currentArguments); } $this->definition->addOptions($this->application->getDefinition()->getOptions()); $this->applicationDefinitionMerged = true; if ($mergeArgs) { $this->applicationDefinitionMergedWithArgs = true; } } /** * Sets an array of argument and option instances. * * @param array|InputDefinition $definition An array of argument and option instances or a definition instance * * @return Command The current instance * * @api */ public function setDefinition($definition) { if ($definition instanceof InputDefinition) { $this->definition = $definition; } else { $this->definition->setDefinition($definition); } $this->applicationDefinitionMerged = false; return $this; } /** * Gets the InputDefinition attached to this Command. * * @return InputDefinition An InputDefinition instance * * @api */ public function getDefinition() { return $this->definition; } /** * Gets the InputDefinition to be used to create XML and Text representations of this Command. * * Can be overridden to provide the original command representation when it would otherwise * be changed by merging with the application InputDefinition. * * This method is not part of public API and should not be used directly. * * @return InputDefinition An InputDefinition instance */ public function getNativeDefinition() { return $this->getDefinition(); } /** * Adds an argument. * * @param string $name The argument name * @param int $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL * @param string $description A description text * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) * * @return Command The current instance * * @api */ public function addArgument($name, $mode = null, $description = '', $default = null) { $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); return $this; } /** * Adds an option. * * @param string $name The option name * @param string $shortcut The shortcut (can be null) * @param int $mode The option mode: One of the InputOption::VALUE_* constants * @param string $description A description text * @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE) * * @return Command The current instance * * @api */ public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null) { $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); return $this; } /** * Sets the name of the command. * * This method can set both the namespace and the name if * you separate them by a colon (:) * * $command->setName('foo:bar'); * * @param string $name The command name * * @return Command The current instance * * @throws \InvalidArgumentException When the name is invalid * * @api */ public function setName($name) { $this->validateName($name); $this->name = $name; return $this; } /** * Sets the process title of the command. * * This feature should be used only when creating a long process command, * like a daemon. * * PHP 5.5+ or the proctitle PECL library is required * * @param string $title The process title * * @return Command The current instance */ public function setProcessTitle($title) { $this->processTitle = $title; return $this; } /** * Returns the command name. * * @return string The command name * * @api */ public function getName() { return $this->name; } /** * Sets the description for the command. * * @param string $description The description for the command * * @return Command The current instance * * @api */ public function setDescription($description) { $this->description = $description; return $this; } /** * Returns the description for the command. * * @return string The description for the command * * @api */ public function getDescription() { return $this->description; } /** * Sets the help for the command. * * @param string $help The help for the command * * @return Command The current instance * * @api */ public function setHelp($help) { $this->help = $help; return $this; } /** * Returns the help for the command. * * @return string The help for the command * * @api */ public function getHelp() { return $this->help; } /** * Returns the processed help for the command replacing the %command.name% and * %command.full_name% patterns with the real values dynamically. * * @return string The processed help for the command */ public function getProcessedHelp() { $name = $this->name; $placeholders = array( '%command.name%', '%command.full_name%', ); $replacements = array( $name, $_SERVER['PHP_SELF'].' '.$name, ); return str_replace($placeholders, $replacements, $this->getHelp()); } /** * Sets the aliases for the command. * * @param string[] $aliases An array of aliases for the command * * @return Command The current instance * * @throws \InvalidArgumentException When an alias is invalid * * @api */ public function setAliases($aliases) { if (!is_array($aliases) && !$aliases instanceof \Traversable) { throw new \InvalidArgumentException('$aliases must be an array or an instance of \Traversable'); } foreach ($aliases as $alias) { $this->validateName($alias); } $this->aliases = $aliases; return $this; } /** * Returns the aliases for the command. * * @return array An array of aliases for the command * * @api */ public function getAliases() { return $this->aliases; } /** * Returns the synopsis for the command. * * @return string The synopsis */ public function getSynopsis() { if (null === $this->synopsis) { $this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis())); } return $this->synopsis; } /** * Gets a helper instance by name. * * @param string $name The helper name * * @return mixed The helper value * * @throws \InvalidArgumentException if the helper is not defined * * @api */ public function getHelper($name) { return $this->helperSet->get($name); } /** * Returns a text representation of the command. * * @return string A string representing the command * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asText() { $descriptor = new TextDescriptor(); $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); $descriptor->describe($output, $this, array('raw_output' => true)); return $output->fetch(); } /** * Returns an XML representation of the command. * * @param bool $asDom Whether to return a DOM or an XML string * * @return string|\DOMDocument An XML string representing the command * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asXml($asDom = false) { $descriptor = new XmlDescriptor(); if ($asDom) { return $descriptor->getCommandDocument($this); } $output = new BufferedOutput(); $descriptor->describe($output, $this); return $output->fetch(); } /** * Validates a command name. * * It must be non-empty and parts can optionally be separated by ":". * * @param string $name * * @throws \InvalidArgumentException When the name is invalid */ private function validateName($name) { if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Helper\DescriptorHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * HelpCommand displays the help for a given command. * * @author Fabien Potencier */ class HelpCommand extends Command { private $command; /** * {@inheritdoc} */ protected function configure() { $this->ignoreValidationErrors(); $this ->setName('help') ->setDefinition(array( new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats', 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), )) ->setDescription('Displays help for a command') ->setHelp(<<%command.name% command displays help for a given command: php %command.full_name% list You can also output the help in other formats by using the --format option: php %command.full_name% --format=xml list To display the list of available commands, please use the list command. EOF ) ; } /** * Sets the command. * * @param Command $command The command to set */ public function setCommand(Command $command) { $this->command = $command; } /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { if (null === $this->command) { $this->command = $this->getApplication()->find($input->getArgument('command_name')); } if ($input->getOption('xml')) { $input->setOption('format', 'xml'); } $helper = new DescriptorHelper(); $helper->describe($output, $this->command, array( 'format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), )); $this->command = null; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Command; use Symfony\Component\Console\Helper\DescriptorHelper; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputDefinition; /** * ListCommand displays the list of all available commands for the application. * * @author Fabien Potencier */ class ListCommand extends Command { /** * {@inheritdoc} */ protected function configure() { $this ->setName('list') ->setDefinition($this->createDefinition()) ->setDescription('Lists commands') ->setHelp(<<%command.name% command lists all commands: php %command.full_name% You can also display the commands for a specific namespace: php %command.full_name% test You can also output the information in other formats by using the --format option: php %command.full_name% --format=xml It's also possible to get raw list of commands (useful for embedding command runner): php %command.full_name% --raw EOF ) ; } /** * {@inheritdoc} */ public function getNativeDefinition() { return $this->createDefinition(); } /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { if ($input->getOption('xml')) { $input->setOption('format', 'xml'); } $helper = new DescriptorHelper(); $helper->describe($output, $this->getApplication(), array( 'format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'namespace' => $input->getArgument('namespace'), )); } /** * {@inheritdoc} */ private function createDefinition() { return new InputDefinition(array( new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats', 'txt'), )); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputAwareInterface; /** * An implementation of InputAwareInterface for Helpers. * * @author Wouter J */ abstract class InputAwareHelper extends Helper implements InputAwareInterface { protected $input; /** * {@inheritdoc} */ public function setInput(InputInterface $input) { $this->input = $input; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\NullOutput; /** * Provides helpers to display table output. * * @author Саша Стаменковић * @author Fabien Potencier * * @deprecated Deprecated since 2.5, to be removed in 3.0; use Table instead. */ class TableHelper extends Helper { const LAYOUT_DEFAULT = 0; const LAYOUT_BORDERLESS = 1; const LAYOUT_COMPACT = 2; /** * @var Table */ private $table; public function __construct() { $this->table = new Table(new NullOutput()); } /** * Sets table layout type. * * @param int $layout self::LAYOUT_* * * @return TableHelper * * @throws \InvalidArgumentException when the table layout is not known */ public function setLayout($layout) { switch ($layout) { case self::LAYOUT_BORDERLESS: $this->table->setStyle('borderless'); break; case self::LAYOUT_COMPACT: $this->table->setStyle('compact'); break; case self::LAYOUT_DEFAULT: $this->table->setStyle('default'); break; default: throw new \InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout)); }; return $this; } public function setHeaders(array $headers) { $this->table->setHeaders($headers); return $this; } public function setRows(array $rows) { $this->table->setRows($rows); return $this; } public function addRows(array $rows) { $this->table->addRows($rows); return $this; } public function addRow(array $row) { $this->table->addRow($row); return $this; } public function setRow($column, array $row) { $this->table->setRow($column, $row); return $this; } /** * Sets padding character, used for cell padding. * * @param string $paddingChar * * @return TableHelper */ public function setPaddingChar($paddingChar) { $this->table->getStyle()->setPaddingChar($paddingChar); return $this; } /** * Sets horizontal border character. * * @param string $horizontalBorderChar * * @return TableHelper */ public function setHorizontalBorderChar($horizontalBorderChar) { $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar); return $this; } /** * Sets vertical border character. * * @param string $verticalBorderChar * * @return TableHelper */ public function setVerticalBorderChar($verticalBorderChar) { $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar); return $this; } /** * Sets crossing character. * * @param string $crossingChar * * @return TableHelper */ public function setCrossingChar($crossingChar) { $this->table->getStyle()->setCrossingChar($crossingChar); return $this; } /** * Sets header cell format. * * @param string $cellHeaderFormat * * @return TableHelper */ public function setCellHeaderFormat($cellHeaderFormat) { $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat); return $this; } /** * Sets row cell format. * * @param string $cellRowFormat * * @return TableHelper */ public function setCellRowFormat($cellRowFormat) { $this->table->getStyle()->setCellHeaderFormat($cellRowFormat); return $this; } /** * Sets row cell content format. * * @param string $cellRowContentFormat * * @return TableHelper */ public function setCellRowContentFormat($cellRowContentFormat) { $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat); return $this; } /** * Sets table border format. * * @param string $borderFormat * * @return TableHelper */ public function setBorderFormat($borderFormat) { $this->table->getStyle()->setBorderFormat($borderFormat); return $this; } /** * Sets cell padding type. * * @param int $padType STR_PAD_* * * @return TableHelper */ public function setPadType($padType) { $this->table->getStyle()->setPadType($padType); return $this; } /** * Renders table to output. * * Example: * +---------------+-----------------------+------------------+ * | ISBN | Title | Author | * +---------------+-----------------------+------------------+ * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | * +---------------+-----------------------+------------------+ * * @param OutputInterface $output */ public function render(OutputInterface $output) { $p = new \ReflectionProperty($this->table, 'output'); $p->setAccessible(true); $p->setValue($this->table, $output); $this->table->render(); } /** * {@inheritdoc} */ public function getName() { return 'table'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; use Symfony\Component\Process\ProcessBuilder; /** * The ProcessHelper class provides helpers to run external processes. * * @author Fabien Potencier */ class ProcessHelper extends Helper { /** * Runs an external process. * * @param OutputInterface $output An OutputInterface instance * @param string|array|Process $cmd An instance of Process or an array of arguments to escape and run or a command to run * @param string|null $error An error message that must be displayed if something went wrong * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * @param int $verbosity The threshold for verbosity * * @return Process The process that ran */ public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE) { $formatter = $this->getHelperSet()->get('debug_formatter'); if (is_array($cmd)) { $process = ProcessBuilder::create($cmd)->getProcess(); } elseif ($cmd instanceof Process) { $process = $cmd; } else { $process = new Process($cmd); } if ($verbosity <= $output->getVerbosity()) { $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine()))); } if ($output->isDebug()) { $callback = $this->wrapCallback($output, $process, $callback); } $process->run($callback); if ($verbosity <= $output->getVerbosity()) { $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode()); $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful())); } if (!$process->isSuccessful() && null !== $error) { $output->writeln(sprintf('%s', $this->escapeString($error))); } return $process; } /** * Runs the process. * * This is identical to run() except that an exception is thrown if the process * exits with a non-zero exit code. * * @param OutputInterface $output An OutputInterface instance * @param string|Process $cmd An instance of Process or a command to run * @param string|null $error An error message that must be displayed if something went wrong * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return Process The process that ran * * @throws ProcessFailedException * * @see run() */ public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null) { $process = $this->run($output, $cmd, $error, $callback); if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } return $process; } /** * Wraps a Process callback to add debugging output. * * @param OutputInterface $output An OutputInterface interface * @param Process $process The Process * @param callable|null $callback A PHP callable * * @return callable */ public function wrapCallback(OutputInterface $output, Process $process, $callback = null) { $formatter = $this->getHelperSet()->get('debug_formatter'); $that = $this; return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) { $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type)); if (null !== $callback) { call_user_func($callback, $type, $buffer); } }; } /** * This method is public for PHP 5.3 compatibility, it should be private. * * @internal */ public function escapeString($str) { return str_replace('<', '\\<', $str); } /** * {@inheritdoc} */ public function getName() { return 'process'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Formatter\OutputFormatterStyle; /** * The Dialog class provides helpers to interact with the user. * * @author Fabien Potencier * * @deprecated Deprecated since version 2.5, to be removed in 3.0. * Use the question helper instead. */ class DialogHelper extends InputAwareHelper { private $inputStream; private static $shell; private static $stty; /** * Asks the user to select a value. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param array $choices List of choices to pick from * @param bool|string $default The default answer if the user enters nothing * @param bool|int $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param string $errorMessage Message which will be shown if invalid value from choice list would be picked * @param bool $multiselect Select more than one value separated by comma * * @return int|string|array The selected value or values (the key of the choices array) * * @throws \InvalidArgumentException */ public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false) { $width = max(array_map('strlen', array_keys($choices))); $messages = (array) $question; foreach ($choices as $key => $value) { $messages[] = sprintf(" [%-${width}s] %s", $key, $value); } $output->writeln($messages); $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) { // Collapse all spaces. $selectedChoices = str_replace(' ', '', $picked); if ($multiselect) { // Check for a separated comma values if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) { throw new \InvalidArgumentException(sprintf($errorMessage, $picked)); } $selectedChoices = explode(',', $selectedChoices); } else { $selectedChoices = array($picked); } $multiselectChoices = array(); foreach ($selectedChoices as $value) { if (empty($choices[$value])) { throw new \InvalidArgumentException(sprintf($errorMessage, $value)); } $multiselectChoices[] = $value; } if ($multiselect) { return $multiselectChoices; } return $picked; }, $attempts, $default); return $result; } /** * Asks a question to the user. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param string $default The default answer if none is given by the user * @param array $autocomplete List of values to autocomplete * * @return string The user answer * * @throws \RuntimeException If there is no data to read in the input stream */ public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null) { if ($this->input && !$this->input->isInteractive()) { return $default; } $output->write($question); $inputStream = $this->inputStream ?: STDIN; if (null === $autocomplete || !$this->hasSttyAvailable()) { $ret = fgets($inputStream, 4096); if (false === $ret) { throw new \RuntimeException('Aborted'); } $ret = trim($ret); } else { $ret = ''; $i = 0; $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); $sttyMode = shell_exec('stty -g'); // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) shell_exec('stty -icanon -echo'); // Add highlighted text style $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); // Read a keypress while (!feof($inputStream)) { $c = fread($inputStream, 1); // Backspace Character if ("\177" === $c) { if (0 === $numMatches && 0 !== $i) { --$i; // Move cursor backwards $output->write("\033[1D"); } if ($i === 0) { $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); } else { $numMatches = 0; } // Pop the last character off the end of our string $ret = substr($ret, 0, $i); } elseif ("\033" === $c) { // Did we read an escape sequence? $c .= fread($inputStream, 2); // A = Up Arrow. B = Down Arrow if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) { if ('A' === $c[2] && -1 === $ofs) { $ofs = 0; } if (0 === $numMatches) { continue; } $ofs += ('A' === $c[2]) ? -1 : 1; $ofs = ($numMatches + $ofs) % $numMatches; } } elseif (ord($c) < 32) { if ("\t" === $c || "\n" === $c) { if ($numMatches > 0 && -1 !== $ofs) { $ret = $matches[$ofs]; // Echo out remaining chars for current match $output->write(substr($ret, $i)); $i = strlen($ret); } if ("\n" === $c) { $output->write($c); break; } $numMatches = 0; } continue; } else { $output->write($c); $ret .= $c; ++$i; $numMatches = 0; $ofs = 0; foreach ($autocomplete as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) if (0 === strpos($value, $ret) && $i !== strlen($value)) { $matches[$numMatches++] = $value; } } } // Erase characters from cursor to end of line $output->write("\033[K"); if ($numMatches > 0 && -1 !== $ofs) { // Save cursor position $output->write("\0337"); // Write highlighted text $output->write(''.substr($matches[$ofs], $i).''); // Restore cursor position $output->write("\0338"); } } // Reset stty so it behaves normally again shell_exec(sprintf('stty %s', $sttyMode)); } return strlen($ret) > 0 ? $ret : $default; } /** * Asks a confirmation to the user. * * The question will be asked until the user answers by nothing, yes, or no. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param bool $default The default answer if the user enters nothing * * @return bool true if the user has confirmed, false otherwise */ public function askConfirmation(OutputInterface $output, $question, $default = true) { $answer = 'z'; while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) { $answer = $this->ask($output, $question); } if (false === $default) { return $answer && 'y' == strtolower($answer[0]); } return !$answer || 'y' == strtolower($answer[0]); } /** * Asks a question to the user, the response is hidden. * * @param OutputInterface $output An Output instance * @param string|array $question The question * @param bool $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not * * @return string The answer * * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden */ public function askHiddenResponse(OutputInterface $output, $question, $fallback = true) { if ('\\' === DIRECTORY_SEPARATOR) { $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; // handle code running from a phar if ('phar:' === substr(__FILE__, 0, 5)) { $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; copy($exe, $tmpExe); $exe = $tmpExe; } $output->write($question); $value = rtrim(shell_exec($exe)); $output->writeln(''); if (isset($tmpExe)) { unlink($tmpExe); } return $value; } if ($this->hasSttyAvailable()) { $output->write($question); $sttyMode = shell_exec('stty -g'); shell_exec('stty -echo'); $value = fgets($this->inputStream ?: STDIN, 4096); shell_exec(sprintf('stty %s', $sttyMode)); if (false === $value) { throw new \RuntimeException('Aborted'); } $value = trim($value); $output->writeln(''); return $value; } if (false !== $shell = $this->getShell()) { $output->write($question); $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); $value = rtrim(shell_exec($command)); $output->writeln(''); return $value; } if ($fallback) { return $this->ask($output, $question); } throw new \RuntimeException('Unable to hide the response'); } /** * Asks for a value and validates the response. * * The validator receives the data to validate. It must return the * validated data when the data is valid and throw an exception * otherwise. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param callable $validator A PHP callback * @param int|false $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param string $default The default answer if none is given by the user * @param array $autocomplete List of values to autocomplete * * @return mixed * * @throws \Exception When any of the validators return an error */ public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null) { $that = $this; $interviewer = function () use ($output, $question, $default, $autocomplete, $that) { return $that->ask($output, $question, $default, $autocomplete); }; return $this->validateAttempts($interviewer, $output, $validator, $attempts); } /** * Asks for a value, hide and validates the response. * * The validator receives the data to validate. It must return the * validated data when the data is valid and throw an exception * otherwise. * * @param OutputInterface $output An Output instance * @param string|array $question The question to ask * @param callable $validator A PHP callback * @param int|false $attempts Max number of times to ask before giving up (false by default, which means infinite) * @param bool $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not * * @return string The response * * @throws \Exception When any of the validators return an error * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden */ public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true) { $that = $this; $interviewer = function () use ($output, $question, $fallback, $that) { return $that->askHiddenResponse($output, $question, $fallback); }; return $this->validateAttempts($interviewer, $output, $validator, $attempts); } /** * Sets the input stream to read from when interacting with the user. * * This is mainly useful for testing purpose. * * @param resource $stream The input stream */ public function setInputStream($stream) { $this->inputStream = $stream; } /** * Returns the helper's input stream. * * @return string */ public function getInputStream() { return $this->inputStream; } /** * {@inheritdoc} */ public function getName() { return 'dialog'; } /** * Return a valid Unix shell. * * @return string|bool The valid shell name, false in case no valid shell is found */ private function getShell() { if (null !== self::$shell) { return self::$shell; } self::$shell = false; if (file_exists('/usr/bin/env')) { // handle other OSs with bash/zsh/ksh/csh if available to hide the answer $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) { if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { self::$shell = $sh; break; } } } return self::$shell; } private function hasSttyAvailable() { if (null !== self::$stty) { return self::$stty; } exec('stty 2>&1', $output, $exitcode); return self::$stty = $exitcode === 0; } /** * Validate an attempt. * * @param callable $interviewer A callable that will ask for a question and return the result * @param OutputInterface $output An Output instance * @param callable $validator A PHP callback * @param int|false $attempts Max number of times to ask before giving up ; false will ask infinitely * * @return string The validated response * * @throws \Exception In case the max number of attempts has been reached and no valid response has been given */ private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts) { $e = null; while (false === $attempts || $attempts--) { if (null !== $e) { $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error')); } try { return call_user_func($validator, $interviewer()); } catch (\Exception $e) { } } throw $e; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * Helps outputting debug information when running an external program from a command. * * An external program can be a Process, an HTTP request, or anything else. * * @author Fabien Potencier */ class DebugFormatterHelper extends Helper { private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default'); private $started = array(); private $count = -1; /** * Starts a debug formatting session * * @param string $id The id of the formatting session * @param string $message The message to display * @param string $prefix The prefix to use * * @return string */ public function start($id, $message, $prefix = 'RUN') { $this->started[$id] = array('border' => ++$this->count % count($this->colors)); return sprintf("%s %s %s\n", $this->getBorder($id), $prefix, $message); } /** * Adds progress to a formatting session * * @param string $id The id of the formatting session * @param string $buffer The message to display * @param bool $error Whether to consider the buffer as error * @param string $prefix The prefix for output * @param string $errorPrefix The prefix for error output * * @return string */ public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR') { $message = ''; if ($error) { if (isset($this->started[$id]['out'])) { $message .= "\n"; unset($this->started[$id]['out']); } if (!isset($this->started[$id]['err'])) { $message .= sprintf("%s %s ", $this->getBorder($id), $errorPrefix); $this->started[$id]['err'] = true; } $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $errorPrefix), $buffer); } else { if (isset($this->started[$id]['err'])) { $message .= "\n"; unset($this->started[$id]['err']); } if (!isset($this->started[$id]['out'])) { $message .= sprintf("%s %s ", $this->getBorder($id), $prefix); $this->started[$id]['out'] = true; } $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $prefix), $buffer); } return $message; } /** * Stops a formatting session * * @param string $id The id of the formatting session * @param string $message The message to display * @param bool $successful Whether to consider the result as success * @param string $prefix The prefix for the end output * * @return string */ public function stop($id, $message, $successful, $prefix = 'RES') { $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : ''; if ($successful) { return sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); } $message = sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); unset($this->started[$id]['out'], $this->started[$id]['err']); return $message; } /** * @param string $id The id of the formatting session * * @return string */ private function getBorder($id) { return sprintf(' ', $this->colors[$this->started[$id]['border']]); } /** * {@inheritdoc} */ public function getName() { return 'debug_formatter'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Output\OutputInterface; /** * The Progress class provides helpers to display progress output. * * @author Chris Jones * @author Fabien Potencier * * @deprecated Deprecated since 2.5, to be removed in 3.0; use ProgressBar instead. */ class ProgressHelper extends Helper { const FORMAT_QUIET = ' %percent%%'; const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%'; const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%'; const FORMAT_QUIET_NOMAX = ' %current%'; const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]'; const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%'; // options private $barWidth = 28; private $barChar = '='; private $emptyBarChar = '-'; private $progressChar = '>'; private $format = null; private $redrawFreq = 1; private $lastMessagesLength; private $barCharOriginal; /** * @var OutputInterface */ private $output; /** * Current step. * * @var int */ private $current; /** * Maximum number of steps. * * @var int */ private $max; /** * Start time of the progress bar. * * @var int */ private $startTime; /** * List of formatting variables. * * @var array */ private $defaultFormatVars = array( 'current', 'max', 'bar', 'percent', 'elapsed', ); /** * Available formatting variables. * * @var array */ private $formatVars; /** * Stored format part widths (used for padding). * * @var array */ private $widths = array( 'current' => 4, 'max' => 4, 'percent' => 3, 'elapsed' => 6, ); /** * Various time formats. * * @var array */ private $timeFormats = array( array(0, '???'), array(2, '1 sec'), array(59, 'secs', 1), array(60, '1 min'), array(3600, 'mins', 60), array(5400, '1 hr'), array(86400, 'hrs', 3600), array(129600, '1 day'), array(604800, 'days', 86400), ); /** * Sets the progress bar width. * * @param int $size The progress bar size */ public function setBarWidth($size) { $this->barWidth = (int) $size; } /** * Sets the bar character. * * @param string $char A character */ public function setBarCharacter($char) { $this->barChar = $char; } /** * Sets the empty bar character. * * @param string $char A character */ public function setEmptyBarCharacter($char) { $this->emptyBarChar = $char; } /** * Sets the progress bar character. * * @param string $char A character */ public function setProgressCharacter($char) { $this->progressChar = $char; } /** * Sets the progress bar format. * * @param string $format The format */ public function setFormat($format) { $this->format = $format; } /** * Sets the redraw frequency. * * @param int $freq The frequency in steps */ public function setRedrawFrequency($freq) { $this->redrawFreq = (int) $freq; } /** * Starts the progress output. * * @param OutputInterface $output An Output instance * @param int|null $max Maximum steps */ public function start(OutputInterface $output, $max = null) { $this->startTime = time(); $this->current = 0; $this->max = (int) $max; // Disabling output when it does not support ANSI codes as it would result in a broken display anyway. $this->output = $output->isDecorated() ? $output : new NullOutput(); $this->lastMessagesLength = 0; $this->barCharOriginal = ''; if (null === $this->format) { switch ($output->getVerbosity()) { case OutputInterface::VERBOSITY_QUIET: $this->format = self::FORMAT_QUIET_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_QUIET; } break; case OutputInterface::VERBOSITY_VERBOSE: case OutputInterface::VERBOSITY_VERY_VERBOSE: case OutputInterface::VERBOSITY_DEBUG: $this->format = self::FORMAT_VERBOSE_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_VERBOSE; } break; default: $this->format = self::FORMAT_NORMAL_NOMAX; if ($this->max > 0) { $this->format = self::FORMAT_NORMAL; } break; } } $this->initialize(); } /** * Advances the progress output X steps. * * @param int $step Number of steps to advance * @param bool $redraw Whether to redraw or not * * @throws \LogicException */ public function advance($step = 1, $redraw = false) { $this->setCurrent($this->current + $step, $redraw); } /** * Sets the current progress. * * @param int $current The current progress * @param bool $redraw Whether to redraw or not * * @throws \LogicException */ public function setCurrent($current, $redraw = false) { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling setCurrent().'); } $current = (int) $current; if ($current < $this->current) { throw new \LogicException('You can\'t regress the progress bar'); } if (0 === $this->current) { $redraw = true; } $prevPeriod = (int) ($this->current / $this->redrawFreq); $this->current = $current; $currPeriod = (int) ($this->current / $this->redrawFreq); if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) { $this->display(); } } /** * Outputs the current progress string. * * @param bool $finish Forces the end result * * @throws \LogicException */ public function display($finish = false) { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling display().'); } $message = $this->format; foreach ($this->generate($finish) as $name => $value) { $message = str_replace("%{$name}%", $value, $message); } $this->overwrite($this->output, $message); } /** * Removes the progress bar from the current line. * * This is useful if you wish to write some output * while a progress bar is running. * Call display() to show the progress bar again. */ public function clear() { $this->overwrite($this->output, ''); } /** * Finishes the progress output. */ public function finish() { if (null === $this->startTime) { throw new \LogicException('You must start the progress bar before calling finish().'); } if (null !== $this->startTime) { if (!$this->max) { $this->barChar = $this->barCharOriginal; $this->display(true); } $this->startTime = null; $this->output->writeln(''); $this->output = null; } } /** * Initializes the progress helper. */ private function initialize() { $this->formatVars = array(); foreach ($this->defaultFormatVars as $var) { if (false !== strpos($this->format, "%{$var}%")) { $this->formatVars[$var] = true; } } if ($this->max > 0) { $this->widths['max'] = $this->strlen($this->max); $this->widths['current'] = $this->widths['max']; } else { $this->barCharOriginal = $this->barChar; $this->barChar = $this->emptyBarChar; } } /** * Generates the array map of format variables to values. * * @param bool $finish Forces the end result * * @return array Array of format vars and values */ private function generate($finish = false) { $vars = array(); $percent = 0; if ($this->max > 0) { $percent = (float) $this->current / $this->max; } if (isset($this->formatVars['bar'])) { $completeBars = 0; if ($this->max > 0) { $completeBars = floor($percent * $this->barWidth); } else { if (!$finish) { $completeBars = floor($this->current % $this->barWidth); } else { $completeBars = $this->barWidth; } } $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar); $bar = str_repeat($this->barChar, $completeBars); if ($completeBars < $this->barWidth) { $bar .= $this->progressChar; $bar .= str_repeat($this->emptyBarChar, $emptyBars); } $vars['bar'] = $bar; } if (isset($this->formatVars['elapsed'])) { $elapsed = time() - $this->startTime; $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT); } if (isset($this->formatVars['current'])) { $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT); } if (isset($this->formatVars['max'])) { $vars['max'] = $this->max; } if (isset($this->formatVars['percent'])) { $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT); } return $vars; } /** * Converts seconds into human-readable format. * * @param int $secs Number of seconds * * @return string Time in readable format */ private function humaneTime($secs) { $text = ''; foreach ($this->timeFormats as $format) { if ($secs < $format[0]) { if (count($format) == 2) { $text = $format[1]; break; } else { $text = ceil($secs / $format[2]).' '.$format[1]; break; } } } return $text; } /** * Overwrites a previous message to the output. * * @param OutputInterface $output An Output instance * @param string $message The message */ private function overwrite(OutputInterface $output, $message) { $length = $this->strlen($message); // append whitespace to match the last line's length if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) { $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); } // carriage return $output->write("\x0D"); $output->write($message); $this->lastMessagesLength = $this->strlen($message); } /** * {@inheritdoc} */ public function getName() { return 'progress'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * Defines the styles for a Table. * * @author Fabien Potencier * @author Саша Стаменковић */ class TableStyle { private $paddingChar = ' '; private $horizontalBorderChar = '-'; private $verticalBorderChar = '|'; private $crossingChar = '+'; private $cellHeaderFormat = '%s'; private $cellRowFormat = '%s'; private $cellRowContentFormat = ' %s '; private $borderFormat = '%s'; private $padType = STR_PAD_RIGHT; /** * Sets padding character, used for cell padding. * * @param string $paddingChar * * @return TableStyle */ public function setPaddingChar($paddingChar) { if (!$paddingChar) { throw new \LogicException('The padding char must not be empty'); } $this->paddingChar = $paddingChar; return $this; } /** * Gets padding character, used for cell padding. * * @return string */ public function getPaddingChar() { return $this->paddingChar; } /** * Sets horizontal border character. * * @param string $horizontalBorderChar * * @return TableStyle */ public function setHorizontalBorderChar($horizontalBorderChar) { $this->horizontalBorderChar = $horizontalBorderChar; return $this; } /** * Gets horizontal border character. * * @return string */ public function getHorizontalBorderChar() { return $this->horizontalBorderChar; } /** * Sets vertical border character. * * @param string $verticalBorderChar * * @return TableStyle */ public function setVerticalBorderChar($verticalBorderChar) { $this->verticalBorderChar = $verticalBorderChar; return $this; } /** * Gets vertical border character. * * @return string */ public function getVerticalBorderChar() { return $this->verticalBorderChar; } /** * Sets crossing character. * * @param string $crossingChar * * @return TableStyle */ public function setCrossingChar($crossingChar) { $this->crossingChar = $crossingChar; return $this; } /** * Gets crossing character. * * @return string $crossingChar */ public function getCrossingChar() { return $this->crossingChar; } /** * Sets header cell format. * * @param string $cellHeaderFormat * * @return TableStyle */ public function setCellHeaderFormat($cellHeaderFormat) { $this->cellHeaderFormat = $cellHeaderFormat; return $this; } /** * Gets header cell format. * * @return string */ public function getCellHeaderFormat() { return $this->cellHeaderFormat; } /** * Sets row cell format. * * @param string $cellRowFormat * * @return TableStyle */ public function setCellRowFormat($cellRowFormat) { $this->cellRowFormat = $cellRowFormat; return $this; } /** * Gets row cell format. * * @return string */ public function getCellRowFormat() { return $this->cellRowFormat; } /** * Sets row cell content format. * * @param string $cellRowContentFormat * * @return TableStyle */ public function setCellRowContentFormat($cellRowContentFormat) { $this->cellRowContentFormat = $cellRowContentFormat; return $this; } /** * Gets row cell content format. * * @return string */ public function getCellRowContentFormat() { return $this->cellRowContentFormat; } /** * Sets table border format. * * @param string $borderFormat * * @return TableStyle */ public function setBorderFormat($borderFormat) { $this->borderFormat = $borderFormat; return $this; } /** * Gets table border format. * * @return string */ public function getBorderFormat() { return $this->borderFormat; } /** * Sets cell padding type. * * @param int $padType STR_PAD_* * * @return TableStyle */ public function setPadType($padType) { $this->padType = $padType; return $this; } /** * Gets cell padding type. * * @return int */ public function getPadType() { return $this->padType; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * HelperInterface is the interface all helpers must implement. * * @author Fabien Potencier * * @api */ interface HelperInterface { /** * Sets the helper set associated with this helper. * * @param HelperSet $helperSet A HelperSet instance * * @api */ public function setHelperSet(HelperSet $helperSet = null); /** * Gets the helper set associated with this helper. * * @return HelperSet A HelperSet instance * * @api */ public function getHelperSet(); /** * Returns the canonical name of this helper. * * @return string The canonical name * * @api */ public function getName(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; /** * Provides helpers to display a table. * * @author Fabien Potencier * @author Саша Стаменковић */ class Table { /** * Table headers. * * @var array */ private $headers = array(); /** * Table rows. * * @var array */ private $rows = array(); /** * Column widths cache. * * @var array */ private $columnWidths = array(); /** * Number of columns cache. * * @var array */ private $numberOfColumns; /** * @var OutputInterface */ private $output; /** * @var TableStyle */ private $style; private static $styles; public function __construct(OutputInterface $output) { $this->output = $output; if (!self::$styles) { self::$styles = self::initStyles(); } $this->setStyle('default'); } /** * Sets a style definition. * * @param string $name The style name * @param TableStyle $style A TableStyle instance */ public static function setStyleDefinition($name, TableStyle $style) { if (!self::$styles) { self::$styles = self::initStyles(); } self::$styles[$name] = $style; } /** * Gets a style definition by name. * * @param string $name The style name * * @return TableStyle A TableStyle instance */ public static function getStyleDefinition($name) { if (!self::$styles) { self::$styles = self::initStyles(); } if (!self::$styles[$name]) { throw new \InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); } return self::$styles[$name]; } /** * Sets table style. * * @param TableStyle|string $name The style name or a TableStyle instance * * @return Table */ public function setStyle($name) { if ($name instanceof TableStyle) { $this->style = $name; } elseif (isset(self::$styles[$name])) { $this->style = self::$styles[$name]; } else { throw new \InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); } return $this; } /** * Gets the current table style. * * @return TableStyle */ public function getStyle() { return $this->style; } public function setHeaders(array $headers) { $this->headers = array_values($headers); return $this; } public function setRows(array $rows) { $this->rows = array(); return $this->addRows($rows); } public function addRows(array $rows) { foreach ($rows as $row) { $this->addRow($row); } return $this; } public function addRow($row) { if ($row instanceof TableSeparator) { $this->rows[] = $row; return $this; } if (!is_array($row)) { throw new \InvalidArgumentException('A row must be an array or a TableSeparator instance.'); } $this->rows[] = array_values($row); end($this->rows); $rowKey = key($this->rows); reset($this->rows); foreach ($row as $key => $cellValue) { if (false === strpos($cellValue, "\n")) { continue; } $lines = explode("\n", $cellValue); $this->rows[$rowKey][$key] = $lines[0]; unset($lines[0]); foreach ($lines as $lineKey => $line) { $nextRowKey = $rowKey + $lineKey + 1; if (isset($this->rows[$nextRowKey])) { $this->rows[$nextRowKey][$key] = $line; } else { $this->rows[$nextRowKey] = array($key => $line); } } } return $this; } public function setRow($column, array $row) { $this->rows[$column] = $row; return $this; } /** * Renders table to output. * * Example: * +---------------+-----------------------+------------------+ * | ISBN | Title | Author | * +---------------+-----------------------+------------------+ * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | * +---------------+-----------------------+------------------+ */ public function render() { $this->renderRowSeparator(); $this->renderRow($this->headers, $this->style->getCellHeaderFormat()); if (!empty($this->headers)) { $this->renderRowSeparator(); } foreach ($this->rows as $row) { if ($row instanceof TableSeparator) { $this->renderRowSeparator(); } else { $this->renderRow($row, $this->style->getCellRowFormat()); } } if (!empty($this->rows)) { $this->renderRowSeparator(); } $this->cleanup(); } /** * Renders horizontal header separator. * * Example: +-----+-----------+-------+ */ private function renderRowSeparator() { if (0 === $count = $this->getNumberOfColumns()) { return; } if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) { return; } $markup = $this->style->getCrossingChar(); for ($column = 0; $column < $count; $column++) { $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->getColumnWidth($column)).$this->style->getCrossingChar(); } $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup)); } /** * Renders vertical column separator. */ private function renderColumnSeparator() { $this->output->write(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar())); } /** * Renders table row. * * Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * * @param array $row * @param string $cellFormat */ private function renderRow(array $row, $cellFormat) { if (empty($row)) { return; } $this->renderColumnSeparator(); for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) { $this->renderCell($row, $column, $cellFormat); $this->renderColumnSeparator(); } $this->output->writeln(''); } /** * Renders table cell with padding. * * @param array $row * @param int $column * @param string $cellFormat */ private function renderCell(array $row, $column, $cellFormat) { $cell = isset($row[$column]) ? $row[$column] : ''; $width = $this->getColumnWidth($column); // str_pad won't work properly with multi-byte strings, we need to fix the padding if (function_exists('mb_strwidth') && false !== $encoding = mb_detect_encoding($cell)) { $width += strlen($cell) - mb_strwidth($cell, $encoding); } $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); $content = sprintf($this->style->getCellRowContentFormat(), $cell); $this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->style->getPaddingChar(), $this->style->getPadType()))); } /** * Gets number of columns for this table. * * @return int */ private function getNumberOfColumns() { if (null !== $this->numberOfColumns) { return $this->numberOfColumns; } $columns = array(count($this->headers)); foreach ($this->rows as $row) { $columns[] = count($row); } return $this->numberOfColumns = max($columns); } /** * Gets column width. * * @param int $column * * @return int */ private function getColumnWidth($column) { if (isset($this->columnWidths[$column])) { return $this->columnWidths[$column]; } $lengths = array($this->getCellWidth($this->headers, $column)); foreach ($this->rows as $row) { if ($row instanceof TableSeparator) { continue; } $lengths[] = $this->getCellWidth($row, $column); } return $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2; } /** * Gets cell width. * * @param array $row * @param int $column * * @return int */ private function getCellWidth(array $row, $column) { return isset($row[$column]) ? Helper::strlenWithoutDecoration($this->output->getFormatter(), $row[$column]) : 0; } /** * Called after rendering to cleanup cache data. */ private function cleanup() { $this->columnWidths = array(); $this->numberOfColumns = null; } private static function initStyles() { $borderless = new TableStyle(); $borderless ->setHorizontalBorderChar('=') ->setVerticalBorderChar(' ') ->setCrossingChar(' ') ; $compact = new TableStyle(); $compact ->setHorizontalBorderChar('') ->setVerticalBorderChar(' ') ->setCrossingChar('') ->setCellRowContentFormat('%s') ; return array( 'default' => new TableStyle(), 'borderless' => $borderless, 'compact' => $compact, ); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Formatter\OutputFormatterInterface; /** * Helper is the base class for all helper classes. * * @author Fabien Potencier */ abstract class Helper implements HelperInterface { protected $helperSet = null; /** * Sets the helper set associated with this helper. * * @param HelperSet $helperSet A HelperSet instance */ public function setHelperSet(HelperSet $helperSet = null) { $this->helperSet = $helperSet; } /** * Gets the helper set associated with this helper. * * @return HelperSet A HelperSet instance */ public function getHelperSet() { return $this->helperSet; } /** * Returns the length of a string, using mb_strwidth if it is available. * * @param string $string The string to check its length * * @return int The length of the string */ public static function strlen($string) { if (!function_exists('mb_strwidth')) { return strlen($string); } if (false === $encoding = mb_detect_encoding($string)) { return strlen($string); } return mb_strwidth($string, $encoding); } public static function formatTime($secs) { static $timeFormats = array( array(0, '< 1 sec'), array(2, '1 sec'), array(59, 'secs', 1), array(60, '1 min'), array(3600, 'mins', 60), array(5400, '1 hr'), array(86400, 'hrs', 3600), array(129600, '1 day'), array(604800, 'days', 86400), ); foreach ($timeFormats as $format) { if ($secs >= $format[0]) { continue; } if (2 == count($format)) { return $format[1]; } return ceil($secs / $format[2]).' '.$format[1]; } } public static function formatMemory($memory) { if ($memory >= 1024 * 1024 * 1024) { return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024); } if ($memory >= 1024 * 1024) { return sprintf('%.1f MiB', $memory / 1024 / 1024); } if ($memory >= 1024) { return sprintf('%d KiB', $memory / 1024); } return sprintf('%d B', $memory); } public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string) { $isDecorated = $formatter->isDecorated(); $formatter->setDecorated(false); // remove <...> formatting $string = $formatter->format($string); // remove already formatted characters $string = preg_replace("/\033\[[^m]*m/", '', $string); $formatter->setDecorated($isDecorated); return self::strlen($string); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Question\ChoiceQuestion; /** * The QuestionHelper class provides helpers to interact with the user. * * @author Fabien Potencier */ class QuestionHelper extends Helper { private $inputStream; private static $shell; private static $stty; /** * Asks a question to the user. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * @param Question $question The question to ask * * @return string The user answer * * @throws \RuntimeException If there is no data to read in the input stream */ public function ask(InputInterface $input, OutputInterface $output, Question $question) { if (!$input->isInteractive()) { return $question->getDefault(); } if (!$question->getValidator()) { return $this->doAsk($output, $question); } $that = $this; $interviewer = function () use ($output, $question, $that) { return $that->doAsk($output, $question); }; return $this->validateAttempts($interviewer, $output, $question); } /** * Sets the input stream to read from when interacting with the user. * * This is mainly useful for testing purpose. * * @param resource $stream The input stream * * @throws \InvalidArgumentException In case the stream is not a resource */ public function setInputStream($stream) { if (!is_resource($stream)) { throw new \InvalidArgumentException('Input stream must be a valid resource.'); } $this->inputStream = $stream; } /** * Returns the helper's input stream * * @return resource */ public function getInputStream() { return $this->inputStream; } /** * {@inheritdoc} */ public function getName() { return 'question'; } /** * Asks the question to the user. * * This method is public for PHP 5.3 compatibility, it should be private. * * @param OutputInterface $output * @param Question $question * * @return bool|mixed|null|string * * @throws \Exception * @throws \RuntimeException */ public function doAsk(OutputInterface $output, Question $question) { $inputStream = $this->inputStream ?: STDIN; $message = $question->getQuestion(); if ($question instanceof ChoiceQuestion) { $width = max(array_map('strlen', array_keys($question->getChoices()))); $messages = (array) $question->getQuestion(); foreach ($question->getChoices() as $key => $value) { $messages[] = sprintf(" [%-${width}s] %s", $key, $value); } $output->writeln($messages); $message = $question->getPrompt(); } $output->write($message); $autocomplete = $question->getAutocompleterValues(); if (null === $autocomplete || !$this->hasSttyAvailable()) { $ret = false; if ($question->isHidden()) { try { $ret = trim($this->getHiddenResponse($output, $inputStream)); } catch (\RuntimeException $e) { if (!$question->isHiddenFallback()) { throw $e; } } } if (false === $ret) { $ret = fgets($inputStream, 4096); if (false === $ret) { throw new \RuntimeException('Aborted'); } $ret = trim($ret); } } else { $ret = trim($this->autocomplete($output, $question, $inputStream)); } $ret = strlen($ret) > 0 ? $ret : $question->getDefault(); if ($normalizer = $question->getNormalizer()) { return $normalizer($ret); } return $ret; } /** * Autocompletes a question. * * @param OutputInterface $output * @param Question $question * * @return string */ private function autocomplete(OutputInterface $output, Question $question, $inputStream) { $autocomplete = $question->getAutocompleterValues(); $ret = ''; $i = 0; $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); $sttyMode = shell_exec('stty -g'); // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) shell_exec('stty -icanon -echo'); // Add highlighted text style $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); // Read a keypress while (!feof($inputStream)) { $c = fread($inputStream, 1); // Backspace Character if ("\177" === $c) { if (0 === $numMatches && 0 !== $i) { $i--; // Move cursor backwards $output->write("\033[1D"); } if ($i === 0) { $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); } else { $numMatches = 0; } // Pop the last character off the end of our string $ret = substr($ret, 0, $i); } elseif ("\033" === $c) { // Did we read an escape sequence? $c .= fread($inputStream, 2); // A = Up Arrow. B = Down Arrow if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) { if ('A' === $c[2] && -1 === $ofs) { $ofs = 0; } if (0 === $numMatches) { continue; } $ofs += ('A' === $c[2]) ? -1 : 1; $ofs = ($numMatches + $ofs) % $numMatches; } } elseif (ord($c) < 32) { if ("\t" === $c || "\n" === $c) { if ($numMatches > 0 && -1 !== $ofs) { $ret = $matches[$ofs]; // Echo out remaining chars for current match $output->write(substr($ret, $i)); $i = strlen($ret); } if ("\n" === $c) { $output->write($c); break; } $numMatches = 0; } continue; } else { $output->write($c); $ret .= $c; $i++; $numMatches = 0; $ofs = 0; foreach ($autocomplete as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) if (0 === strpos($value, $ret) && $i !== strlen($value)) { $matches[$numMatches++] = $value; } } } // Erase characters from cursor to end of line $output->write("\033[K"); if ($numMatches > 0 && -1 !== $ofs) { // Save cursor position $output->write("\0337"); // Write highlighted text $output->write(''.substr($matches[$ofs], $i).''); // Restore cursor position $output->write("\0338"); } } // Reset stty so it behaves normally again shell_exec(sprintf('stty %s', $sttyMode)); return $ret; } /** * Gets a hidden response from user. * * @param OutputInterface $output An Output instance * * @return string The answer * * @throws \RuntimeException In case the fallback is deactivated and the response cannot be hidden */ private function getHiddenResponse(OutputInterface $output, $inputStream) { if ('\\' === DIRECTORY_SEPARATOR) { $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; // handle code running from a phar if ('phar:' === substr(__FILE__, 0, 5)) { $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; copy($exe, $tmpExe); $exe = $tmpExe; } $value = rtrim(shell_exec($exe)); $output->writeln(''); if (isset($tmpExe)) { unlink($tmpExe); } return $value; } if ($this->hasSttyAvailable()) { $sttyMode = shell_exec('stty -g'); shell_exec('stty -echo'); $value = fgets($inputStream, 4096); shell_exec(sprintf('stty %s', $sttyMode)); if (false === $value) { throw new \RuntimeException('Aborted'); } $value = trim($value); $output->writeln(''); return $value; } if (false !== $shell = $this->getShell()) { $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); $value = rtrim(shell_exec($command)); $output->writeln(''); return $value; } throw new \RuntimeException('Unable to hide the response.'); } /** * Validates an attempt. * * @param callable $interviewer A callable that will ask for a question and return the result * @param OutputInterface $output An Output instance * @param Question $question A Question instance * * @return string The validated response * * @throws \Exception In case the max number of attempts has been reached and no valid response has been given */ private function validateAttempts($interviewer, OutputInterface $output, Question $question) { $error = null; $attempts = $question->getMaxAttempts(); while (null === $attempts || $attempts--) { if (null !== $error) { if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) { $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'); } else { $message = ''.$error->getMessage().''; } $output->writeln($message); } try { return call_user_func($question->getValidator(), $interviewer()); } catch (\Exception $error) { } } throw $error; } /** * Returns a valid unix shell. * * @return string|bool The valid shell name, false in case no valid shell is found */ private function getShell() { if (null !== self::$shell) { return self::$shell; } self::$shell = false; if (file_exists('/usr/bin/env')) { // handle other OSs with bash/zsh/ksh/csh if available to hide the answer $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) { if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { self::$shell = $sh; break; } } } return self::$shell; } /** * Returns whether Stty is available or not. * * @return bool */ private function hasSttyAvailable() { if (null !== self::$stty) { return self::$stty; } exec('stty 2>&1', $output, $exitcode); return self::$stty = $exitcode === 0; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Descriptor\DescriptorInterface; use Symfony\Component\Console\Descriptor\JsonDescriptor; use Symfony\Component\Console\Descriptor\MarkdownDescriptor; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Output\OutputInterface; /** * This class adds helper method to describe objects in various formats. * * @author Jean-François Simon */ class DescriptorHelper extends Helper { /** * @var DescriptorInterface[] */ private $descriptors = array(); /** * Constructor. */ public function __construct() { $this ->register('txt', new TextDescriptor()) ->register('xml', new XmlDescriptor()) ->register('json', new JsonDescriptor()) ->register('md', new MarkdownDescriptor()) ; } /** * Describes an object if supported. * * Available options are: * * format: string, the output format name * * raw_text: boolean, sets output type as raw * * @param OutputInterface $output * @param object $object * @param array $options * * @throws \InvalidArgumentException when the given format is not supported */ public function describe(OutputInterface $output, $object, array $options = array()) { $options = array_merge(array( 'raw_text' => false, 'format' => 'txt', ), $options); if (!isset($this->descriptors[$options['format']])) { throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); } $descriptor = $this->descriptors[$options['format']]; $descriptor->describe($output, $object, $options); } /** * Registers a descriptor. * * @param string $format * @param DescriptorInterface $descriptor * * @return DescriptorHelper */ public function register($format, DescriptorInterface $descriptor) { $this->descriptors[$format] = $descriptor; return $this; } /** * {@inheritdoc} */ public function getName() { return 'descriptor'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Output\OutputInterface; /** * The ProgressBar provides helpers to display progress output. * * @author Fabien Potencier * @author Chris Jones */ class ProgressBar { // options private $barWidth = 28; private $barChar; private $emptyBarChar = '-'; private $progressChar = '>'; private $format = null; private $redrawFreq = 1; /** * @var OutputInterface */ private $output; private $step = 0; private $max; private $startTime; private $stepWidth; private $percent = 0.0; private $lastMessagesLength = 0; private $formatLineCount; private $messages; private $overwrite = true; private static $formatters; private static $formats; /** * Constructor. * * @param OutputInterface $output An OutputInterface instance * @param int $max Maximum steps (0 if unknown) */ public function __construct(OutputInterface $output, $max = 0) { $this->output = $output; $this->setMaxSteps($max); if (!$this->output->isDecorated()) { // disable overwrite when output does not support ANSI codes. $this->overwrite = false; if ($this->max > 10) { // set a reasonable redraw frequency so output isn't flooded $this->setRedrawFrequency($max / 10); } } $this->setFormat($this->determineBestFormat()); $this->startTime = time(); } /** * Sets a placeholder formatter for a given name. * * This method also allow you to override an existing placeholder. * * @param string $name The placeholder name (including the delimiter char like %) * @param callable $callable A PHP callable */ public static function setPlaceholderFormatterDefinition($name, $callable) { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } self::$formatters[$name] = $callable; } /** * Gets the placeholder formatter for a given name. * * @param string $name The placeholder name (including the delimiter char like %) * * @return callable|null A PHP callable */ public static function getPlaceholderFormatterDefinition($name) { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); } return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; } /** * Sets a format for a given name. * * This method also allow you to override an existing format. * * @param string $name The format name * @param string $format A format string */ public static function setFormatDefinition($name, $format) { if (!self::$formats) { self::$formats = self::initFormats(); } self::$formats[$name] = $format; } /** * Gets the format for a given name. * * @param string $name The format name * * @return string|null A format string */ public static function getFormatDefinition($name) { if (!self::$formats) { self::$formats = self::initFormats(); } return isset(self::$formats[$name]) ? self::$formats[$name] : null; } public function setMessage($message, $name = 'message') { $this->messages[$name] = $message; } public function getMessage($name = 'message') { return $this->messages[$name]; } /** * Gets the progress bar start time. * * @return int The progress bar start time */ public function getStartTime() { return $this->startTime; } /** * Gets the progress bar maximal steps. * * @return int The progress bar max steps */ public function getMaxSteps() { return $this->max; } /** * Gets the progress bar step. * * @deprecated since 2.6, to be removed in 3.0. Use {@link getProgress()} instead. * * @return int The progress bar step */ public function getStep() { return $this->getProgress(); } /** * Gets the current step position. * * @return int The progress bar step */ public function getProgress() { return $this->step; } /** * Gets the progress bar step width. * * @internal This method is public for PHP 5.3 compatibility, it should not be used. * * @return int The progress bar step width */ public function getStepWidth() { return $this->stepWidth; } /** * Gets the current progress bar percent. * * @return float The current progress bar percent */ public function getProgressPercent() { return $this->percent; } /** * Sets the progress bar width. * * @param int $size The progress bar size */ public function setBarWidth($size) { $this->barWidth = (int) $size; } /** * Gets the progress bar width. * * @return int The progress bar size */ public function getBarWidth() { return $this->barWidth; } /** * Sets the bar character. * * @param string $char A character */ public function setBarCharacter($char) { $this->barChar = $char; } /** * Gets the bar character. * * @return string A character */ public function getBarCharacter() { if (null === $this->barChar) { return $this->max ? '=' : $this->emptyBarChar; } return $this->barChar; } /** * Sets the empty bar character. * * @param string $char A character */ public function setEmptyBarCharacter($char) { $this->emptyBarChar = $char; } /** * Gets the empty bar character. * * @return string A character */ public function getEmptyBarCharacter() { return $this->emptyBarChar; } /** * Sets the progress bar character. * * @param string $char A character */ public function setProgressCharacter($char) { $this->progressChar = $char; } /** * Gets the progress bar character. * * @return string A character */ public function getProgressCharacter() { return $this->progressChar; } /** * Sets the progress bar format. * * @param string $format The format */ public function setFormat($format) { // try to use the _nomax variant if available if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) { $this->format = self::getFormatDefinition($format.'_nomax'); } elseif (null !== self::getFormatDefinition($format)) { $this->format = self::getFormatDefinition($format); } else { $this->format = $format; } $this->formatLineCount = substr_count($this->format, "\n"); } /** * Sets the redraw frequency. * * @param int $freq The frequency in steps */ public function setRedrawFrequency($freq) { $this->redrawFreq = (int) $freq; } /** * Starts the progress output. * * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged */ public function start($max = null) { $this->startTime = time(); $this->step = 0; $this->percent = 0.0; if (null !== $max) { $this->setMaxSteps($max); } $this->display(); } /** * Advances the progress output X steps. * * @param int $step Number of steps to advance * * @throws \LogicException */ public function advance($step = 1) { $this->setProgress($this->step + $step); } /** * Sets the current progress. * * @deprecated since 2.6, to be removed in 3.0. Use {@link setProgress()} instead. * * @param int $step The current progress * * @throws \LogicException */ public function setCurrent($step) { $this->setProgress($step); } /** * Sets whether to overwrite the progressbar, false for new line. * * @param bool $overwrite */ public function setOverwrite($overwrite) { $this->overwrite = (bool) $overwrite; } /** * Sets the current progress. * * @param int $step The current progress * * @throws \LogicException */ public function setProgress($step) { $step = (int) $step; if ($step < $this->step) { throw new \LogicException('You can\'t regress the progress bar.'); } if ($this->max && $step > $this->max) { $this->max = $step; } $prevPeriod = (int) ($this->step / $this->redrawFreq); $currPeriod = (int) ($step / $this->redrawFreq); $this->step = $step; $this->percent = $this->max ? (float) $this->step / $this->max : 0; if ($prevPeriod !== $currPeriod || $this->max === $step) { $this->display(); } } /** * Finishes the progress output. */ public function finish() { if (!$this->max) { $this->max = $this->step; } if ($this->step === $this->max && !$this->overwrite) { // prevent double 100% output return; } $this->setProgress($this->max); } /** * Outputs the current progress string. */ public function display() { if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { return; } // these 3 variables can be removed in favor of using $this in the closure when support for PHP 5.3 will be dropped. $self = $this; $output = $this->output; $messages = $this->messages; $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) { if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) { $text = call_user_func($formatter, $self, $output); } elseif (isset($messages[$matches[1]])) { $text = $messages[$matches[1]]; } else { return $matches[0]; } if (isset($matches[2])) { $text = sprintf('%'.$matches[2], $text); } return $text; }, $this->format)); } /** * Removes the progress bar from the current line. * * This is useful if you wish to write some output * while a progress bar is running. * Call display() to show the progress bar again. */ public function clear() { if (!$this->overwrite) { return; } $this->overwrite(str_repeat("\n", $this->formatLineCount)); } /** * Sets the progress bar maximal steps. * * @param int The progress bar max steps */ private function setMaxSteps($max) { $this->max = max(0, (int) $max); $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4; } /** * Overwrites a previous message to the output. * * @param string $message The message */ private function overwrite($message) { $lines = explode("\n", $message); // append whitespace to match the line's length if (null !== $this->lastMessagesLength) { foreach ($lines as $i => $line) { if ($this->lastMessagesLength > Helper::strlenWithoutDecoration($this->output->getFormatter(), $line)) { $lines[$i] = str_pad($line, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); } } } if ($this->overwrite) { // move back to the beginning of the progress bar before redrawing it $this->output->write("\x0D"); } elseif ($this->step > 0) { // move to new line $this->output->writeln(''); } if ($this->formatLineCount) { $this->output->write(sprintf("\033[%dA", $this->formatLineCount)); } $this->output->write(implode("\n", $lines)); $this->lastMessagesLength = 0; foreach ($lines as $line) { $len = Helper::strlenWithoutDecoration($this->output->getFormatter(), $line); if ($len > $this->lastMessagesLength) { $this->lastMessagesLength = $len; } } } private function determineBestFormat() { switch ($this->output->getVerbosity()) { // OutputInterface::VERBOSITY_QUIET: display is disabled anyway case OutputInterface::VERBOSITY_VERBOSE: return $this->max ? 'verbose' : 'verbose_nomax'; case OutputInterface::VERBOSITY_VERY_VERBOSE: return $this->max ? 'very_verbose' : 'very_verbose_nomax'; case OutputInterface::VERBOSITY_DEBUG: return $this->max ? 'debug' : 'debug_nomax'; default: return $this->max ? 'normal' : 'normal_nomax'; } } private static function initPlaceholderFormatters() { return array( 'bar' => function (ProgressBar $bar, OutputInterface $output) { $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth()); $display = str_repeat($bar->getBarCharacter(), $completeBars); if ($completeBars < $bar->getBarWidth()) { $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter()); $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars); } return $display; }, 'elapsed' => function (ProgressBar $bar) { return Helper::formatTime(time() - $bar->getStartTime()); }, 'remaining' => function (ProgressBar $bar) { if (!$bar->getMaxSteps()) { throw new \LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); } if (!$bar->getProgress()) { $remaining = 0; } else { $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress())); } return Helper::formatTime($remaining); }, 'estimated' => function (ProgressBar $bar) { if (!$bar->getMaxSteps()) { throw new \LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); } if (!$bar->getProgress()) { $estimated = 0; } else { $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps()); } return Helper::formatTime($estimated); }, 'memory' => function (ProgressBar $bar) { return Helper::formatMemory(memory_get_usage(true)); }, 'current' => function (ProgressBar $bar) { return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT); }, 'max' => function (ProgressBar $bar) { return $bar->getMaxSteps(); }, 'percent' => function (ProgressBar $bar) { return floor($bar->getProgressPercent() * 100); }, ); } private static function initFormats() { return array( 'normal' => ' %current%/%max% [%bar%] %percent:3s%%', 'normal_nomax' => ' %current% [%bar%]', 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%', ); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Formatter\OutputFormatter; /** * The Formatter class provides helpers to format messages. * * @author Fabien Potencier */ class FormatterHelper extends Helper { /** * Formats a message within a section. * * @param string $section The section name * @param string $message The message * @param string $style The style to apply to the section * * @return string The format section */ public function formatSection($section, $message, $style = 'info') { return sprintf('<%s>[%s] %s', $style, $section, $style, $message); } /** * Formats a message as a block of text. * * @param string|array $messages The message to write in the block * @param string $style The style to apply to the whole block * @param bool $large Whether to return a large block * * @return string The formatter message */ public function formatBlock($messages, $style, $large = false) { if (!is_array($messages)) { $messages = array($messages); } $len = 0; $lines = array(); foreach ($messages as $message) { $message = OutputFormatter::escape($message); $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); $len = max($this->strlen($message) + ($large ? 4 : 2), $len); } $messages = $large ? array(str_repeat(' ', $len)) : array(); for ($i = 0; isset($lines[$i]); ++$i) { $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i])); } if ($large) { $messages[] = str_repeat(' ', $len); } for ($i = 0; isset($messages[$i]); ++$i) { $messages[$i] = sprintf('<%s>%s', $style, $messages[$i], $style); } return implode("\n", $messages); } /** * {@inheritdoc} */ public function getName() { return 'formatter'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; /** * Marks a row as being a separator. * * @author Fabien Potencier */ class TableSeparator { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Helper; use Symfony\Component\Console\Command\Command; /** * HelperSet represents a set of helpers to be used with a command. * * @author Fabien Potencier */ class HelperSet implements \IteratorAggregate { private $helpers = array(); private $command; /** * Constructor. * * @param Helper[] $helpers An array of helper. */ public function __construct(array $helpers = array()) { foreach ($helpers as $alias => $helper) { $this->set($helper, is_int($alias) ? null : $alias); } } /** * Sets a helper. * * @param HelperInterface $helper The helper instance * @param string $alias An alias */ public function set(HelperInterface $helper, $alias = null) { $this->helpers[$helper->getName()] = $helper; if (null !== $alias) { $this->helpers[$alias] = $helper; } $helper->setHelperSet($this); } /** * Returns true if the helper if defined. * * @param string $name The helper name * * @return bool true if the helper is defined, false otherwise */ public function has($name) { return isset($this->helpers[$name]); } /** * Gets a helper value. * * @param string $name The helper name * * @return HelperInterface The helper instance * * @throws \InvalidArgumentException if the helper is not defined */ public function get($name) { if (!$this->has($name)) { throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); } return $this->helpers[$name]; } /** * Sets the command associated with this helper set. * * @param Command $command A Command instance */ public function setCommand(Command $command = null) { $this->command = $command; } /** * Gets the command associated with this helper set. * * @return Command A Command instance */ public function getCommand() { return $this->command; } public function getIterator() { return new \ArrayIterator($this->helpers); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console; use Symfony\Component\Console\Descriptor\TextDescriptor; use Symfony\Component\Console\Descriptor\XmlDescriptor; use Symfony\Component\Console\Helper\DebugFormatterHelper; use Symfony\Component\Console\Helper\ProcessHelper; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputAwareInterface; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\HelpCommand; use Symfony\Component\Console\Command\ListCommand; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Helper\FormatterHelper; use Symfony\Component\Console\Helper\DialogHelper; use Symfony\Component\Console\Helper\ProgressHelper; use Symfony\Component\Console\Helper\TableHelper; use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * An Application is the container for a collection of commands. * * It is the main entry point of a Console application. * * This class is optimized for a standard CLI environment. * * Usage: * * $app = new Application('myapp', '1.0 (stable)'); * $app->add(new SimpleCommand()); * $app->run(); * * @author Fabien Potencier * * @api */ class Application { private $commands = array(); private $wantHelps = false; private $runningCommand; private $name; private $version; private $catchExceptions = true; private $autoExit = true; private $definition; private $helperSet; private $dispatcher; private $terminalDimensions; private $defaultCommand; /** * Constructor. * * @param string $name The name of the application * @param string $version The version of the application * * @api */ public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') { $this->name = $name; $this->version = $version; $this->defaultCommand = 'list'; $this->helperSet = $this->getDefaultHelperSet(); $this->definition = $this->getDefaultInputDefinition(); foreach ($this->getDefaultCommands() as $command) { $this->add($command); } } public function setDispatcher(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } /** * Runs the current application. * * @param InputInterface $input An Input instance * @param OutputInterface $output An Output instance * * @return int 0 if everything went fine, or an error code * * @throws \Exception When doRun returns Exception * * @api */ public function run(InputInterface $input = null, OutputInterface $output = null) { if (null === $input) { $input = new ArgvInput(); } if (null === $output) { $output = new ConsoleOutput(); } $this->configureIO($input, $output); try { $exitCode = $this->doRun($input, $output); } catch (\Exception $e) { if (!$this->catchExceptions) { throw $e; } if ($output instanceof ConsoleOutputInterface) { $this->renderException($e, $output->getErrorOutput()); } else { $this->renderException($e, $output); } $exitCode = $e->getCode(); if (is_numeric($exitCode)) { $exitCode = (int) $exitCode; if (0 === $exitCode) { $exitCode = 1; } } else { $exitCode = 1; } } if ($this->autoExit) { if ($exitCode > 255) { $exitCode = 255; } exit($exitCode); } return $exitCode; } /** * Runs the current application. * * @param InputInterface $input An Input instance * @param OutputInterface $output An Output instance * * @return int 0 if everything went fine, or an error code */ public function doRun(InputInterface $input, OutputInterface $output) { if (true === $input->hasParameterOption(array('--version', '-V'))) { $output->writeln($this->getLongVersion()); return 0; } $name = $this->getCommandName($input); if (true === $input->hasParameterOption(array('--help', '-h'))) { if (!$name) { $name = 'help'; $input = new ArrayInput(array('command' => 'help')); } else { $this->wantHelps = true; } } if (!$name) { $name = $this->defaultCommand; $input = new ArrayInput(array('command' => $this->defaultCommand)); } // the command name MUST be the first element of the input $command = $this->find($name); $this->runningCommand = $command; $exitCode = $this->doRunCommand($command, $input, $output); $this->runningCommand = null; return $exitCode; } /** * Set a helper set to be used with the command. * * @param HelperSet $helperSet The helper set * * @api */ public function setHelperSet(HelperSet $helperSet) { $this->helperSet = $helperSet; } /** * Get the helper set associated with the command. * * @return HelperSet The HelperSet instance associated with this command * * @api */ public function getHelperSet() { return $this->helperSet; } /** * Set an input definition set to be used with this application. * * @param InputDefinition $definition The input definition * * @api */ public function setDefinition(InputDefinition $definition) { $this->definition = $definition; } /** * Gets the InputDefinition related to this Application. * * @return InputDefinition The InputDefinition instance */ public function getDefinition() { return $this->definition; } /** * Gets the help message. * * @return string A help message. */ public function getHelp() { return $this->getLongVersion(); } /** * Sets whether to catch exceptions or not during commands execution. * * @param bool $boolean Whether to catch exceptions or not during commands execution * * @api */ public function setCatchExceptions($boolean) { $this->catchExceptions = (bool) $boolean; } /** * Sets whether to automatically exit after a command execution or not. * * @param bool $boolean Whether to automatically exit after a command execution or not * * @api */ public function setAutoExit($boolean) { $this->autoExit = (bool) $boolean; } /** * Gets the name of the application. * * @return string The application name * * @api */ public function getName() { return $this->name; } /** * Sets the application name. * * @param string $name The application name * * @api */ public function setName($name) { $this->name = $name; } /** * Gets the application version. * * @return string The application version * * @api */ public function getVersion() { return $this->version; } /** * Sets the application version. * * @param string $version The application version * * @api */ public function setVersion($version) { $this->version = $version; } /** * Returns the long version of the application. * * @return string The long application version * * @api */ public function getLongVersion() { if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) { return sprintf('%s version %s', $this->getName(), $this->getVersion()); } return 'Console Tool'; } /** * Registers a new command. * * @param string $name The command name * * @return Command The newly created command * * @api */ public function register($name) { return $this->add(new Command($name)); } /** * Adds an array of command objects. * * @param Command[] $commands An array of commands * * @api */ public function addCommands(array $commands) { foreach ($commands as $command) { $this->add($command); } } /** * Adds a command object. * * If a command with the same name already exists, it will be overridden. * * @param Command $command A Command object * * @return Command The registered command * * @api */ public function add(Command $command) { $command->setApplication($this); if (!$command->isEnabled()) { $command->setApplication(null); return; } if (null === $command->getDefinition()) { throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command))); } $this->commands[$command->getName()] = $command; foreach ($command->getAliases() as $alias) { $this->commands[$alias] = $command; } return $command; } /** * Returns a registered command by name or alias. * * @param string $name The command name or alias * * @return Command A Command object * * @throws \InvalidArgumentException When command name given does not exist * * @api */ public function get($name) { if (!isset($this->commands[$name])) { throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name)); } $command = $this->commands[$name]; if ($this->wantHelps) { $this->wantHelps = false; $helpCommand = $this->get('help'); $helpCommand->setCommand($command); return $helpCommand; } return $command; } /** * Returns true if the command exists, false otherwise. * * @param string $name The command name or alias * * @return bool true if the command exists, false otherwise * * @api */ public function has($name) { return isset($this->commands[$name]); } /** * Returns an array of all unique namespaces used by currently registered commands. * * It does not returns the global namespace which always exists. * * @return array An array of namespaces */ public function getNamespaces() { $namespaces = array(); foreach ($this->commands as $command) { $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName())); foreach ($command->getAliases() as $alias) { $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias)); } } return array_values(array_unique(array_filter($namespaces))); } /** * Finds a registered namespace by a name or an abbreviation. * * @param string $namespace A namespace or abbreviation to search for * * @return string A registered namespace * * @throws \InvalidArgumentException When namespace is incorrect or ambiguous */ public function findNamespace($namespace) { $allNamespaces = $this->getNamespaces(); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace); $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); if (empty($namespaces)) { $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) { if (1 == count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { $message .= "\n\nDid you mean one of these?\n "; } $message .= implode("\n ", $alternatives); } throw new \InvalidArgumentException($message); } $exact = in_array($namespace, $namespaces, true); if (count($namespaces) > 1 && !$exact) { throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces)))); } return $exact ? $namespace : reset($namespaces); } /** * Finds a command by name or alias. * * Contrary to get, this command tries to find the best * match if you give it an abbreviation of a name or alias. * * @param string $name A command name or a command alias * * @return Command A Command instance * * @throws \InvalidArgumentException When command name is incorrect or ambiguous * * @api */ public function find($name) { $allCommands = array_keys($this->commands); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); $commands = preg_grep('{^'.$expr.'}', $allCommands); if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) { if (false !== $pos = strrpos($name, ':')) { // check if a namespace exists and contains commands $this->findNamespace(substr($name, 0, $pos)); } $message = sprintf('Command "%s" is not defined.', $name); if ($alternatives = $this->findAlternatives($name, $allCommands)) { if (1 == count($alternatives)) { $message .= "\n\nDid you mean this?\n "; } else { $message .= "\n\nDid you mean one of these?\n "; } $message .= implode("\n ", $alternatives); } throw new \InvalidArgumentException($message); } // filter out aliases for commands which are already on the list if (count($commands) > 1) { $commandList = $this->commands; $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) { $commandName = $commandList[$nameOrAlias]->getName(); return $commandName === $nameOrAlias || !in_array($commandName, $commands); }); } $exact = in_array($name, $commands, true); if (count($commands) > 1 && !$exact) { $suggestions = $this->getAbbreviationSuggestions(array_values($commands)); throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions)); } return $this->get($exact ? $name : reset($commands)); } /** * Gets the commands (registered in the given namespace if provided). * * The array keys are the full names and the values the command instances. * * @param string $namespace A namespace name * * @return Command[] An array of Command instances * * @api */ public function all($namespace = null) { if (null === $namespace) { return $this->commands; } $commands = array(); foreach ($this->commands as $name => $command) { if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { $commands[$name] = $command; } } return $commands; } /** * Returns an array of possible abbreviations given a set of names. * * @param array $names An array of names * * @return array An array of abbreviations */ public static function getAbbreviations($names) { $abbrevs = array(); foreach ($names as $name) { for ($len = strlen($name); $len > 0; --$len) { $abbrev = substr($name, 0, $len); $abbrevs[$abbrev][] = $name; } } return $abbrevs; } /** * Returns a text representation of the Application. * * @param string $namespace An optional namespace name * @param bool $raw Whether to return raw command list * * @return string A string representing the Application * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asText($namespace = null, $raw = false) { $descriptor = new TextDescriptor(); $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw); $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true)); return $output->fetch(); } /** * Returns an XML representation of the Application. * * @param string $namespace An optional namespace name * @param bool $asDom Whether to return a DOM or an XML string * * @return string|\DOMDocument An XML string representing the Application * * @deprecated Deprecated since version 2.3, to be removed in 3.0. */ public function asXml($namespace = null, $asDom = false) { $descriptor = new XmlDescriptor(); if ($asDom) { return $descriptor->getApplicationDocument($this, $namespace); } $output = new BufferedOutput(); $descriptor->describe($output, $this, array('namespace' => $namespace)); return $output->fetch(); } /** * Renders a caught exception. * * @param \Exception $e An exception instance * @param OutputInterface $output An OutputInterface instance */ public function renderException($e, $output) { do { $title = sprintf(' [%s] ', get_class($e)); $len = $this->stringWidth($title); $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX; // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327 if (defined('HHVM_VERSION') && $width > 1 << 31) { $width = 1 << 31; } $formatter = $output->getFormatter(); $lines = array(); foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { foreach ($this->splitStringByWidth($line, $width - 4) as $line) { // pre-format lines to get the right string length $lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4; $lines[] = array($line, $lineLength); $len = max($lineLength, $len); } } $messages = array('', ''); $messages[] = $emptyLine = $formatter->format(sprintf('%s', str_repeat(' ', $len))); $messages[] = $formatter->format(sprintf('%s%s', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title))))); foreach ($lines as $line) { $messages[] = $formatter->format(sprintf(' %s %s', $line[0], str_repeat(' ', $len - $line[1]))); } $messages[] = $emptyLine; $messages[] = ''; $messages[] = ''; $output->writeln($messages, OutputInterface::OUTPUT_RAW); if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $output->writeln('Exception trace:'); // exception related properties $trace = $e->getTrace(); array_unshift($trace, array( 'function' => '', 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a', 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a', 'args' => array(), )); for ($i = 0, $count = count($trace); $i < $count; ++$i) { $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; $function = $trace[$i]['function']; $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; $output->writeln(sprintf(' %s%s%s() at %s:%s', $class, $type, $function, $file, $line)); } $output->writeln(''); $output->writeln(''); } } while ($e = $e->getPrevious()); if (null !== $this->runningCommand) { $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName()))); $output->writeln(''); $output->writeln(''); } } /** * Tries to figure out the terminal width in which this application runs. * * @return int|null */ protected function getTerminalWidth() { $dimensions = $this->getTerminalDimensions(); return $dimensions[0]; } /** * Tries to figure out the terminal height in which this application runs. * * @return int|null */ protected function getTerminalHeight() { $dimensions = $this->getTerminalDimensions(); return $dimensions[1]; } /** * Tries to figure out the terminal dimensions based on the current environment. * * @return array Array containing width and height */ public function getTerminalDimensions() { if ($this->terminalDimensions) { return $this->terminalDimensions; } if ('\\' === DIRECTORY_SEPARATOR) { // extract [w, H] from "wxh (WxH)" if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) { return array((int) $matches[1], (int) $matches[2]); } // extract [w, h] from "wxh" if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) { return array((int) $matches[1], (int) $matches[2]); } } if ($sttyString = $this->getSttyColumns()) { // extract [w, h] from "rows h; columns w;" if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { return array((int) $matches[2], (int) $matches[1]); } // extract [w, h] from "; h rows; w columns" if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { return array((int) $matches[2], (int) $matches[1]); } } return array(null, null); } /** * Sets terminal dimensions. * * Can be useful to force terminal dimensions for functional tests. * * @param int $width The width * @param int $height The height * * @return Application The current application */ public function setTerminalDimensions($width, $height) { $this->terminalDimensions = array($width, $height); return $this; } /** * Configures the input and output instances based on the user arguments and options. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ protected function configureIO(InputInterface $input, OutputInterface $output) { if (true === $input->hasParameterOption(array('--ansi'))) { $output->setDecorated(true); } elseif (true === $input->hasParameterOption(array('--no-ansi'))) { $output->setDecorated(false); } if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) { $input->setInteractive(false); } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) { $inputStream = $this->getHelperSet()->get('question')->getInputStream(); if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) { $input->setInteractive(false); } } if (true === $input->hasParameterOption(array('--quiet', '-q'))) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); } else { if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) { $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) { $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) { $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); } } } /** * Runs the current command. * * If an event dispatcher has been attached to the application, * events are also dispatched during the life-cycle of the command. * * @param Command $command A Command instance * @param InputInterface $input An Input instance * @param OutputInterface $output An Output instance * * @return int 0 if everything went fine, or an error code * * @throws \Exception when the command being run threw an exception */ protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) { foreach ($command->getHelperSet() as $helper) { if ($helper instanceof InputAwareInterface) { $helper->setInput($input); } } if (null === $this->dispatcher) { return $command->run($input, $output); } $event = new ConsoleCommandEvent($command, $input, $output); $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); if ($event->commandShouldRun()) { try { $exitCode = $command->run($input, $output); } catch (\Exception $e) { $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode()); $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); $event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode()); $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); throw $event->getException(); } } else { $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED; } $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); return $event->getExitCode(); } /** * Gets the name of the command based on input. * * @param InputInterface $input The input interface * * @return string The command name */ protected function getCommandName(InputInterface $input) { return $input->getFirstArgument(); } /** * Gets the default input definition. * * @return InputDefinition An InputDefinition instance */ protected function getDefaultInputDefinition() { return new InputDefinition(array( new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'), new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'), new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'), new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'), )); } /** * Gets the default commands that should always be available. * * @return Command[] An array of default Command instances */ protected function getDefaultCommands() { return array(new HelpCommand(), new ListCommand()); } /** * Gets the default helper set with the helpers that should always be available. * * @return HelperSet A HelperSet instance */ protected function getDefaultHelperSet() { return new HelperSet(array( new FormatterHelper(), new DialogHelper(), new ProgressHelper(), new TableHelper(), new DebugFormatterHelper(), new ProcessHelper(), new QuestionHelper(), )); } /** * Runs and parses stty -a if it's available, suppressing any error output. * * @return string */ private function getSttyColumns() { if (!function_exists('proc_open')) { return; } $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); if (is_resource($process)) { $info = stream_get_contents($pipes[1]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); return $info; } } /** * Runs and parses mode CON if it's available, suppressing any error output. * * @return string x or null if it could not be parsed */ private function getConsoleMode() { if (!function_exists('proc_open')) { return; } $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')); $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true)); if (is_resource($process)) { $info = stream_get_contents($pipes[1]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { return $matches[2].'x'.$matches[1]; } } } /** * Returns abbreviated suggestions in string format. * * @param array $abbrevs Abbreviated suggestions to convert * * @return string A formatted string of abbreviated suggestions */ private function getAbbreviationSuggestions($abbrevs) { return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : ''); } /** * Returns the namespace part of the command name. * * This method is not part of public API and should not be used directly. * * @param string $name The full name of the command * @param string $limit The maximum number of parts of the namespace * * @return string The namespace of the command */ public function extractNamespace($name, $limit = null) { $parts = explode(':', $name); array_pop($parts); return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit)); } /** * Finds alternative of $name among $collection, * if nothing is found in $collection, try in $abbrevs. * * @param string $name The string * @param array|\Traversable $collection The collection * * @return array A sorted array of similar string */ private function findAlternatives($name, $collection) { $threshold = 1e3; $alternatives = array(); $collectionParts = array(); foreach ($collection as $item) { $collectionParts[$item] = explode(':', $item); } foreach (explode(':', $name) as $i => $subname) { foreach ($collectionParts as $collectionName => $parts) { $exists = isset($alternatives[$collectionName]); if (!isset($parts[$i]) && $exists) { $alternatives[$collectionName] += $threshold; continue; } elseif (!isset($parts[$i])) { continue; } $lev = levenshtein($subname, $parts[$i]); if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) { $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; } elseif ($exists) { $alternatives[$collectionName] += $threshold; } } } foreach ($collection as $item) { $lev = levenshtein($name, $item); if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; } } $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); asort($alternatives); return array_keys($alternatives); } /** * Sets the default Command name. * * @param string $commandName The Command name */ public function setDefaultCommand($commandName) { $this->defaultCommand = $commandName; } private function stringWidth($string) { if (!function_exists('mb_strwidth')) { return strlen($string); } if (false === $encoding = mb_detect_encoding($string)) { return strlen($string); } return mb_strwidth($string, $encoding); } private function splitStringByWidth($string, $width) { // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly. // additionally, array_slice() is not enough as some character has doubled width. // we need a function to split string not by character count but by string width if (!function_exists('mb_strwidth')) { return str_split($string, $width); } if (false === $encoding = mb_detect_encoding($string)) { return str_split($string, $width); } $utf8String = mb_convert_encoding($string, 'utf8', $encoding); $lines = array(); $line = ''; foreach (preg_split('//u', $utf8String) as $char) { // test if $char could be appended to current line if (mb_strwidth($line.$char, 'utf8') <= $width) { $line .= $char; continue; } // if not, push current line to array and make new line $lines[] = str_pad($line, $width); $line = $char; } if ('' !== $line) { $lines[] = count($lines) ? str_pad($line, $width) : $line; } mb_convert_variables($encoding, 'utf8', $lines); return $lines; } /** * Returns all namespaces of the command name. * * @param string $name The full name of the command * * @return array The namespaces of the command */ private function extractAllNamespaces($name) { // -1 as third argument is needed to skip the command short name when exploding $parts = explode(':', $name, -1); $namespaces = array(); foreach ($parts as $part) { if (count($namespaces)) { $namespaces[] = end($namespaces).':'.$part; } else { $namespaces[] = $part; } } return $namespaces; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console; use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\Process\ProcessBuilder; use Symfony\Component\Process\PhpExecutableFinder; /** * A Shell wraps an Application to add shell capabilities to it. * * Support for history and completion only works with a PHP compiled * with readline support (either --with-readline or --with-libedit) * * @author Fabien Potencier * @author Martin Hasoň */ class Shell { private $application; private $history; private $output; private $hasReadline; private $processIsolation = false; /** * Constructor. * * If there is no readline support for the current PHP executable * a \RuntimeException exception is thrown. * * @param Application $application An application instance */ public function __construct(Application $application) { $this->hasReadline = function_exists('readline'); $this->application = $application; $this->history = getenv('HOME').'/.history_'.$application->getName(); $this->output = new ConsoleOutput(); } /** * Runs the shell. */ public function run() { $this->application->setAutoExit(false); $this->application->setCatchExceptions(true); if ($this->hasReadline) { readline_read_history($this->history); readline_completion_function(array($this, 'autocompleter')); } $this->output->writeln($this->getHeader()); $php = null; if ($this->processIsolation) { $finder = new PhpExecutableFinder(); $php = $finder->find(); $this->output->writeln(<<Running with process isolation, you should consider this: * each command is executed as separate process, * commands don't support interactivity, all params must be passed explicitly, * commands output is not colorized. EOF ); } while (true) { $command = $this->readline(); if (false === $command) { $this->output->writeln("\n"); break; } if ($this->hasReadline) { readline_add_history($command); readline_write_history($this->history); } if ($this->processIsolation) { $pb = new ProcessBuilder(); $process = $pb ->add($php) ->add($_SERVER['argv'][0]) ->add($command) ->inheritEnvironmentVariables(true) ->getProcess() ; $output = $this->output; $process->run(function ($type, $data) use ($output) { $output->writeln($data); }); $ret = $process->getExitCode(); } else { $ret = $this->application->run(new StringInput($command), $this->output); } if (0 !== $ret) { $this->output->writeln(sprintf('The command terminated with an error status (%s)', $ret)); } } } /** * Returns the shell header. * * @return string The header string */ protected function getHeader() { return <<{$this->application->getName()} shell ({$this->application->getVersion()}). At the prompt, type help for some help, or list to get a list of available commands. To exit the shell, type ^D. EOF; } /** * Renders a prompt. * * @return string The prompt */ protected function getPrompt() { // using the formatter here is required when using readline return $this->output->getFormatter()->format($this->application->getName().' > '); } protected function getOutput() { return $this->output; } protected function getApplication() { return $this->application; } /** * Tries to return autocompletion for the current entered text. * * @param string $text The last segment of the entered text * * @return bool|array A list of guessed strings or true */ private function autocompleter($text) { $info = readline_info(); $text = substr($info['line_buffer'], 0, $info['end']); if ($info['point'] !== $info['end']) { return true; } // task name? if (false === strpos($text, ' ') || !$text) { return array_keys($this->application->all()); } // options and arguments? try { $command = $this->application->find(substr($text, 0, strpos($text, ' '))); } catch (\Exception $e) { return true; } $list = array('--help'); foreach ($command->getDefinition()->getOptions() as $option) { $list[] = '--'.$option->getName(); } return $list; } /** * Reads a single line from standard input. * * @return string The single line from standard input */ private function readline() { if ($this->hasReadline) { $line = readline($this->getPrompt()); } else { $this->output->write($this->getPrompt()); $line = fgets(STDIN, 1024); $line = (false === $line || '' === $line) ? false : rtrim($line); } return $line; } public function getProcessIsolation() { return $this->processIsolation; } public function setProcessIsolation($processIsolation) { $this->processIsolation = (bool) $processIsolation; if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) { throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.'); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * @author Jean-François Simon */ class OutputFormatterStyleStack { /** * @var OutputFormatterStyleInterface[] */ private $styles; /** * @var OutputFormatterStyleInterface */ private $emptyStyle; /** * Constructor. * * @param OutputFormatterStyleInterface|null $emptyStyle */ public function __construct(OutputFormatterStyleInterface $emptyStyle = null) { $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); $this->reset(); } /** * Resets stack (ie. empty internal arrays). */ public function reset() { $this->styles = array(); } /** * Pushes a style in the stack. * * @param OutputFormatterStyleInterface $style */ public function push(OutputFormatterStyleInterface $style) { $this->styles[] = $style; } /** * Pops a style from the stack. * * @param OutputFormatterStyleInterface|null $style * * @return OutputFormatterStyleInterface * * @throws \InvalidArgumentException When style tags incorrectly nested */ public function pop(OutputFormatterStyleInterface $style = null) { if (empty($this->styles)) { return $this->emptyStyle; } if (null === $style) { return array_pop($this->styles); } foreach (array_reverse($this->styles, true) as $index => $stackedStyle) { if ($style->apply('') === $stackedStyle->apply('')) { $this->styles = array_slice($this->styles, 0, $index); return $stackedStyle; } } throw new \InvalidArgumentException('Incorrectly nested style tag found.'); } /** * Computes current style with stacks top codes. * * @return OutputFormatterStyle */ public function getCurrent() { if (empty($this->styles)) { return $this->emptyStyle; } return $this->styles[count($this->styles) - 1]; } /** * @param OutputFormatterStyleInterface $emptyStyle * * @return OutputFormatterStyleStack */ public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle) { $this->emptyStyle = $emptyStyle; return $this; } /** * @return OutputFormatterStyleInterface */ public function getEmptyStyle() { return $this->emptyStyle; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter interface for console output. * * @author Konstantin Kudryashov * * @api */ interface OutputFormatterInterface { /** * Sets the decorated flag. * * @param bool $decorated Whether to decorate the messages or not * * @api */ public function setDecorated($decorated); /** * Gets the decorated flag. * * @return bool true if the output will decorate messages, false otherwise * * @api */ public function isDecorated(); /** * Sets a new style. * * @param string $name The style name * @param OutputFormatterStyleInterface $style The style instance * * @api */ public function setStyle($name, OutputFormatterStyleInterface $style); /** * Checks if output formatter has style with specified name. * * @param string $name * * @return bool * * @api */ public function hasStyle($name); /** * Gets style options from style with specified name. * * @param string $name * * @return OutputFormatterStyleInterface * * @api */ public function getStyle($name); /** * Formats a message according to the given styles. * * @param string $message The message to style * * @return string The styled message * * @api */ public function format($message); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter class for console output. * * @author Konstantin Kudryashov * * @api */ class OutputFormatter implements OutputFormatterInterface { private $decorated; private $styles = array(); private $styleStack; /** * Escapes "<" special char in given text. * * @param string $text Text to escape * * @return string Escaped text */ public static function escape($text) { return preg_replace('/([^\\\\]?) FormatterStyle" instances * * @api */ public function __construct($decorated = false, array $styles = array()) { $this->decorated = (bool) $decorated; $this->setStyle('error', new OutputFormatterStyle('white', 'red')); $this->setStyle('info', new OutputFormatterStyle('green')); $this->setStyle('comment', new OutputFormatterStyle('yellow')); $this->setStyle('question', new OutputFormatterStyle('black', 'cyan')); foreach ($styles as $name => $style) { $this->setStyle($name, $style); } $this->styleStack = new OutputFormatterStyleStack(); } /** * Sets the decorated flag. * * @param bool $decorated Whether to decorate the messages or not * * @api */ public function setDecorated($decorated) { $this->decorated = (bool) $decorated; } /** * Gets the decorated flag. * * @return bool true if the output will decorate messages, false otherwise * * @api */ public function isDecorated() { return $this->decorated; } /** * Sets a new style. * * @param string $name The style name * @param OutputFormatterStyleInterface $style The style instance * * @api */ public function setStyle($name, OutputFormatterStyleInterface $style) { $this->styles[strtolower($name)] = $style; } /** * Checks if output formatter has style with specified name. * * @param string $name * * @return bool * * @api */ public function hasStyle($name) { return isset($this->styles[strtolower($name)]); } /** * Gets style options from style with specified name. * * @param string $name * * @return OutputFormatterStyleInterface * * @throws \InvalidArgumentException When style isn't defined * * @api */ public function getStyle($name) { if (!$this->hasStyle($name)) { throw new \InvalidArgumentException(sprintf('Undefined style: %s', $name)); } return $this->styles[strtolower($name)]; } /** * Formats a message according to the given styles. * * @param string $message The message to style * * @return string The styled message * * @api */ public function format($message) { $message = (string) $message; $offset = 0; $output = ''; $tagRegex = '[a-z][a-z0-9_=;-]*'; preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE); foreach ($matches[0] as $i => $match) { $pos = $match[1]; $text = $match[0]; if (0 != $pos && '\\' == $message[$pos - 1]) { continue; } // add the text up to the next tag $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset)); $offset = $pos + strlen($text); // opening tag? if ($open = '/' != $text[1]) { $tag = $matches[1][$i][0]; } else { $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : ''; } if (!$open && !$tag) { // $this->styleStack->pop(); } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) { $output .= $this->applyCurrentStyle($text); } elseif ($open) { $this->styleStack->push($style); } else { $this->styleStack->pop($style); } } $output .= $this->applyCurrentStyle(substr($message, $offset)); return str_replace('\\<', '<', $output); } /** * @return OutputFormatterStyleStack */ public function getStyleStack() { return $this->styleStack; } /** * Tries to create new style instance from string. * * @param string $string * * @return OutputFormatterStyle|bool false if string is not format string */ private function createStyleFromString($string) { if (isset($this->styles[$string])) { return $this->styles[$string]; } if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) { return false; } $style = new OutputFormatterStyle(); foreach ($matches as $match) { array_shift($match); if ('fg' == $match[0]) { $style->setForeground($match[1]); } elseif ('bg' == $match[0]) { $style->setBackground($match[1]); } else { try { $style->setOption($match[1]); } catch (\InvalidArgumentException $e) { return false; } } } return $style; } /** * Applies current style from stack to text, if must be applied. * * @param string $text Input text * * @return string Styled text */ private function applyCurrentStyle($text) { return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter style interface for defining styles. * * @author Konstantin Kudryashov * * @api */ interface OutputFormatterStyleInterface { /** * Sets style foreground color. * * @param string $color The color name * * @api */ public function setForeground($color = null); /** * Sets style background color. * * @param string $color The color name * * @api */ public function setBackground($color = null); /** * Sets some specific style option. * * @param string $option The option name * * @api */ public function setOption($option); /** * Unsets some specific style option. * * @param string $option The option name */ public function unsetOption($option); /** * Sets multiple style options at once. * * @param array $options */ public function setOptions(array $options); /** * Applies the style to a given text. * * @param string $text The text to style * * @return string */ public function apply($text); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Console\Formatter; /** * Formatter style class for defining styles. * * @author Konstantin Kudryashov * * @api */ class OutputFormatterStyle implements OutputFormatterStyleInterface { private static $availableForegroundColors = array( 'black' => array('set' => 30, 'unset' => 39), 'red' => array('set' => 31, 'unset' => 39), 'green' => array('set' => 32, 'unset' => 39), 'yellow' => array('set' => 33, 'unset' => 39), 'blue' => array('set' => 34, 'unset' => 39), 'magenta' => array('set' => 35, 'unset' => 39), 'cyan' => array('set' => 36, 'unset' => 39), 'white' => array('set' => 37, 'unset' => 39), 'default' => array('set' => 39, 'unset' => 39), ); private static $availableBackgroundColors = array( 'black' => array('set' => 40, 'unset' => 49), 'red' => array('set' => 41, 'unset' => 49), 'green' => array('set' => 42, 'unset' => 49), 'yellow' => array('set' => 43, 'unset' => 49), 'blue' => array('set' => 44, 'unset' => 49), 'magenta' => array('set' => 45, 'unset' => 49), 'cyan' => array('set' => 46, 'unset' => 49), 'white' => array('set' => 47, 'unset' => 49), 'default' => array('set' => 49, 'unset' => 49), ); private static $availableOptions = array( 'bold' => array('set' => 1, 'unset' => 22), 'underscore' => array('set' => 4, 'unset' => 24), 'blink' => array('set' => 5, 'unset' => 25), 'reverse' => array('set' => 7, 'unset' => 27), 'conceal' => array('set' => 8, 'unset' => 28), ); private $foreground; private $background; private $options = array(); /** * Initializes output formatter style. * * @param string|null $foreground The style foreground color name * @param string|null $background The style background color name * @param array $options The style options * * @api */ public function __construct($foreground = null, $background = null, array $options = array()) { if (null !== $foreground) { $this->setForeground($foreground); } if (null !== $background) { $this->setBackground($background); } if (count($options)) { $this->setOptions($options); } } /** * Sets style foreground color. * * @param string|null $color The color name * * @throws \InvalidArgumentException When the color name isn't defined * * @api */ public function setForeground($color = null) { if (null === $color) { $this->foreground = null; return; } if (!isset(static::$availableForegroundColors[$color])) { throw new \InvalidArgumentException(sprintf( 'Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors)) )); } $this->foreground = static::$availableForegroundColors[$color]; } /** * Sets style background color. * * @param string|null $color The color name * * @throws \InvalidArgumentException When the color name isn't defined * * @api */ public function setBackground($color = null) { if (null === $color) { $this->background = null; return; } if (!isset(static::$availableBackgroundColors[$color])) { throw new \InvalidArgumentException(sprintf( 'Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors)) )); } $this->background = static::$availableBackgroundColors[$color]; } /** * Sets some specific style option. * * @param string $option The option name * * @throws \InvalidArgumentException When the option name isn't defined * * @api */ public function setOption($option) { if (!isset(static::$availableOptions[$option])) { throw new \InvalidArgumentException(sprintf( 'Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)) )); } if (!in_array(static::$availableOptions[$option], $this->options)) { $this->options[] = static::$availableOptions[$option]; } } /** * Unsets some specific style option. * * @param string $option The option name * * @throws \InvalidArgumentException When the option name isn't defined */ public function unsetOption($option) { if (!isset(static::$availableOptions[$option])) { throw new \InvalidArgumentException(sprintf( 'Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)) )); } $pos = array_search(static::$availableOptions[$option], $this->options); if (false !== $pos) { unset($this->options[$pos]); } } /** * Sets multiple style options at once. * * @param array $options */ public function setOptions(array $options) { $this->options = array(); foreach ($options as $option) { $this->setOption($option); } } /** * Applies the style to a given text. * * @param string $text The text to style * * @return string */ public function apply($text) { $setCodes = array(); $unsetCodes = array(); if (null !== $this->foreground) { $setCodes[] = $this->foreground['set']; $unsetCodes[] = $this->foreground['unset']; } if (null !== $this->background) { $setCodes[] = $this->background['set']; $unsetCodes[] = $this->background['unset']; } if (count($this->options)) { foreach ($this->options as $option) { $setCodes[] = $option['set']; $unsetCodes[] = $option['unset']; } } if (0 === count($setCodes)) { return $text; } return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; /** * Represents an already parsed expression. * * @author Fabien Potencier */ class SerializedParsedExpression extends ParsedExpression { private $nodes; /** * Constructor. * * @param string $expression An expression * @param string $nodes The serialized nodes for the expression */ public function __construct($expression, $nodes) { $this->expression = (string) $expression; $this->nodes = $nodes; } public function getNodes() { return unserialize($this->nodes); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; /** * @author Fabien Potencier */ interface ExpressionFunctionProviderInterface { /** * @return ExpressionFunction[] An array of Function instances */ public function getFunctions(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; /** * Compiles a node to PHP code. * * @author Fabien Potencier */ class Compiler { private $source; private $functions; public function __construct(array $functions) { $this->functions = $functions; } public function getFunction($name) { return $this->functions[$name]; } /** * Gets the current PHP code after compilation. * * @return string The PHP code */ public function getSource() { return $this->source; } public function reset() { $this->source = ''; return $this; } /** * Compiles a node. * * @param Node\Node $node The node to compile * * @return Compiler The current compiler instance */ public function compile(Node\Node $node) { $node->compile($this); return $this; } public function subcompile(Node\Node $node) { $current = $this->source; $this->source = ''; $node->compile($this); $source = $this->source; $this->source = $current; return $source; } /** * Adds a raw string to the compiled code. * * @param string $string The string * * @return Compiler The current compiler instance */ public function raw($string) { $this->source .= $string; return $this; } /** * Adds a quoted string to the compiled code. * * @param string $value The string * * @return Compiler The current compiler instance */ public function string($value) { $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\")); return $this; } /** * Returns a PHP representation of a given value. * * @param mixed $value The value to convert * * @return Compiler The current compiler instance */ public function repr($value) { if (is_int($value) || is_float($value)) { if (false !== $locale = setlocale(LC_NUMERIC, 0)) { setlocale(LC_NUMERIC, 'C'); } $this->raw($value); if (false !== $locale) { setlocale(LC_NUMERIC, $locale); } } elseif (null === $value) { $this->raw('null'); } elseif (is_bool($value)) { $this->raw($value ? 'true' : 'false'); } elseif (is_array($value)) { $this->raw('array('); $first = true; foreach ($value as $key => $value) { if (!$first) { $this->raw(', '); } $first = false; $this->repr($key); $this->raw(' => '); $this->repr($value); } $this->raw(')'); } else { $this->string($value); } return $this; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; class SyntaxError extends \LogicException { public function __construct($message, $cursor = 0) { parent::__construct(sprintf('%s around position %d.', $message, $cursor)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\Node; use Symfony\Component\ExpressionLanguage\Compiler; class NameNode extends Node { public function __construct($name) { parent::__construct( array(), array('name' => $name) ); } public function compile(Compiler $compiler) { $compiler->raw('$'.$this->attributes['name']); } public function evaluate($functions, $values) { return $values[$this->attributes['name']]; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\Node; use Symfony\Component\ExpressionLanguage\Compiler; class GetAttrNode extends Node { const PROPERTY_CALL = 1; const METHOD_CALL = 2; const ARRAY_CALL = 3; public function __construct(Node $node, Node $attribute, ArrayNode $arguments, $type) { parent::__construct( array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type) ); } public function compile(Compiler $compiler) { switch ($this->attributes['type']) { case self::PROPERTY_CALL: $compiler ->compile($this->nodes['node']) ->raw('->') ->raw($this->nodes['attribute']->attributes['value']) ; break; case self::METHOD_CALL: $compiler ->compile($this->nodes['node']) ->raw('->') ->raw($this->nodes['attribute']->attributes['value']) ->raw('(') ->compile($this->nodes['arguments']) ->raw(')') ; break; case self::ARRAY_CALL: $compiler ->compile($this->nodes['node']) ->raw('[') ->compile($this->nodes['attribute'])->raw(']') ; break; } } public function evaluate($functions, $values) { switch ($this->attributes['type']) { case self::PROPERTY_CALL: $obj = $this->nodes['node']->evaluate($functions, $values); if (!is_object($obj)) { throw new \RuntimeException('Unable to get a property on a non-object.'); } $property = $this->nodes['attribute']->attributes['value']; return $obj->$property; case self::METHOD_CALL: $obj = $this->nodes['node']->evaluate($functions, $values); if (!is_object($obj)) { throw new \RuntimeException('Unable to get a property on a non-object.'); } return call_user_func_array(array($obj, $this->nodes['attribute']->evaluate($functions, $values)), $this->nodes['arguments']->evaluate($functions, $values)); case self::ARRAY_CALL: $array = $this->nodes['node']->evaluate($functions, $values); if (!is_array($array) && !$array instanceof \ArrayAccess) { throw new \RuntimeException('Unable to get an item on a non-array.'); } return $array[$this->nodes['attribute']->evaluate($functions, $values)]; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\Node; use Symfony\Component\ExpressionLanguage\Compiler; class UnaryNode extends Node { private static $operators = array( '!' => '!', 'not' => '!', '+' => '+', '-' => '-', ); public function __construct($operator, Node $node) { parent::__construct( array('node' => $node), array('operator' => $operator) ); } public function compile(Compiler $compiler) { $compiler ->raw('(') ->raw(self::$operators[$this->attributes['operator']]) ->compile($this->nodes['node']) ->raw(')') ; } public function evaluate($functions, $values) { $value = $this->nodes['node']->evaluate($functions, $values); switch ($this->attributes['operator']) { case 'not': case '!': return !$value; case '-': return -$value; } return $value; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\Node; use Symfony\Component\ExpressionLanguage\Compiler; class ArgumentsNode extends ArrayNode { public function compile(Compiler $compiler) { $this->compileArguments($compiler, false); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\Node; use Symfony\Component\ExpressionLanguage\Compiler; class FunctionNode extends Node { public function __construct($name, Node $arguments) { parent::__construct( array('arguments' => $arguments), array('name' => $name) ); } public function compile(Compiler $compiler) { $arguments = array(); foreach ($this->nodes['arguments']->nodes as $node) { $arguments[] = $compiler->subcompile($node); } $function = $compiler->getFunction($this->attributes['name']); $compiler->raw(call_user_func_array($function['compiler'], $arguments)); } public function evaluate($functions, $values) { $arguments = array($values); foreach ($this->nodes['arguments']->nodes as $node) { $arguments[] = $node->evaluate($functions, $values); } return call_user_func_array($functions[$this->attributes['name']]['evaluator'], $arguments); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\Node; use Symfony\Component\ExpressionLanguage\Compiler; class ConstantNode extends Node { public function __construct($value) { parent::__construct( array(), array('value' => $value) ); } public function compile(Compiler $compiler) { $compiler->repr($this->attributes['value']); } public function evaluate($functions, $values) { return $this->attributes['value']; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\Node; use Symfony\Component\ExpressionLanguage\Compiler; class ArrayNode extends Node { protected $index; public function __construct() { $this->index = -1; } public function addElement(Node $value, Node $key = null) { if (null === $key) { $key = new ConstantNode(++$this->index); } array_push($this->nodes, $key, $value); } /** * Compiles the node to PHP. * * @param Compiler $compiler A Compiler instance */ public function compile(Compiler $compiler) { $compiler->raw('array('); $this->compileArguments($compiler); $compiler->raw(')'); } public function evaluate($functions, $values) { $result = array(); foreach ($this->getKeyValuePairs() as $pair) { $result[$pair['key']->evaluate($functions, $values)] = $pair['value']->evaluate($functions, $values); } return $result; } protected function getKeyValuePairs() { $pairs = array(); foreach (array_chunk($this->nodes, 2) as $pair) { $pairs[] = array('key' => $pair[0], 'value' => $pair[1]); } return $pairs; } protected function compileArguments(Compiler $compiler, $withKeys = true) { $first = true; foreach ($this->getKeyValuePairs() as $pair) { if (!$first) { $compiler->raw(', '); } $first = false; if ($withKeys) { $compiler ->compile($pair['key']) ->raw(' => ') ; } $compiler->compile($pair['value']); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\Node; use Symfony\Component\ExpressionLanguage\Compiler; /** * Represents a node in the AST. * * @author Fabien Potencier */ class Node { public $nodes = array(); public $attributes = array(); /** * Constructor. * * @param array $nodes An array of nodes * @param array $attributes An array of attributes */ public function __construct(array $nodes = array(), array $attributes = array()) { $this->nodes = $nodes; $this->attributes = $attributes; } public function __toString() { $attributes = array(); foreach ($this->attributes as $name => $value) { $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true))); } $repr = array(str_replace('Symfony\Component\ExpressionLanguage\Node\\', '', get_class($this)).'('.implode(', ', $attributes)); if (count($this->nodes)) { foreach ($this->nodes as $node) { foreach (explode("\n", (string) $node) as $line) { $repr[] = ' '.$line; } } $repr[] = ')'; } else { $repr[0] .= ')'; } return implode("\n", $repr); } public function compile(Compiler $compiler) { foreach ($this->nodes as $node) { $node->compile($compiler); } } public function evaluate($functions, $values) { $results = array(); foreach ($this->nodes as $node) { $results[] = $node->evaluate($functions, $values); } return $results; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\Node; use Symfony\Component\ExpressionLanguage\Compiler; class ConditionalNode extends Node { public function __construct(Node $expr1, Node $expr2, Node $expr3) { parent::__construct( array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3) ); } public function compile(Compiler $compiler) { $compiler ->raw('((') ->compile($this->nodes['expr1']) ->raw(') ? (') ->compile($this->nodes['expr2']) ->raw(') : (') ->compile($this->nodes['expr3']) ->raw('))') ; } public function evaluate($functions, $values) { if ($this->nodes['expr1']->evaluate($functions, $values)) { return $this->nodes['expr2']->evaluate($functions, $values); } return $this->nodes['expr3']->evaluate($functions, $values); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\Node; use Symfony\Component\ExpressionLanguage\Compiler; class BinaryNode extends Node { private static $operators = array( '~' => '.', 'and' => '&&', 'or' => '||', ); private static $functions = array( '**' => 'pow', '..' => 'range', 'in' => 'in_array', 'not in' => '!in_array', ); public function __construct($operator, Node $left, Node $right) { parent::__construct( array('left' => $left, 'right' => $right), array('operator' => $operator) ); } public function compile(Compiler $compiler) { $operator = $this->attributes['operator']; if ('matches' == $operator) { $compiler ->raw('preg_match(') ->compile($this->nodes['right']) ->raw(', ') ->compile($this->nodes['left']) ->raw(')') ; return; } if (isset(self::$functions[$operator])) { $compiler ->raw(sprintf('%s(', self::$functions[$operator])) ->compile($this->nodes['left']) ->raw(', ') ->compile($this->nodes['right']) ->raw(')') ; return; } if (isset(self::$operators[$operator])) { $operator = self::$operators[$operator]; } $compiler ->raw('(') ->compile($this->nodes['left']) ->raw(' ') ->raw($operator) ->raw(' ') ->compile($this->nodes['right']) ->raw(')') ; } public function evaluate($functions, $values) { $operator = $this->attributes['operator']; $left = $this->nodes['left']->evaluate($functions, $values); if (isset(self::$functions[$operator])) { $right = $this->nodes['right']->evaluate($functions, $values); if ('not in' === $operator) { return !in_array($left, $right); } $f = self::$functions[$operator]; return $f($left, $right); } switch ($operator) { case 'or': case '||': return $left || $this->nodes['right']->evaluate($functions, $values); case 'and': case '&&': return $left && $this->nodes['right']->evaluate($functions, $values); } $right = $this->nodes['right']->evaluate($functions, $values); switch ($operator) { case '|': return $left | $right; case '^': return $left ^ $right; case '&': return $left & $right; case '==': return $left == $right; case '===': return $left === $right; case '!=': return $left != $right; case '!==': return $left !== $right; case '<': return $left < $right; case '>': return $left > $right; case '>=': return $left >= $right; case '<=': return $left <= $right; case 'not in': return !in_array($left, $right); case 'in': return in_array($left, $right); case '+': return $left + $right; case '-': return $left - $right; case '~': return $left.$right; case '*': return $left * $right; case '/': return $left / $right; case '%': return $left % $right; case 'matches': return preg_match($right, $left); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; use Symfony\Component\ExpressionLanguage\Node\Node; /** * Represents an already parsed expression. * * @author Fabien Potencier */ class ParsedExpression extends Expression { private $nodes; /** * Constructor. * * @param string $expression An expression * @param Node $nodes A Node representing the expression */ public function __construct($expression, Node $nodes) { parent::__construct($expression); $this->nodes = $nodes; } public function getNodes() { return $this->nodes; } } ', '>=', '<=', 'not in', 'in', '..', '+', '-', '~', '*', '/', '%', 'matches', '**'); $operators = array_combine($operators, array_map('strlen', $operators)); arsort($operators); $regex = array(); foreach ($operators as $operator => $length) { // an operator that ends with a character must be followed by // a whitespace or a parenthesis $regex[] = preg_quote($operator, '/').(ctype_alpha($operator[$length - 1]) ? '(?=[\s(])' : ''); } echo '/'.implode('|', $regex).'/A'; * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; /** * Lexes an expression. * * @author Fabien Potencier */ class Lexer { /** * Tokenizes an expression. * * @param string $expression The expression to tokenize * * @return TokenStream A token stream instance * * @throws SyntaxError */ public function tokenize($expression) { $expression = str_replace(array("\r", "\n", "\t", "\v", "\f"), ' ', $expression); $cursor = 0; $tokens = array(); $brackets = array(); $end = strlen($expression); while ($cursor < $end) { if (' ' == $expression[$cursor]) { ++$cursor; continue; } if (preg_match('/[0-9]+(?:\.[0-9]+)?/A', $expression, $match, null, $cursor)) { // numbers $number = (float) $match[0]; // floats if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) { $number = (int) $match[0]; // integers lower than the maximum } $tokens[] = new Token(Token::NUMBER_TYPE, $number, $cursor + 1); $cursor += strlen($match[0]); } elseif (false !== strpos('([{', $expression[$cursor])) { // opening bracket $brackets[] = array($expression[$cursor], $cursor); $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); ++$cursor; } elseif (false !== strpos(')]}', $expression[$cursor])) { // closing bracket if (empty($brackets)) { throw new SyntaxError(sprintf('Unexpected "%s"', $expression[$cursor]), $cursor); } list($expect, $cur) = array_pop($brackets); if ($expression[$cursor] != strtr($expect, '([{', ')]}')) { throw new SyntaxError(sprintf('Unclosed "%s"', $expect), $cur); } $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); ++$cursor; } elseif (preg_match('/"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As', $expression, $match, null, $cursor)) { // strings $tokens[] = new Token(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)), $cursor + 1); $cursor += strlen($match[0]); } elseif (preg_match('/not in(?=[\s(])|\!\=\=|not(?=[\s(])|and(?=[\s(])|\=\=\=|\>\=|or(?=[\s(])|\<\=|\*\*|\.\.|in(?=[\s(])|&&|\|\||matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, null, $cursor)) { // operators $tokens[] = new Token(Token::OPERATOR_TYPE, $match[0], $cursor + 1); $cursor += strlen($match[0]); } elseif (false !== strpos('.,?:', $expression[$cursor])) { // punctuation $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); ++$cursor; } elseif (preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $expression, $match, null, $cursor)) { // names $tokens[] = new Token(Token::NAME_TYPE, $match[0], $cursor + 1); $cursor += strlen($match[0]); } else { // unlexable throw new SyntaxError(sprintf('Unexpected character "%s"', $expression[$cursor]), $cursor); } } $tokens[] = new Token(Token::EOF_TYPE, null, $cursor + 1); if (!empty($brackets)) { list($expect, $cur) = array_pop($brackets); throw new SyntaxError(sprintf('Unclosed "%s"', $expect), $cur); } return new TokenStream($tokens); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\ParserCache; use Symfony\Component\ExpressionLanguage\ParsedExpression; /** * @author Adrien Brault */ interface ParserCacheInterface { /** * Saves an expression in the cache. * * @param string $key The cache key * @param ParsedExpression $expression A ParsedExpression instance to store in the cache */ public function save($key, ParsedExpression $expression); /** * Fetches an expression from the cache. * * @param string $key The cache key * * @return ParsedExpression|null */ public function fetch($key); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage\ParserCache; use Symfony\Component\ExpressionLanguage\ParsedExpression; /** * @author Adrien Brault */ class ArrayParserCache implements ParserCacheInterface { /** * @var array */ private $cache = array(); /** * {@inheritdoc} */ public function fetch($key) { return isset($this->cache[$key]) ? $this->cache[$key] : null; } /** * {@inheritdoc} */ public function save($key, ParsedExpression $expression) { $this->cache[$key] = $expression; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; /** * Parsers a token stream. * * 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 * * @author Fabien Potencier */ class Parser { const OPERATOR_LEFT = 1; const OPERATOR_RIGHT = 2; private $stream; private $unaryOperators; private $binaryOperators; private $functions; private $names; public function __construct(array $functions) { $this->functions = $functions; $this->unaryOperators = array( 'not' => array('precedence' => 50), '!' => array('precedence' => 50), '-' => array('precedence' => 500), '+' => array('precedence' => 500), ); $this->binaryOperators = array( 'or' => array('precedence' => 10, 'associativity' => Parser::OPERATOR_LEFT), '||' => array('precedence' => 10, 'associativity' => Parser::OPERATOR_LEFT), 'and' => array('precedence' => 15, 'associativity' => Parser::OPERATOR_LEFT), '&&' => array('precedence' => 15, 'associativity' => Parser::OPERATOR_LEFT), '|' => array('precedence' => 16, 'associativity' => Parser::OPERATOR_LEFT), '^' => array('precedence' => 17, 'associativity' => Parser::OPERATOR_LEFT), '&' => array('precedence' => 18, 'associativity' => Parser::OPERATOR_LEFT), '==' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), '===' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), '!=' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), '!==' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), '<' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), '>' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), '>=' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), '<=' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), 'not in' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), 'in' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), 'matches' => array('precedence' => 20, 'associativity' => Parser::OPERATOR_LEFT), '..' => array('precedence' => 25, 'associativity' => Parser::OPERATOR_LEFT), '+' => array('precedence' => 30, 'associativity' => Parser::OPERATOR_LEFT), '-' => array('precedence' => 30, 'associativity' => Parser::OPERATOR_LEFT), '~' => array('precedence' => 40, 'associativity' => Parser::OPERATOR_LEFT), '*' => array('precedence' => 60, 'associativity' => Parser::OPERATOR_LEFT), '/' => array('precedence' => 60, 'associativity' => Parser::OPERATOR_LEFT), '%' => array('precedence' => 60, 'associativity' => Parser::OPERATOR_LEFT), '**' => array('precedence' => 200, 'associativity' => Parser::OPERATOR_RIGHT), ); } /** * Converts a token stream to a node tree. * * The valid names is an array where the values * are the names that the user can use in an expression. * * If the variable name in the compiled PHP code must be * different, define it as the key. * * For instance, ['this' => 'container'] means that the * variable 'container' can be used in the expression * but the compiled code will use 'this'. * * @param TokenStream $stream A token stream instance * @param array $names An array of valid names * * @return Node A node tree * * @throws SyntaxError */ public function parse(TokenStream $stream, $names = array()) { $this->stream = $stream; $this->names = $names; $node = $this->parseExpression(); if (!$stream->isEOF()) { throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s"', $stream->current->type, $stream->current->value), $stream->current->cursor); } return $node; } public function parseExpression($precedence = 0) { $expr = $this->getPrimary(); $token = $this->stream->current; while ($token->test(Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->value]) && $this->binaryOperators[$token->value]['precedence'] >= $precedence) { $op = $this->binaryOperators[$token->value]; $this->stream->next(); $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']); $expr = new Node\BinaryNode($token->value, $expr, $expr1); $token = $this->stream->current; } if (0 === $precedence) { return $this->parseConditionalExpression($expr); } return $expr; } protected function getPrimary() { $token = $this->stream->current; if ($token->test(Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->value])) { $operator = $this->unaryOperators[$token->value]; $this->stream->next(); $expr = $this->parseExpression($operator['precedence']); return $this->parsePostfixExpression(new Node\UnaryNode($token->value, $expr)); } if ($token->test(Token::PUNCTUATION_TYPE, '(')) { $this->stream->next(); $expr = $this->parseExpression(); $this->stream->expect(Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed'); return $this->parsePostfixExpression($expr); } return $this->parsePrimaryExpression(); } protected function parseConditionalExpression($expr) { while ($this->stream->current->test(Token::PUNCTUATION_TYPE, '?')) { $this->stream->next(); if (!$this->stream->current->test(Token::PUNCTUATION_TYPE, ':')) { $expr2 = $this->parseExpression(); if ($this->stream->current->test(Token::PUNCTUATION_TYPE, ':')) { $this->stream->next(); $expr3 = $this->parseExpression(); } else { $expr3 = new Node\ConstantNode(null); } } else { $this->stream->next(); $expr2 = $expr; $expr3 = $this->parseExpression(); } $expr = new Node\ConditionalNode($expr, $expr2, $expr3); } return $expr; } public function parsePrimaryExpression() { $token = $this->stream->current; switch ($token->type) { case Token::NAME_TYPE: $this->stream->next(); switch ($token->value) { case 'true': case 'TRUE': return new Node\ConstantNode(true); case 'false': case 'FALSE': return new Node\ConstantNode(false); case 'null': case 'NULL': return new Node\ConstantNode(null); default: if ('(' === $this->stream->current->value) { if (false === isset($this->functions[$token->value])) { throw new SyntaxError(sprintf('The function "%s" does not exist', $token->value), $token->cursor); } $node = new Node\FunctionNode($token->value, $this->parseArguments()); } else { if (!in_array($token->value, $this->names, true)) { throw new SyntaxError(sprintf('Variable "%s" is not valid', $token->value), $token->cursor); } // is the name used in the compiled code different // from the name used in the expression? if (is_int($name = array_search($token->value, $this->names))) { $name = $token->value; } $node = new Node\NameNode($name); } } break; case Token::NUMBER_TYPE: case Token::STRING_TYPE: $this->stream->next(); return new Node\ConstantNode($token->value); default: if ($token->test(Token::PUNCTUATION_TYPE, '[')) { $node = $this->parseArrayExpression(); } elseif ($token->test(Token::PUNCTUATION_TYPE, '{')) { $node = $this->parseHashExpression(); } else { throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s"', $token->type, $token->value), $token->cursor); } } return $this->parsePostfixExpression($node); } public function parseArrayExpression() { $this->stream->expect(Token::PUNCTUATION_TYPE, '[', 'An array element was expected'); $node = new Node\ArrayNode(); $first = true; while (!$this->stream->current->test(Token::PUNCTUATION_TYPE, ']')) { if (!$first) { $this->stream->expect(Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma'); // trailing ,? if ($this->stream->current->test(Token::PUNCTUATION_TYPE, ']')) { break; } } $first = false; $node->addElement($this->parseExpression()); } $this->stream->expect(Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed'); return $node; } public function parseHashExpression() { $this->stream->expect(Token::PUNCTUATION_TYPE, '{', 'A hash element was expected'); $node = new Node\ArrayNode(); $first = true; while (!$this->stream->current->test(Token::PUNCTUATION_TYPE, '}')) { if (!$first) { $this->stream->expect(Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma'); // trailing ,? if ($this->stream->current->test(Token::PUNCTUATION_TYPE, '}')) { break; } } $first = false; // a hash key can be: // // * a number -- 12 // * a string -- 'a' // * a name, which is equivalent to a string -- a // * an expression, which must be enclosed in parentheses -- (1 + 2) if ($this->stream->current->test(Token::STRING_TYPE) || $this->stream->current->test(Token::NAME_TYPE) || $this->stream->current->test(Token::NUMBER_TYPE)) { $key = new Node\ConstantNode($this->stream->current->value); $this->stream->next(); } elseif ($this->stream->current->test(Token::PUNCTUATION_TYPE, '(')) { $key = $this->parseExpression(); } else { $current = $this->stream->current; 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"', $current->type, $current->value), $current->cursor); } $this->stream->expect(Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); $value = $this->parseExpression(); $node->addElement($value, $key); } $this->stream->expect(Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed'); return $node; } public function parsePostfixExpression($node) { $token = $this->stream->current; while ($token->type == Token::PUNCTUATION_TYPE) { if ('.' === $token->value) { $this->stream->next(); $token = $this->stream->current; $this->stream->next(); if ( $token->type !== Token::NAME_TYPE && // Operators like "not" and "matches" are valid method or property names, // // In other words, besides NAME_TYPE, OPERATOR_TYPE could also be parsed as a property or method. // This is because operators are processed by the lexer prior to names. So "not" in "foo.not()" or "matches" in "foo.matches" will be recognized as an operator first. // But in fact, "not" and "matches" in such expressions shall be parsed as method or property names. // // And this ONLY works if the operator consists of valid characters for a property or method name. // // Other types, such as STRING_TYPE and NUMBER_TYPE, can't be parsed as property nor method names. // // As a result, if $token is NOT an operator OR $token->value is NOT a valid property or method name, an exception shall be thrown. ($token->type !== Token::OPERATOR_TYPE || !preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value)) ) { throw new SyntaxError('Expected name', $token->cursor); } $arg = new Node\ConstantNode($token->value); $arguments = new Node\ArgumentsNode(); if ($this->stream->current->test(Token::PUNCTUATION_TYPE, '(')) { $type = Node\GetAttrNode::METHOD_CALL; foreach ($this->parseArguments()->nodes as $n) { $arguments->addElement($n); } } else { $type = Node\GetAttrNode::PROPERTY_CALL; } $node = new Node\GetAttrNode($node, $arg, $arguments, $type); } elseif ('[' === $token->value) { if ($node instanceof Node\GetAttrNode && Node\GetAttrNode::METHOD_CALL === $node->attributes['type'] && PHP_VERSION_ID < 50400) { throw new SyntaxError('Array calls on a method call is only supported on PHP 5.4+', $token->cursor); } $this->stream->next(); $arg = $this->parseExpression(); $this->stream->expect(Token::PUNCTUATION_TYPE, ']'); $node = new Node\GetAttrNode($node, $arg, new Node\ArgumentsNode(), Node\GetAttrNode::ARRAY_CALL); } else { break; } $token = $this->stream->current; } return $node; } /** * Parses arguments. */ public function parseArguments() { $args = array(); $this->stream->expect(Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); while (!$this->stream->current->test(Token::PUNCTUATION_TYPE, ')')) { if (!empty($args)) { $this->stream->expect(Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); } $args[] = $this->parseExpression(); } $this->stream->expect(Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); return new Node\Node($args); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; /** * Represents a token stream. * * @author Fabien Potencier */ class TokenStream { public $current; private $tokens; private $position = 0; /** * Constructor. * * @param array $tokens An array of tokens */ public function __construct(array $tokens) { $this->tokens = $tokens; $this->current = $tokens[0]; } /** * Returns a string representation of the token stream. * * @return string */ public function __toString() { return implode("\n", $this->tokens); } /** * Sets the pointer to the next token and returns the old one. */ public function next() { if (!isset($this->tokens[$this->position])) { throw new SyntaxError('Unexpected end of expression', $this->current->cursor); } ++$this->position; $this->current = $this->tokens[$this->position]; } /** * Tests a token. */ public function expect($type, $value = null, $message = null) { $token = $this->current; if (!$token->test($type, $value)) { throw new SyntaxError(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s)', $message ? $message.'. ' : '', $token->type, $token->value, $type, $value ? sprintf(' with value "%s"', $value) : ''), $token->cursor); } $this->next(); } /** * Checks if end of stream was reached * * @return bool */ public function isEOF() { return $this->current->type === Token::EOF_TYPE; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; /** * Represents a function that can be used in an expression. * * A function is defined by two PHP callables. The callables are used * by the language to compile and/or evaluate the function. * * The "compiler" function is used at compilation time and must return a * PHP representation of the function call (it receives the function * arguments as arguments). * * The "evaluator" function is used for expression evaluation and must return * the value of the function call based on the values defined for the * expression (it receives the values as a first argument and the function * arguments as remaining arguments). * * @author Fabien Potencier */ class ExpressionFunction { private $name; private $compiler; private $evaluator; /** * Constructor. * * @param string $name The function name * @param callable $compiler A callable able to compile the function * @param callable $evaluator A callable able to evaluate the function */ public function __construct($name, $compiler, $evaluator) { $this->name = $name; $this->compiler = $compiler; $this->evaluator = $evaluator; } public function getName() { return $this->name; } public function getCompiler() { return $this->compiler; } public function getEvaluator() { return $this->evaluator; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; /** * Represents a Token. * * @author Fabien Potencier */ class Token { public $value; public $type; public $cursor; const EOF_TYPE = 'end of expression'; const NAME_TYPE = 'name'; const NUMBER_TYPE = 'number'; const STRING_TYPE = 'string'; const OPERATOR_TYPE = 'operator'; const PUNCTUATION_TYPE = 'punctuation'; /** * Constructor. * * @param int $type The type of the token * @param string $value The token value * @param int $cursor The cursor position in the source */ public function __construct($type, $value, $cursor) { $this->type = $type; $this->value = $value; $this->cursor = $cursor; } /** * Returns a string representation of the token. * * @return string A string representation of the token */ public function __toString() { return sprintf('%3d %-11s %s', $this->cursor, strtoupper($this->type), $this->value); } /** * Tests the current token for a type and/or a value. * * @param array|int $type The type to test * @param string|null $value The token value * * @return bool */ public function test($type, $value = null) { return $this->type === $type && (null === $value || $this->value == $value); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; /** * Represents an expression. * * @author Fabien Potencier */ class Expression { protected $expression; /** * Constructor. * * @param string $expression An expression */ public function __construct($expression) { $this->expression = (string) $expression; } /** * Gets the expression. * * @return string The expression */ public function __toString() { return $this->expression; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ExpressionLanguage; use Symfony\Component\ExpressionLanguage\ParserCache\ArrayParserCache; use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface; /** * Allows to compile and evaluate expressions written in your own DSL. * * @author Fabien Potencier */ class ExpressionLanguage { /** * @var ParserCacheInterface */ private $cache; private $lexer; private $parser; private $compiler; protected $functions = array(); /** * @param ParserCacheInterface $cache * @param ExpressionFunctionProviderInterface[] $providers */ public function __construct(ParserCacheInterface $cache = null, array $providers = array()) { $this->cache = $cache ?: new ArrayParserCache(); $this->registerFunctions(); foreach ($providers as $provider) { $this->registerProvider($provider); } } /** * Compiles an expression source code. * * @param Expression|string $expression The expression to compile * @param array $names An array of valid names * * @return string The compiled PHP source code */ public function compile($expression, $names = array()) { return $this->getCompiler()->compile($this->parse($expression, $names)->getNodes())->getSource(); } /** * Evaluate an expression. * * @param Expression|string $expression The expression to compile * @param array $values An array of values * * @return string The result of the evaluation of the expression */ public function evaluate($expression, $values = array()) { return $this->parse($expression, array_keys($values))->getNodes()->evaluate($this->functions, $values); } /** * Parses an expression. * * @param Expression|string $expression The expression to parse * @param array $names An array of valid names * * @return ParsedExpression A ParsedExpression instance */ public function parse($expression, $names) { if ($expression instanceof ParsedExpression) { return $expression; } $key = $expression.'//'.implode('-', $names); if (null === $parsedExpression = $this->cache->fetch($key)) { $nodes = $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names); $parsedExpression = new ParsedExpression((string) $expression, $nodes); $this->cache->save($key, $parsedExpression); } return $parsedExpression; } /** * Registers a function. * * @param string $name The function name * @param callable $compiler A callable able to compile the function * @param callable $evaluator A callable able to evaluate the function * * @see ExpressionFunction */ public function register($name, $compiler, $evaluator) { $this->functions[$name] = array('compiler' => $compiler, 'evaluator' => $evaluator); } public function addFunction(ExpressionFunction $function) { $this->register($function->getName(), $function->getCompiler(), $function->getEvaluator()); } public function registerProvider(ExpressionFunctionProviderInterface $provider) { foreach ($provider->getFunctions() as $function) { $this->addFunction($function); } } protected function registerFunctions() { $this->register('constant', function ($constant) { return sprintf('constant(%s)', $constant); }, function (array $values, $constant) { return constant($constant); }); } private function getLexer() { if (null === $this->lexer) { $this->lexer = new Lexer(); } return $this->lexer; } private function getParser() { if (null === $this->parser) { $this->parser = new Parser($this->functions); } return $this->parser; } private function getCompiler() { if (null === $this->compiler) { $this->compiler = new Compiler($this->functions); } return $this->compiler->reset(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; /** * An executable finder specifically designed for the PHP executable. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class PhpExecutableFinder { private $executableFinder; public function __construct() { $this->executableFinder = new ExecutableFinder(); } /** * Finds The PHP executable. * * @param bool $includeArgs Whether or not include command arguments * * @return string|false The PHP executable path or false if it cannot be found */ public function find($includeArgs = true) { // HHVM support if (defined('HHVM_VERSION')) { return (getenv('PHP_BINARY') ?: PHP_BINARY).($includeArgs ? ' '.implode(' ', $this->findArguments()) : ''); } // PHP_BINARY return the current sapi executable if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server')) && is_file(PHP_BINARY)) { return PHP_BINARY; } if ($php = getenv('PHP_PATH')) { if (!is_executable($php)) { return false; } return $php; } if ($php = getenv('PHP_PEAR_PHP_BIN')) { if (is_executable($php)) { return $php; } } $dirs = array(PHP_BINDIR); if ('\\' === DIRECTORY_SEPARATOR) { $dirs[] = 'C:\xampp\php\\'; } return $this->executableFinder->find('php', false, $dirs); } /** * Finds the PHP executable arguments. * * @return array The PHP executable arguments */ public function findArguments() { $arguments = array(); // HHVM support if (defined('HHVM_VERSION')) { $arguments[] = '--php'; } return $arguments; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; /** * Generic executable finder. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class ExecutableFinder { private $suffixes = array('.exe', '.bat', '.cmd', '.com'); /** * Replaces default suffixes of executable. * * @param array $suffixes */ public function setSuffixes(array $suffixes) { $this->suffixes = $suffixes; } /** * Adds new possible suffix to check for executable. * * @param string $suffix */ public function addSuffix($suffix) { $this->suffixes[] = $suffix; } /** * Finds an executable by name. * * @param string $name The executable name (without the extension) * @param string $default The default to return if no executable is found * @param array $extraDirs Additional dirs to check into * * @return string The executable path or default value */ public function find($name, $default = null, array $extraDirs = array()) { if (ini_get('open_basedir')) { $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir')); $dirs = array(); foreach ($searchPath as $path) { if (is_dir($path)) { $dirs[] = $path; } else { if (basename($path) == $name && is_executable($path)) { return $path; } } } } else { $dirs = array_merge( explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), $extraDirs ); } $suffixes = array(''); if ('\\' === DIRECTORY_SEPARATOR) { $pathExt = getenv('PATHEXT'); $suffixes = $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes; } foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { if (is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) { return $file; } } } return $default; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\InvalidArgumentException; use Symfony\Component\Process\Exception\LogicException; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Exception\ProcessTimedOutException; use Symfony\Component\Process\Exception\RuntimeException; use Symfony\Component\Process\Pipes\PipesInterface; use Symfony\Component\Process\Pipes\UnixPipes; use Symfony\Component\Process\Pipes\WindowsPipes; /** * Process is a thin wrapper around proc_* functions to easily * start independent PHP processes. * * @author Fabien Potencier * @author Romain Neutron * * @api */ class Process { const ERR = 'err'; const OUT = 'out'; const STATUS_READY = 'ready'; const STATUS_STARTED = 'started'; const STATUS_TERMINATED = 'terminated'; const STDIN = 0; const STDOUT = 1; const STDERR = 2; // Timeout Precision in seconds. const TIMEOUT_PRECISION = 0.2; private $callback; private $commandline; private $cwd; private $env; private $input; private $starttime; private $lastOutputTime; private $timeout; private $idleTimeout; private $options; private $exitcode; private $fallbackExitcode; private $processInformation; private $outputDisabled = false; private $stdout; private $stderr; private $enhanceWindowsCompatibility = true; private $enhanceSigchildCompatibility; private $process; private $status = self::STATUS_READY; private $incrementalOutputOffset = 0; private $incrementalErrorOutputOffset = 0; private $tty; private $pty; private $useFileHandles = false; /** @var PipesInterface */ private $processPipes; private $latestSignal; private static $sigchild; /** * Exit codes translation table. * * User-defined errors must use exit codes in the 64-113 range. * * @var array */ public static $exitCodes = array( 0 => 'OK', 1 => 'General error', 2 => 'Misuse of shell builtins', 126 => 'Invoked command cannot execute', 127 => 'Command not found', 128 => 'Invalid exit argument', // signals 129 => 'Hangup', 130 => 'Interrupt', 131 => 'Quit and dump core', 132 => 'Illegal instruction', 133 => 'Trace/breakpoint trap', 134 => 'Process aborted', 135 => 'Bus error: "access to undefined portion of memory object"', 136 => 'Floating point exception: "erroneous arithmetic operation"', 137 => 'Kill (terminate immediately)', 138 => 'User-defined 1', 139 => 'Segmentation violation', 140 => 'User-defined 2', 141 => 'Write to pipe with no one reading', 142 => 'Signal raised by alarm', 143 => 'Termination (request to terminate)', // 144 - not defined 145 => 'Child process terminated, stopped (or continued*)', 146 => 'Continue if stopped', 147 => 'Stop executing temporarily', 148 => 'Terminal stop signal', 149 => 'Background process attempting to read from tty ("in")', 150 => 'Background process attempting to write to tty ("out")', 151 => 'Urgent data available on socket', 152 => 'CPU time limit exceeded', 153 => 'File size limit exceeded', 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"', 155 => 'Profiling timer expired', // 156 - not defined 157 => 'Pollable event', // 158 - not defined 159 => 'Bad syscall', ); /** * Constructor. * * @param string $commandline The command line to run * @param string|null $cwd The working directory or null to use the working dir of the current PHP process * @param array|null $env The environment variables or null to inherit * @param string|null $input The input * @param int|float|null $timeout The timeout in seconds or null to disable * @param array $options An array of options for proc_open * * @throws RuntimeException When proc_open is not installed * * @api */ public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array()) { if (!function_exists('proc_open')) { throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.'); } $this->commandline = $commandline; $this->cwd = $cwd; // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected // @see : https://bugs.php.net/bug.php?id=51800 // @see : https://bugs.php.net/bug.php?id=50524 if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || '\\' === DIRECTORY_SEPARATOR)) { $this->cwd = getcwd(); } if (null !== $env) { $this->setEnv($env); } $this->input = $input; $this->setTimeout($timeout); $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR; $this->pty = false; $this->enhanceWindowsCompatibility = true; $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled(); $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options); } public function __destruct() { // stop() will check if we have a process running. $this->stop(); } public function __clone() { $this->resetProcessData(); } /** * Runs the process. * * The callback receives the type of output (out or err) and * some bytes from the output in real-time. It allows to have feedback * from the independent process during execution. * * The STDOUT and STDERR are also available after the process is finished * via the getOutput() and getErrorOutput() methods. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return int The exit status code * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process stopped after receiving signal * @throws LogicException In case a callback is provided and output has been disabled * * @api */ public function run($callback = null) { $this->start($callback); return $this->wait(); } /** * Runs the process. * * This is identical to run() except that an exception is thrown if the process * exits with a non-zero exit code. * * @param callable|null $callback * * @return self * * @throws RuntimeException if PHP was compiled with --enable-sigchild and the enhanced sigchild compatibility mode is not enabled * @throws ProcessFailedException if the process didn't terminate successfully */ public function mustRun($callback = null) { if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); } if (0 !== $this->run($callback)) { throw new ProcessFailedException($this); } return $this; } /** * Starts the process and returns after writing the input to STDIN. * * This method blocks until all STDIN data is sent to the process then it * returns while the process runs in the background. * * The termination of the process can be awaited with wait(). * * The callback receives the type of output (out or err) and some bytes from * the output in real-time while writing the standard input to the process. * It allows to have feedback from the independent process during execution. * If there is no callback passed, the wait() method can be called * with true as a second parameter then the callback will get all data occurred * in (and since) the start call. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running * @throws LogicException In case a callback is provided and output has been disabled */ public function start($callback = null) { if ($this->isRunning()) { throw new RuntimeException('Process is already running'); } if ($this->outputDisabled && null !== $callback) { throw new LogicException('Output has been disabled, enable it to allow the use of a callback.'); } $this->resetProcessData(); $this->starttime = $this->lastOutputTime = microtime(true); $this->callback = $this->buildCallback($callback); $descriptors = $this->getDescriptors(); $commandline = $this->commandline; if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) { $commandline = 'cmd /V:ON /E:ON /C "('.$commandline.')'; foreach ($this->processPipes->getFiles() as $offset => $filename) { $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename); } $commandline .= '"'; if (!isset($this->options['bypass_shell'])) { $this->options['bypass_shell'] = true; } } $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options); if (!is_resource($this->process)) { throw new RuntimeException('Unable to launch a new process.'); } $this->status = self::STATUS_STARTED; if ($this->tty) { return; } $this->updateStatus(false); $this->checkTimeout(); } /** * Restarts the process. * * Be warned that the process is cloned before being started. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return Process The new process * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running * * @see start() */ public function restart($callback = null) { if ($this->isRunning()) { throw new RuntimeException('Process is already running'); } $process = clone $this; $process->start($callback); return $process; } /** * Waits for the process to terminate. * * The callback receives the type of output (out or err) and some bytes * from the output in real-time while writing the standard input to the process. * It allows to have feedback from the independent process during execution. * * @param callable|null $callback A valid PHP callback * * @return int The exitcode of the process * * @throws RuntimeException When process timed out * @throws RuntimeException When process stopped after receiving signal * @throws LogicException When process is not yet started */ public function wait($callback = null) { $this->requireProcessIsStarted(__FUNCTION__); $this->updateStatus(false); if (null !== $callback) { $this->callback = $this->buildCallback($callback); } do { $this->checkTimeout(); $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); $close = '\\' !== DIRECTORY_SEPARATOR || !$running; $this->readPipes(true, $close); } while ($running); while ($this->isRunning()) { usleep(1000); } if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) { throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig'])); } return $this->exitcode; } /** * Returns the Pid (process identifier), if applicable. * * @return int|null The process id if running, null otherwise * * @throws RuntimeException In case --enable-sigchild is activated */ public function getPid() { if ($this->isSigchildEnabled()) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.'); } $this->updateStatus(false); return $this->isRunning() ? $this->processInformation['pid'] : null; } /** * Sends a POSIX signal to the process. * * @param int $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php) * * @return Process * * @throws LogicException In case the process is not running * @throws RuntimeException In case --enable-sigchild is activated * @throws RuntimeException In case of failure */ public function signal($signal) { $this->doSignal($signal, true); return $this; } /** * Disables fetching output and error output from the underlying process. * * @return Process * * @throws RuntimeException In case the process is already running * @throws LogicException if an idle timeout is set */ public function disableOutput() { if ($this->isRunning()) { throw new RuntimeException('Disabling output while the process is running is not possible.'); } if (null !== $this->idleTimeout) { throw new LogicException('Output can not be disabled while an idle timeout is set.'); } $this->outputDisabled = true; return $this; } /** * Enables fetching output and error output from the underlying process. * * @return Process * * @throws RuntimeException In case the process is already running */ public function enableOutput() { if ($this->isRunning()) { throw new RuntimeException('Enabling output while the process is running is not possible.'); } $this->outputDisabled = false; return $this; } /** * Returns true in case the output is disabled, false otherwise. * * @return bool */ public function isOutputDisabled() { return $this->outputDisabled; } /** * Returns the current output of the process (STDOUT). * * @return string The process output * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started * * @api */ public function getOutput() { if ($this->outputDisabled) { throw new LogicException('Output has been disabled.'); } $this->requireProcessIsStarted(__FUNCTION__); $this->readPipes(false, '\\' === DIRECTORY_SEPARATOR ? !$this->processInformation['running'] : true); return $this->stdout; } /** * Returns the output incrementally. * * In comparison with the getOutput method which always return the whole * output, this one returns the new output since the last call. * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started * * @return string The process output since the last call */ public function getIncrementalOutput() { $this->requireProcessIsStarted(__FUNCTION__); $data = $this->getOutput(); $latest = substr($data, $this->incrementalOutputOffset); if (false === $latest) { return ''; } $this->incrementalOutputOffset = strlen($data); return $latest; } /** * Clears the process output. * * @return Process */ public function clearOutput() { $this->stdout = ''; $this->incrementalOutputOffset = 0; return $this; } /** * Returns the current error output of the process (STDERR). * * @return string The process error output * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started * * @api */ public function getErrorOutput() { if ($this->outputDisabled) { throw new LogicException('Output has been disabled.'); } $this->requireProcessIsStarted(__FUNCTION__); $this->readPipes(false, '\\' === DIRECTORY_SEPARATOR ? !$this->processInformation['running'] : true); return $this->stderr; } /** * Returns the errorOutput incrementally. * * In comparison with the getErrorOutput method which always return the * whole error output, this one returns the new error output since the last * call. * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started * * @return string The process error output since the last call */ public function getIncrementalErrorOutput() { $this->requireProcessIsStarted(__FUNCTION__); $data = $this->getErrorOutput(); $latest = substr($data, $this->incrementalErrorOutputOffset); if (false === $latest) { return ''; } $this->incrementalErrorOutputOffset = strlen($data); return $latest; } /** * Clears the process output. * * @return Process */ public function clearErrorOutput() { $this->stderr = ''; $this->incrementalErrorOutputOffset = 0; return $this; } /** * Returns the exit code returned by the process. * * @return null|int The exit status code, null if the Process is not terminated * * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled * * @api */ public function getExitCode() { if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); } $this->updateStatus(false); return $this->exitcode; } /** * Returns a string representation for the exit code returned by the process. * * This method relies on the Unix exit code status standardization * and might not be relevant for other operating systems. * * @return null|string A string representation for the exit status code, null if the Process is not terminated. * * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled * * @see http://tldp.org/LDP/abs/html/exitcodes.html * @see http://en.wikipedia.org/wiki/Unix_signal */ public function getExitCodeText() { if (null === $exitcode = $this->getExitCode()) { return; } return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error'; } /** * Checks if the process ended successfully. * * @return bool true if the process ended successfully, false otherwise * * @api */ public function isSuccessful() { return 0 === $this->getExitCode(); } /** * Returns true if the child process has been terminated by an uncaught signal. * * It always returns false on Windows. * * @return bool * * @throws RuntimeException In case --enable-sigchild is activated * @throws LogicException In case the process is not terminated * * @api */ public function hasBeenSignaled() { $this->requireProcessIsTerminated(__FUNCTION__); if ($this->isSigchildEnabled()) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); } $this->updateStatus(false); return $this->processInformation['signaled']; } /** * Returns the number of the signal that caused the child process to terminate its execution. * * It is only meaningful if hasBeenSignaled() returns true. * * @return int * * @throws RuntimeException In case --enable-sigchild is activated * @throws LogicException In case the process is not terminated * * @api */ public function getTermSignal() { $this->requireProcessIsTerminated(__FUNCTION__); if ($this->isSigchildEnabled()) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); } $this->updateStatus(false); return $this->processInformation['termsig']; } /** * Returns true if the child process has been stopped by a signal. * * It always returns false on Windows. * * @return bool * * @throws LogicException In case the process is not terminated * * @api */ public function hasBeenStopped() { $this->requireProcessIsTerminated(__FUNCTION__); $this->updateStatus(false); return $this->processInformation['stopped']; } /** * Returns the number of the signal that caused the child process to stop its execution. * * It is only meaningful if hasBeenStopped() returns true. * * @return int * * @throws LogicException In case the process is not terminated * * @api */ public function getStopSignal() { $this->requireProcessIsTerminated(__FUNCTION__); $this->updateStatus(false); return $this->processInformation['stopsig']; } /** * Checks if the process is currently running. * * @return bool true if the process is currently running, false otherwise */ public function isRunning() { if (self::STATUS_STARTED !== $this->status) { return false; } $this->updateStatus(false); return $this->processInformation['running']; } /** * Checks if the process has been started with no regard to the current state. * * @return bool true if status is ready, false otherwise */ public function isStarted() { return $this->status != self::STATUS_READY; } /** * Checks if the process is terminated. * * @return bool true if process is terminated, false otherwise */ public function isTerminated() { $this->updateStatus(false); return $this->status == self::STATUS_TERMINATED; } /** * Gets the process status. * * The status is one of: ready, started, terminated. * * @return string The current process status */ public function getStatus() { $this->updateStatus(false); return $this->status; } /** * Stops the process. * * @param int|float $timeout The timeout in seconds * @param int $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL * * @return int The exit-code of the process * * @throws RuntimeException if the process got signaled */ public function stop($timeout = 10, $signal = null) { $timeoutMicro = microtime(true) + $timeout; if ($this->isRunning()) { if ('\\' === DIRECTORY_SEPARATOR && !$this->isSigchildEnabled()) { exec(sprintf('taskkill /F /T /PID %d 2>&1', $this->getPid()), $output, $exitCode); if ($exitCode > 0) { throw new RuntimeException('Unable to kill the process'); } } // given `SIGTERM` may not be defined and that `proc_terminate` uses the constant value and not the constant itself, we use the same here $this->doSignal(15, false); do { usleep(1000); } while ($this->isRunning() && microtime(true) < $timeoutMicro); if ($this->isRunning() && !$this->isSigchildEnabled()) { if (null !== $signal || defined('SIGKILL')) { // avoid exception here : // process is supposed to be running, but it might have stop // just after this line. // in any case, let's silently discard the error, we can not do anything $this->doSignal($signal ?: SIGKILL, false); } } } $this->updateStatus(false); if ($this->processInformation['running']) { $this->close(); } return $this->exitcode; } /** * Adds a line to the STDOUT stream. * * @param string $line The line to append */ public function addOutput($line) { $this->lastOutputTime = microtime(true); $this->stdout .= $line; } /** * Adds a line to the STDERR stream. * * @param string $line The line to append */ public function addErrorOutput($line) { $this->lastOutputTime = microtime(true); $this->stderr .= $line; } /** * Gets the command line to be executed. * * @return string The command to execute */ public function getCommandLine() { return $this->commandline; } /** * Sets the command line to be executed. * * @param string $commandline The command to execute * * @return self The current Process instance */ public function setCommandLine($commandline) { $this->commandline = $commandline; return $this; } /** * Gets the process timeout (max. runtime). * * @return float|null The timeout in seconds or null if it's disabled */ public function getTimeout() { return $this->timeout; } /** * Gets the process idle timeout (max. time since last output). * * @return float|null The timeout in seconds or null if it's disabled */ public function getIdleTimeout() { return $this->idleTimeout; } /** * Sets the process timeout (max. runtime). * * To disable the timeout, set this value to null. * * @param int|float|null $timeout The timeout in seconds * * @return self The current Process instance * * @throws InvalidArgumentException if the timeout is negative */ public function setTimeout($timeout) { $this->timeout = $this->validateTimeout($timeout); return $this; } /** * Sets the process idle timeout (max. time since last output). * * To disable the timeout, set this value to null. * * @param int|float|null $timeout The timeout in seconds * * @return self The current Process instance. * * @throws LogicException if the output is disabled * @throws InvalidArgumentException if the timeout is negative */ public function setIdleTimeout($timeout) { if (null !== $timeout && $this->outputDisabled) { throw new LogicException('Idle timeout can not be set while the output is disabled.'); } $this->idleTimeout = $this->validateTimeout($timeout); return $this; } /** * Enables or disables the TTY mode. * * @param bool $tty True to enabled and false to disable * * @return self The current Process instance * * @throws RuntimeException In case the TTY mode is not supported */ public function setTty($tty) { if ('\\' === DIRECTORY_SEPARATOR && $tty) { throw new RuntimeException('TTY mode is not supported on Windows platform.'); } if ($tty && (!file_exists('/dev/tty') || !is_readable('/dev/tty'))) { throw new RuntimeException('TTY mode requires /dev/tty to be readable.'); } $this->tty = (bool) $tty; return $this; } /** * Checks if the TTY mode is enabled. * * @return bool true if the TTY mode is enabled, false otherwise */ public function isTty() { return $this->tty; } /** * Sets PTY mode. * * @param bool $bool * * @return self */ public function setPty($bool) { $this->pty = (bool) $bool; return $this; } /** * Returns PTY state. * * @return bool */ public function isPty() { return $this->pty; } /** * Gets the working directory. * * @return string|null The current working directory or null on failure */ public function getWorkingDirectory() { if (null === $this->cwd) { // getcwd() will return false if any one of the parent directories does not have // the readable or search mode set, even if the current directory does return getcwd() ?: null; } return $this->cwd; } /** * Sets the current working directory. * * @param string $cwd The new working directory * * @return self The current Process instance */ public function setWorkingDirectory($cwd) { $this->cwd = $cwd; return $this; } /** * Gets the environment variables. * * @return array The current environment variables */ public function getEnv() { return $this->env; } /** * Sets the environment variables. * * An environment variable value should be a string. * If it is an array, the variable is ignored. * * That happens in PHP when 'argv' is registered into * the $_ENV array for instance. * * @param array $env The new environment variables * * @return self The current Process instance */ public function setEnv(array $env) { // Process can not handle env values that are arrays $env = array_filter($env, function ($value) { return !is_array($value); }); $this->env = array(); foreach ($env as $key => $value) { $this->env[(binary) $key] = (binary) $value; } return $this; } /** * Gets the contents of STDIN. * * @return string|null The current contents * * @deprecated Deprecated since version 2.5, to be removed in 3.0. * This method is deprecated in favor of getInput. */ public function getStdin() { return $this->getInput(); } /** * Gets the Process input. * * @return null|string The Process input */ public function getInput() { return $this->input; } /** * Sets the contents of STDIN. * * @param string|null $stdin The new contents * * @return self The current Process instance * * @deprecated Deprecated since version 2.5, to be removed in 3.0. * This method is deprecated in favor of setInput. * * @throws LogicException In case the process is running * @throws InvalidArgumentException In case the argument is invalid */ public function setStdin($stdin) { return $this->setInput($stdin); } /** * Sets the input. * * This content will be passed to the underlying process standard input. * * @param string|null $input The content * * @return self The current Process instance * * @throws LogicException In case the process is running */ public function setInput($input) { if ($this->isRunning()) { throw new LogicException('Input can not be set while the process is running.'); } $this->input = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $input); return $this; } /** * Gets the options for proc_open. * * @return array The current options */ public function getOptions() { return $this->options; } /** * Sets the options for proc_open. * * @param array $options The new options * * @return self The current Process instance */ public function setOptions(array $options) { $this->options = $options; return $this; } /** * Gets whether or not Windows compatibility is enabled. * * This is true by default. * * @return bool */ public function getEnhanceWindowsCompatibility() { return $this->enhanceWindowsCompatibility; } /** * Sets whether or not Windows compatibility is enabled. * * @param bool $enhance * * @return self The current Process instance */ public function setEnhanceWindowsCompatibility($enhance) { $this->enhanceWindowsCompatibility = (bool) $enhance; return $this; } /** * Returns whether sigchild compatibility mode is activated or not. * * @return bool */ public function getEnhanceSigchildCompatibility() { return $this->enhanceSigchildCompatibility; } /** * Activates sigchild compatibility mode. * * Sigchild compatibility mode is required to get the exit code and * determine the success of a process when PHP has been compiled with * the --enable-sigchild option * * @param bool $enhance * * @return self The current Process instance */ public function setEnhanceSigchildCompatibility($enhance) { $this->enhanceSigchildCompatibility = (bool) $enhance; return $this; } /** * Performs a check between the timeout definition and the time the process started. * * In case you run a background process (with the start method), you should * trigger this method regularly to ensure the process timeout * * @throws ProcessTimedOutException In case the timeout was reached */ public function checkTimeout() { if ($this->status !== self::STATUS_STARTED) { return; } if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) { $this->stop(0); throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL); } if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) { $this->stop(0); throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE); } } /** * Returns whether PTY is supported on the current operating system. * * @return bool */ public static function isPtySupported() { static $result; if (null !== $result) { return $result; } if ('\\' === DIRECTORY_SEPARATOR) { return $result = false; } $proc = @proc_open('echo 1', array(array('pty'), array('pty'), array('pty')), $pipes); if (is_resource($proc)) { proc_close($proc); return $result = true; } return $result = false; } /** * Creates the descriptors needed by the proc_open. * * @return array */ private function getDescriptors() { if ('\\' === DIRECTORY_SEPARATOR) { $this->processPipes = WindowsPipes::create($this, $this->input); } else { $this->processPipes = UnixPipes::create($this, $this->input); } $descriptors = $this->processPipes->getDescriptors($this->outputDisabled); if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { // last exit code is output on the fourth pipe and caught to work around --enable-sigchild $descriptors = array_merge($descriptors, array(array('pipe', 'w'))); $this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code'; } return $descriptors; } /** * Builds up the callback used by wait(). * * The callbacks adds all occurred output to the specific buffer and calls * the user callback (if present) with the received output. * * @param callable|null $callback The user defined PHP callback * * @return callable A PHP callable */ protected function buildCallback($callback) { $that = $this; $out = self::OUT; $callback = function ($type, $data) use ($that, $callback, $out) { if ($out == $type) { $that->addOutput($data); } else { $that->addErrorOutput($data); } if (null !== $callback) { call_user_func($callback, $type, $data); } }; return $callback; } /** * Updates the status of the process, reads pipes. * * @param bool $blocking Whether to use a blocking read call. */ protected function updateStatus($blocking) { if (self::STATUS_STARTED !== $this->status) { return; } $this->processInformation = proc_get_status($this->process); $this->captureExitCode(); $this->readPipes($blocking, '\\' === DIRECTORY_SEPARATOR ? !$this->processInformation['running'] : true); if (!$this->processInformation['running']) { $this->close(); } } /** * Returns whether PHP has been compiled with the '--enable-sigchild' option or not. * * @return bool */ protected function isSigchildEnabled() { if (null !== self::$sigchild) { return self::$sigchild; } if (!function_exists('phpinfo')) { return self::$sigchild = false; } ob_start(); phpinfo(INFO_GENERAL); return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild'); } /** * Validates and returns the filtered timeout. * * @param int|float|null $timeout * * @return float|null * * @throws InvalidArgumentException if the given timeout is a negative number */ private function validateTimeout($timeout) { $timeout = (float) $timeout; if (0.0 === $timeout) { $timeout = null; } elseif ($timeout < 0) { throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.'); } return $timeout; } /** * Reads pipes, executes callback. * * @param bool $blocking Whether to use blocking calls or not. * @param bool $close Whether to close file handles or not. */ private function readPipes($blocking, $close) { $result = $this->processPipes->readAndWrite($blocking, $close); $callback = $this->callback; foreach ($result as $type => $data) { if (3 == $type) { $this->fallbackExitcode = (int) $data; } else { $callback($type === self::STDOUT ? self::OUT : self::ERR, $data); } } } /** * Captures the exitcode if mentioned in the process information. */ private function captureExitCode() { if (isset($this->processInformation['exitcode']) && -1 != $this->processInformation['exitcode']) { $this->exitcode = $this->processInformation['exitcode']; } } /** * Closes process resource, closes file handles, sets the exitcode. * * @return int The exitcode */ private function close() { $this->processPipes->close(); if (is_resource($this->process)) { $exitcode = proc_close($this->process); } else { $exitcode = -1; } $this->exitcode = -1 !== $exitcode ? $exitcode : (null !== $this->exitcode ? $this->exitcode : -1); $this->status = self::STATUS_TERMINATED; if (-1 === $this->exitcode && null !== $this->fallbackExitcode) { $this->exitcode = $this->fallbackExitcode; } elseif (-1 === $this->exitcode && $this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) { // if process has been signaled, no exitcode but a valid termsig, apply Unix convention $this->exitcode = 128 + $this->processInformation['termsig']; } return $this->exitcode; } /** * Resets data related to the latest run of the process. */ private function resetProcessData() { $this->starttime = null; $this->callback = null; $this->exitcode = null; $this->fallbackExitcode = null; $this->processInformation = null; $this->stdout = null; $this->stderr = null; $this->process = null; $this->latestSignal = null; $this->status = self::STATUS_READY; $this->incrementalOutputOffset = 0; $this->incrementalErrorOutputOffset = 0; } /** * Sends a POSIX signal to the process. * * @param int $signal A valid POSIX signal (see http://www.php.net/manual/en/pcntl.constants.php) * @param bool $throwException Whether to throw exception in case signal failed * * @return bool True if the signal was sent successfully, false otherwise * * @throws LogicException In case the process is not running * @throws RuntimeException In case --enable-sigchild is activated * @throws RuntimeException In case of failure */ private function doSignal($signal, $throwException) { if (!$this->isRunning()) { if ($throwException) { throw new LogicException('Can not send signal on a non running process.'); } return false; } if ($this->isSigchildEnabled()) { if ($throwException) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.'); } return false; } if (true !== @proc_terminate($this->process, $signal)) { if ($throwException) { throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal)); } return false; } $this->latestSignal = $signal; return true; } /** * Ensures the process is running or terminated, throws a LogicException if the process has a not started. * * @param string $functionName The function name that was called. * * @throws LogicException If the process has not run. */ private function requireProcessIsStarted($functionName) { if (!$this->isStarted()) { throw new LogicException(sprintf('Process must be started before calling %s.', $functionName)); } } /** * Ensures the process is terminated, throws a LogicException if the process has a status different than `terminated`. * * @param string $functionName The function name that was called. * * @throws LogicException If the process is not yet terminated. */ private function requireProcessIsTerminated($functionName) { if (!$this->isTerminated()) { throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName)); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\InvalidArgumentException; /** * ProcessUtils is a bunch of utility methods. * * This class contains static methods only and is not meant to be instantiated. * * @author Martin Hasoň */ class ProcessUtils { /** * This class should not be instantiated. */ private function __construct() { } /** * Escapes a string to be used as a shell argument. * * @param string $argument The argument that will be escaped * * @return string The escaped argument */ public static function escapeArgument($argument) { //Fix for PHP bug #43784 escapeshellarg removes % from given string //Fix for PHP bug #49446 escapeshellarg doesn't work on Windows //@see https://bugs.php.net/bug.php?id=43784 //@see https://bugs.php.net/bug.php?id=49446 if ('\\' === DIRECTORY_SEPARATOR) { if ('' === $argument) { return escapeshellarg($argument); } $escapedArgument = ''; $quote = false; foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) { if ('"' === $part) { $escapedArgument .= '\\"'; } elseif (self::isSurroundedBy($part, '%')) { // Avoid environment variable expansion $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%'; } else { // escape trailing backslash if ('\\' === substr($part, -1)) { $part .= '\\'; } $quote = true; $escapedArgument .= $part; } } if ($quote) { $escapedArgument = '"'.$escapedArgument.'"'; } return $escapedArgument; } return escapeshellarg($argument); } /** * Validates and normalizes a Process input. * * @param string $caller The name of method call that validates the input * @param mixed $input The input to validate * * @return string The validated input * * @throws InvalidArgumentException In case the input is not valid */ public static function validateInput($caller, $input) { if (null !== $input) { if (is_resource($input)) { return $input; } if (is_scalar($input)) { return (string) $input; } // deprecated as of Symfony 2.5, to be removed in 3.0 if (is_object($input) && method_exists($input, '__toString')) { return (string) $input; } throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller)); } return $input; } private static function isSurroundedBy($arg, $char) { return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1]; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\RuntimeException; /** * PhpProcess runs a PHP script in an independent process. * * $p = new PhpProcess(''); * $p->run(); * print $p->getOutput()."\n"; * * @author Fabien Potencier * * @api */ class PhpProcess extends Process { /** * Constructor. * * @param string $script The PHP script to run (as a string) * @param string $cwd The working directory * @param array $env The environment variables * @param int $timeout The timeout in seconds * @param array $options An array of options for proc_open * * @api */ public function __construct($script, $cwd = null, array $env = array(), $timeout = 60, array $options = array()) { $executableFinder = new PhpExecutableFinder(); if (false === $php = $executableFinder->find()) { $php = null; } parent::__construct($php, $cwd, $env, $script, $timeout, $options); } /** * Sets the path to the PHP binary to use. * * @api */ public function setPhpBinary($php) { $this->setCommandLine($php); } /** * {@inheritdoc} */ public function start($callback = null) { if (null === $this->getCommandLine()) { throw new RuntimeException('Unable to find the PHP executable.'); } parent::start($callback); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Pipes; /** * PipesInterface manages descriptors and pipes for the use of proc_open. * * @author Romain Neutron * * @internal */ interface PipesInterface { const CHUNK_SIZE = 16384; /** * Returns an array of descriptors for the use of proc_open. * * @return array */ public function getDescriptors(); /** * Returns an array of filenames indexed by their related stream in case these pipes use temporary files. * * @return string[] */ public function getFiles(); /** * Reads data in file handles and pipes. * * @param bool $blocking Whether to use blocking calls or not. * @param bool $close Whether to close pipes if they've reached EOF. * * @return string[] An array of read data indexed by their fd. */ public function readAndWrite($blocking, $close = false); /** * Returns if the current state has open file handles or pipes. * * @return bool */ public function areOpen(); /** * Closes file handles and pipes. */ public function close(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Pipes; /** * @author Romain Neutron * * @internal */ abstract class AbstractPipes implements PipesInterface { /** @var array */ public $pipes = array(); /** @var string */ protected $inputBuffer = ''; /** @var resource|null */ protected $input; /** @var bool */ private $blocked = true; /** * {@inheritdoc} */ public function close() { foreach ($this->pipes as $pipe) { fclose($pipe); } $this->pipes = array(); } /** * Returns true if a system call has been interrupted. * * @return bool */ protected function hasSystemCallBeenInterrupted() { $lastError = error_get_last(); // stream_select returns false when the `select` system call is interrupted by an incoming signal return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call'); } /** * Unblocks streams */ protected function unblock() { if (!$this->blocked) { return; } foreach ($this->pipes as $pipe) { stream_set_blocking($pipe, 0); } if (null !== $this->input) { stream_set_blocking($this->input, 0); } $this->blocked = false; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Pipes; use Symfony\Component\Process\Process; use Symfony\Component\Process\Exception\RuntimeException; /** * WindowsPipes implementation uses temporary files as handles. * * @see https://bugs.php.net/bug.php?id=51800 * @see https://bugs.php.net/bug.php?id=65650 * * @author Romain Neutron * * @internal */ class WindowsPipes extends AbstractPipes { /** @var array */ private $files = array(); /** @var array */ private $fileHandles = array(); /** @var array */ private $readBytes = array( Process::STDOUT => 0, Process::STDERR => 0, ); /** @var bool */ private $disableOutput; public function __construct($disableOutput, $input) { $this->disableOutput = (bool) $disableOutput; if (!$this->disableOutput) { // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big. // Workaround for this problem is to use temporary files instead of pipes on Windows platform. // // @see https://bugs.php.net/bug.php?id=51800 $this->files = array( Process::STDOUT => tempnam(sys_get_temp_dir(), 'sf_proc_stdout'), Process::STDERR => tempnam(sys_get_temp_dir(), 'sf_proc_stderr'), ); foreach ($this->files as $offset => $file) { $this->fileHandles[$offset] = fopen($this->files[$offset], 'rb'); if (false === $this->fileHandles[$offset]) { throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable'); } } } if (is_resource($input)) { $this->input = $input; } else { $this->inputBuffer = $input; } } public function __destruct() { $this->close(); $this->removeFiles(); } /** * {@inheritdoc} */ public function getDescriptors() { if ($this->disableOutput) { $nullstream = fopen('NUL', 'c'); return array( array('pipe', 'r'), $nullstream, $nullstream, ); } // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800) // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650 // So we redirect output within the commandline and pass the nul device to the process return array( array('pipe', 'r'), array('file', 'NUL', 'w'), array('file', 'NUL', 'w'), ); } /** * {@inheritdoc} */ public function getFiles() { return $this->files; } /** * {@inheritdoc} */ public function readAndWrite($blocking, $close = false) { $this->write($blocking, $close); $read = array(); $fh = $this->fileHandles; foreach ($fh as $type => $fileHandle) { if (0 !== fseek($fileHandle, $this->readBytes[$type])) { continue; } $data = ''; $dataread = null; while (!feof($fileHandle)) { if (false !== $dataread = fread($fileHandle, self::CHUNK_SIZE)) { $data .= $dataread; } } if (0 < $length = strlen($data)) { $this->readBytes[$type] += $length; $read[$type] = $data; } if (false === $dataread || (true === $close && feof($fileHandle) && '' === $data)) { fclose($this->fileHandles[$type]); unset($this->fileHandles[$type]); } } return $read; } /** * {@inheritdoc} */ public function areOpen() { return (bool) $this->pipes && (bool) $this->fileHandles; } /** * {@inheritdoc} */ public function close() { parent::close(); foreach ($this->fileHandles as $handle) { fclose($handle); } $this->fileHandles = array(); } /** * Creates a new WindowsPipes instance. * * @param Process $process The process * @param $input * * @return WindowsPipes */ public static function create(Process $process, $input) { return new static($process->isOutputDisabled(), $input); } /** * Removes temporary files */ private function removeFiles() { foreach ($this->files as $filename) { if (file_exists($filename)) { @unlink($filename); } } $this->files = array(); } /** * Writes input to stdin * * @param bool $blocking * @param bool $close */ private function write($blocking, $close) { if (empty($this->pipes)) { return; } $this->unblock(); $r = null !== $this->input ? array('input' => $this->input) : null; $w = isset($this->pipes[0]) ? array($this->pipes[0]) : null; $e = null; // let's have a look if something changed in streams if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) { // if a system call has been interrupted, forget about it, let's try again // otherwise, an error occurred, let's reset pipes if (!$this->hasSystemCallBeenInterrupted()) { $this->pipes = array(); } return; } // nothing has changed if (0 === $n) { return; } if (null !== $w && 0 < count($r)) { $data = ''; while ($dataread = fread($r['input'], self::CHUNK_SIZE)) { $data .= $dataread; } $this->inputBuffer .= $data; if (false === $data || (true === $close && feof($r['input']) && '' === $data)) { // no more data to read on input resource // use an empty buffer in the next reads $this->input = null; } } if (null !== $w && 0 < count($w)) { while (strlen($this->inputBuffer)) { $written = fwrite($w[0], $this->inputBuffer, 2 << 18); if ($written > 0) { $this->inputBuffer = (string) substr($this->inputBuffer, $written); } else { break; } } } // no input to read on resource, buffer is empty and stdin still open if ('' === $this->inputBuffer && null === $this->input && isset($this->pipes[0])) { fclose($this->pipes[0]); unset($this->pipes[0]); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Pipes; use Symfony\Component\Process\Process; /** * UnixPipes implementation uses unix pipes as handles. * * @author Romain Neutron * * @internal */ class UnixPipes extends AbstractPipes { /** @var bool */ private $ttyMode; /** @var bool */ private $ptyMode; /** @var bool */ private $disableOutput; public function __construct($ttyMode, $ptyMode, $input, $disableOutput) { $this->ttyMode = (bool) $ttyMode; $this->ptyMode = (bool) $ptyMode; $this->disableOutput = (bool) $disableOutput; if (is_resource($input)) { $this->input = $input; } else { $this->inputBuffer = (string) $input; } } public function __destruct() { $this->close(); } /** * {@inheritdoc} */ public function getDescriptors() { if ($this->disableOutput) { $nullstream = fopen('/dev/null', 'c'); return array( array('pipe', 'r'), $nullstream, $nullstream, ); } if ($this->ttyMode) { return array( array('file', '/dev/tty', 'r'), array('file', '/dev/tty', 'w'), array('file', '/dev/tty', 'w'), ); } if ($this->ptyMode && Process::isPtySupported()) { return array( array('pty'), array('pty'), array('pty'), ); } return array( array('pipe', 'r'), array('pipe', 'w'), // stdout array('pipe', 'w'), // stderr ); } /** * {@inheritdoc} */ public function getFiles() { return array(); } /** * {@inheritdoc} */ public function readAndWrite($blocking, $close = false) { // only stdin is left open, job has been done ! // we can now close it if (1 === count($this->pipes) && array(0) === array_keys($this->pipes)) { fclose($this->pipes[0]); unset($this->pipes[0]); } if (empty($this->pipes)) { return array(); } $this->unblock(); $read = array(); if (null !== $this->input) { // if input is a resource, let's add it to stream_select argument to // fill a buffer $r = array_merge($this->pipes, array('input' => $this->input)); } else { $r = $this->pipes; } // discard read on stdin unset($r[0]); $w = isset($this->pipes[0]) ? array($this->pipes[0]) : null; $e = null; // let's have a look if something changed in streams if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) { // if a system call has been interrupted, forget about it, let's try again // otherwise, an error occurred, let's reset pipes if (!$this->hasSystemCallBeenInterrupted()) { $this->pipes = array(); } return $read; } // nothing has changed if (0 === $n) { return $read; } foreach ($r as $pipe) { // prior PHP 5.4 the array passed to stream_select is modified and // lose key association, we have to find back the key $type = (false !== $found = array_search($pipe, $this->pipes)) ? $found : 'input'; $data = ''; while ('' !== $dataread = (string) fread($pipe, self::CHUNK_SIZE)) { $data .= $dataread; } if ('' !== $data) { if ($type === 'input') { $this->inputBuffer .= $data; } else { $read[$type] = $data; } } if (false === $data || (true === $close && feof($pipe) && '' === $data)) { if ($type === 'input') { // no more data to read on input resource // use an empty buffer in the next reads $this->input = null; } else { fclose($this->pipes[$type]); unset($this->pipes[$type]); } } } if (null !== $w && 0 < count($w)) { while (strlen($this->inputBuffer)) { $written = fwrite($w[0], $this->inputBuffer, 2 << 18); // write 512k if ($written > 0) { $this->inputBuffer = (string) substr($this->inputBuffer, $written); } else { break; } } } // no input to read on resource, buffer is empty and stdin still open if ('' === $this->inputBuffer && null === $this->input && isset($this->pipes[0])) { fclose($this->pipes[0]); unset($this->pipes[0]); } return $read; } /** * {@inheritdoc} */ public function areOpen() { return (bool) $this->pipes; } /** * Creates a new UnixPipes instance * * @param Process $process * @param string|resource $input * * @return UnixPipes */ public static function create(Process $process, $input) { return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled()); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; use Symfony\Component\Process\Process; /** * Exception that is thrown when a process times out. * * @author Johannes M. Schmitt */ class ProcessTimedOutException extends RuntimeException { const TYPE_GENERAL = 1; const TYPE_IDLE = 2; private $process; private $timeoutType; public function __construct(Process $process, $timeoutType) { $this->process = $process; $this->timeoutType = $timeoutType; parent::__construct(sprintf( 'The process "%s" exceeded the timeout of %s seconds.', $process->getCommandLine(), $this->getExceededTimeout() )); } public function getProcess() { return $this->process; } public function isGeneralTimeout() { return $this->timeoutType === self::TYPE_GENERAL; } public function isIdleTimeout() { return $this->timeoutType === self::TYPE_IDLE; } public function getExceededTimeout() { switch ($this->timeoutType) { case self::TYPE_GENERAL: return $this->process->getTimeout(); case self::TYPE_IDLE: return $this->process->getIdleTimeout(); default: throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType)); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * Marker Interface for the Process Component. * * @author Johannes M. Schmitt */ interface ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * InvalidArgumentException for the Process Component. * * @author Romain Neutron */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * LogicException for the Process Component. * * @author Romain Neutron */ class LogicException extends \LogicException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * RuntimeException for the Process Component. * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; use Symfony\Component\Process\Process; /** * Exception for failed processes. * * @author Johannes M. Schmitt */ class ProcessFailedException extends RuntimeException { private $process; public function __construct(Process $process) { if ($process->isSuccessful()) { throw new InvalidArgumentException('Expected a failed process, but the given process was successful.'); } $error = sprintf('The command "%s" failed.'."\nExit Code: %s(%s)", $process->getCommandLine(), $process->getExitCode(), $process->getExitCodeText() ); if (!$process->isOutputDisabled()) { $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s", $process->getOutput(), $process->getErrorOutput() ); } parent::__construct($error); $this->process = $process; } public function getProcess() { return $this->process; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\InvalidArgumentException; use Symfony\Component\Process\Exception\LogicException; /** * Process builder. * * @author Kris Wallsmith */ class ProcessBuilder { private $arguments; private $cwd; private $env = array(); private $input; private $timeout = 60; private $options = array(); private $inheritEnv = true; private $prefix = array(); private $outputDisabled = false; /** * Constructor. * * @param string[] $arguments An array of arguments */ public function __construct(array $arguments = array()) { $this->arguments = $arguments; } /** * Creates a process builder instance. * * @param string[] $arguments An array of arguments * * @return ProcessBuilder */ public static function create(array $arguments = array()) { return new static($arguments); } /** * Adds an unescaped argument to the command string. * * @param string $argument A command argument * * @return ProcessBuilder */ public function add($argument) { $this->arguments[] = $argument; return $this; } /** * Adds a prefix to the command string. * * The prefix is preserved when resetting arguments. * * @param string|array $prefix A command prefix or an array of command prefixes * * @return ProcessBuilder */ public function setPrefix($prefix) { $this->prefix = is_array($prefix) ? $prefix : array($prefix); return $this; } /** * Sets the arguments of the process. * * Arguments must not be escaped. * Previous arguments are removed. * * @param string[] $arguments * * @return ProcessBuilder */ public function setArguments(array $arguments) { $this->arguments = $arguments; return $this; } /** * Sets the working directory. * * @param null|string $cwd The working directory * * @return ProcessBuilder */ public function setWorkingDirectory($cwd) { $this->cwd = $cwd; return $this; } /** * Sets whether environment variables will be inherited or not. * * @param bool $inheritEnv * * @return ProcessBuilder */ public function inheritEnvironmentVariables($inheritEnv = true) { $this->inheritEnv = $inheritEnv; return $this; } /** * Sets an environment variable. * * Setting a variable overrides its previous value. Use `null` to unset a * defined environment variable. * * @param string $name The variable name * @param null|string $value The variable value * * @return ProcessBuilder */ public function setEnv($name, $value) { $this->env[$name] = $value; return $this; } /** * Adds a set of environment variables. * * Already existing environment variables with the same name will be * overridden by the new values passed to this method. Pass `null` to unset * a variable. * * @param array $variables The variables * * @return ProcessBuilder */ public function addEnvironmentVariables(array $variables) { $this->env = array_replace($this->env, $variables); return $this; } /** * Sets the input of the process. * * @param string|null $input The input as a string * * @return ProcessBuilder * * @throws InvalidArgumentException In case the argument is invalid */ public function setInput($input) { $this->input = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $input); return $this; } /** * Sets the process timeout. * * To disable the timeout, set this value to null. * * @param float|null $timeout * * @return ProcessBuilder * * @throws InvalidArgumentException */ public function setTimeout($timeout) { if (null === $timeout) { $this->timeout = null; return $this; } $timeout = (float) $timeout; if ($timeout < 0) { throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.'); } $this->timeout = $timeout; return $this; } /** * Adds a proc_open option. * * @param string $name The option name * @param string $value The option value * * @return ProcessBuilder */ public function setOption($name, $value) { $this->options[$name] = $value; return $this; } /** * Disables fetching output and error output from the underlying process. * * @return ProcessBuilder */ public function disableOutput() { $this->outputDisabled = true; return $this; } /** * Enables fetching output and error output from the underlying process. * * @return ProcessBuilder */ public function enableOutput() { $this->outputDisabled = false; return $this; } /** * Creates a Process instance and returns it. * * @return Process * * @throws LogicException In case no arguments have been provided */ public function getProcess() { if (0 === count($this->prefix) && 0 === count($this->arguments)) { throw new LogicException('You must add() command arguments before calling getProcess().'); } $options = $this->options; $arguments = array_merge($this->prefix, $this->arguments); $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments)); if ($this->inheritEnv) { // include $_ENV for BC purposes $env = array_replace($_ENV, $_SERVER, $this->env); } else { $env = $this->env; } $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options); if ($this->outputDisabled) { $process->disableOutput(); } return $process; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * Event encapsulation class. * * Encapsulates events thus decoupling the observer from the subject they encapsulate. * * @author Drak */ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate { /** * Event subject. * * @var mixed usually object or callable */ protected $subject; /** * Array of arguments. * * @var array */ protected $arguments; /** * Encapsulate an event with $subject and $args. * * @param mixed $subject The subject of the event, usually an object. * @param array $arguments Arguments to store in the event. */ public function __construct($subject = null, array $arguments = array()) { $this->subject = $subject; $this->arguments = $arguments; } /** * Getter for subject property. * * @return mixed $subject The observer subject. */ public function getSubject() { return $this->subject; } /** * Get argument by key. * * @param string $key Key. * * @throws \InvalidArgumentException If key is not found. * * @return mixed Contents of array key. */ public function getArgument($key) { if ($this->hasArgument($key)) { return $this->arguments[$key]; } throw new \InvalidArgumentException(sprintf('%s not found in %s', $key, $this->getName())); } /** * Add argument to event. * * @param string $key Argument name. * @param mixed $value Value. * * @return GenericEvent */ public function setArgument($key, $value) { $this->arguments[$key] = $value; return $this; } /** * Getter for all arguments. * * @return array */ public function getArguments() { return $this->arguments; } /** * Set args property. * * @param array $args Arguments. * * @return GenericEvent */ public function setArguments(array $args = array()) { $this->arguments = $args; return $this; } /** * Has argument. * * @param string $key Key of arguments array. * * @return bool */ public function hasArgument($key) { return array_key_exists($key, $this->arguments); } /** * ArrayAccess for argument getter. * * @param string $key Array key. * * @throws \InvalidArgumentException If key does not exist in $this->args. * * @return mixed */ public function offsetGet($key) { return $this->getArgument($key); } /** * ArrayAccess for argument setter. * * @param string $key Array key to set. * @param mixed $value Value. */ public function offsetSet($key, $value) { $this->setArgument($key, $value); } /** * ArrayAccess for unset argument. * * @param string $key Array key. */ public function offsetUnset($key) { if ($this->hasArgument($key)) { unset($this->arguments[$key]); } } /** * ArrayAccess has argument. * * @param string $key Array key. * * @return bool */ public function offsetExists($key) { return $this->hasArgument($key); } /** * IteratorAggregate for iterating over the object like an array. * * @return \ArrayIterator */ public function getIterator() { return new \ArrayIterator($this->arguments); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * Listeners are registered on the manager and events are dispatched through the * manager. * * @author Bernhard Schussek * * @api */ interface EventDispatcherInterface { /** * Dispatches an event to all registered listeners. * * @param string $eventName The name of the event to dispatch. The name of * the event is the name of the method that is * invoked on listeners. * @param Event $event The event to pass to the event handlers/listeners. * If not supplied, an empty Event instance is created. * * @return Event * * @api */ public function dispatch($eventName, Event $event = null); /** * Adds an event listener that listens on the specified events. * * @param string $eventName The event to listen on * @param callable $listener The listener * @param int $priority The higher this value, the earlier an event * listener will be triggered in the chain (defaults to 0) * * @api */ public function addListener($eventName, $listener, $priority = 0); /** * Adds an event subscriber. * * The subscriber is asked for all the events he is * interested in and added as a listener for these events. * * @param EventSubscriberInterface $subscriber The subscriber. * * @api */ public function addSubscriber(EventSubscriberInterface $subscriber); /** * Removes an event listener from the specified events. * * @param string $eventName The event to remove a listener from * @param callable $listener The listener to remove */ public function removeListener($eventName, $listener); /** * Removes an event subscriber. * * @param EventSubscriberInterface $subscriber The subscriber */ public function removeSubscriber(EventSubscriberInterface $subscriber); /** * Gets the listeners of a specific event or all listeners sorted by descending priority. * * @param string $eventName The name of the event * * @return array The event listeners for the specified event, or all event listeners by event name */ public function getListeners($eventName = null); /** * Checks whether an event has any registered listeners. * * @param string $eventName The name of the event * * @return bool true if the specified event has any listeners, false otherwise */ public function hasListeners($eventName = null); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Lazily loads listeners and subscribers from the dependency injection * container. * * @author Fabien Potencier * @author Bernhard Schussek * @author Jordan Alliot */ class ContainerAwareEventDispatcher extends EventDispatcher { /** * The container from where services are loaded. * * @var ContainerInterface */ private $container; /** * The service IDs of the event listeners and subscribers. * * @var array */ private $listenerIds = array(); /** * The services registered as listeners. * * @var array */ private $listeners = array(); /** * Constructor. * * @param ContainerInterface $container A ContainerInterface instance */ public function __construct(ContainerInterface $container) { $this->container = $container; } /** * Adds a service as event listener. * * @param string $eventName Event for which the listener is added * @param array $callback The service ID of the listener service & the method * name that has to be called * @param int $priority The higher this value, the earlier an event listener * will be triggered in the chain. * Defaults to 0. * * @throws \InvalidArgumentException */ public function addListenerService($eventName, $callback, $priority = 0) { if (!is_array($callback) || 2 !== count($callback)) { throw new \InvalidArgumentException('Expected an array("service", "method") argument'); } $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority); } public function removeListener($eventName, $listener) { $this->lazyLoad($eventName); if (isset($this->listenerIds[$eventName])) { foreach ($this->listenerIds[$eventName] as $i => $args) { list($serviceId, $method, $priority) = $args; $key = $serviceId.'.'.$method; if (isset($this->listeners[$eventName][$key]) && $listener === array($this->listeners[$eventName][$key], $method)) { unset($this->listeners[$eventName][$key]); if (empty($this->listeners[$eventName])) { unset($this->listeners[$eventName]); } unset($this->listenerIds[$eventName][$i]); if (empty($this->listenerIds[$eventName])) { unset($this->listenerIds[$eventName]); } } } } parent::removeListener($eventName, $listener); } /** * @see EventDispatcherInterface::hasListeners() */ public function hasListeners($eventName = null) { if (null === $eventName) { return (bool) count($this->listenerIds) || (bool) count($this->listeners); } if (isset($this->listenerIds[$eventName])) { return true; } return parent::hasListeners($eventName); } /** * @see EventDispatcherInterface::getListeners() */ public function getListeners($eventName = null) { if (null === $eventName) { foreach ($this->listenerIds as $serviceEventName => $args) { $this->lazyLoad($serviceEventName); } } else { $this->lazyLoad($eventName); } return parent::getListeners($eventName); } /** * Adds a service as event subscriber. * * @param string $serviceId The service ID of the subscriber service * @param string $class The service's class name (which must implement EventSubscriberInterface) */ public function addSubscriberService($serviceId, $class) { foreach ($class::getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { $this->listenerIds[$eventName][] = array($serviceId, $params, 0); } elseif (is_string($params[0])) { $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0); } else { foreach ($params as $listener) { $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0); } } } } /** * {@inheritdoc} * * Lazily loads listeners for this event from the dependency injection * container. * * @throws \InvalidArgumentException if the service is not defined */ public function dispatch($eventName, Event $event = null) { $this->lazyLoad($eventName); return parent::dispatch($eventName, $event); } public function getContainer() { return $this->container; } /** * Lazily loads listeners for this event from the dependency injection * container. * * @param string $eventName The name of the event to dispatch. The name of * the event is the name of the method that is * invoked on listeners. */ protected function lazyLoad($eventName) { if (isset($this->listenerIds[$eventName])) { foreach ($this->listenerIds[$eventName] as $args) { list($serviceId, $method, $priority) = $args; $listener = $this->container->get($serviceId); $key = $serviceId.'.'.$method; if (!isset($this->listeners[$eventName][$key])) { $this->addListener($eventName, array($listener, $method), $priority); } elseif ($listener !== $this->listeners[$eventName][$key]) { parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method)); $this->addListener($eventName, array($listener, $method), $priority); } $this->listeners[$eventName][$key] = $listener; } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * An EventSubscriber knows himself what events he is interested in. * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes * {@link getSubscribedEvents} and registers the subscriber as a listener for all * returned events. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * * @api */ interface EventSubscriberInterface { /** * Returns an array of event names this subscriber wants to listen to. * * The array keys are event names and the value can be: * * * The method name to call (priority defaults to 0) * * An array composed of the method name to call and the priority * * An array of arrays composed of the method names to call and respective * priorities, or 0 if unset * * For instance: * * * array('eventName' => 'methodName') * * array('eventName' => array('methodName', $priority)) * * array('eventName' => array(array('methodName1', $priority), array('methodName2')) * * @return array The event names to listen to * * @api */ public static function getSubscribedEvents(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * A read-only proxy for an event dispatcher. * * @author Bernhard Schussek */ class ImmutableEventDispatcher implements EventDispatcherInterface { /** * The proxied dispatcher. * * @var EventDispatcherInterface */ private $dispatcher; /** * Creates an unmodifiable proxy for an event dispatcher. * * @param EventDispatcherInterface $dispatcher The proxied event dispatcher. */ public function __construct(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } /** * {@inheritdoc} */ public function dispatch($eventName, Event $event = null) { return $this->dispatcher->dispatch($eventName, $event); } /** * {@inheritdoc} */ public function addListener($eventName, $listener, $priority = 0) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function removeListener($eventName, $listener) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function getListeners($eventName = null) { return $this->dispatcher->getListeners($eventName); } /** * {@inheritdoc} */ public function hasListeners($eventName = null) { return $this->dispatcher->hasListeners($eventName); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * Event is the base class for classes containing event data. * * This class contains no event data. It is used by events that do not pass * state information to an event handler when an event is raised. * * You can call the method stopPropagation() to abort the execution of * further listeners in your event listener. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * * @api */ class Event { /** * @var bool Whether no further event listeners should be triggered */ private $propagationStopped = false; /** * @var EventDispatcher Dispatcher that dispatched this event */ private $dispatcher; /** * @var string This event's name */ private $name; /** * Returns whether further event listeners should be triggered. * * @see Event::stopPropagation() * * @return bool Whether propagation was already stopped for this event. * * @api */ public function isPropagationStopped() { return $this->propagationStopped; } /** * Stops the propagation of the event to further event listeners. * * If multiple event listeners are connected to the same event, no * further event listener will be triggered once any trigger calls * stopPropagation(). * * @api */ public function stopPropagation() { $this->propagationStopped = true; } /** * Stores the EventDispatcher that dispatches this Event. * * @param EventDispatcherInterface $dispatcher * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call. * * @api */ public function setDispatcher(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } /** * Returns the EventDispatcher that dispatches this Event. * * @return EventDispatcherInterface * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call. * * @api */ public function getDispatcher() { return $this->dispatcher; } /** * Gets the event's name. * * @return string * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call. * * @api */ public function getName() { return $this->name; } /** * Sets the event's name property. * * @param string $name The event name. * * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call. * * @api */ public function setName($name) { $this->name = $name; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\Debug; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\Stopwatch\Stopwatch; use Psr\Log\LoggerInterface; /** * Collects some data about event listeners. * * This event dispatcher delegates the dispatching to another one. * * @author Fabien Potencier */ class TraceableEventDispatcher implements TraceableEventDispatcherInterface { protected $logger; protected $stopwatch; private $called; private $dispatcher; private $wrappedListeners; /** * Constructor. * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param Stopwatch $stopwatch A Stopwatch instance * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null) { $this->dispatcher = $dispatcher; $this->stopwatch = $stopwatch; $this->logger = $logger; $this->called = array(); $this->wrappedListeners = array(); } /** * {@inheritdoc} */ public function addListener($eventName, $listener, $priority = 0) { $this->dispatcher->addListener($eventName, $listener, $priority); } /** * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { $this->dispatcher->addSubscriber($subscriber); } /** * {@inheritdoc} */ public function removeListener($eventName, $listener) { if (isset($this->wrappedListeners[$eventName])) { foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { if ($wrappedListener->getWrappedListener() === $listener) { $listener = $wrappedListener; unset($this->wrappedListeners[$eventName][$index]); break; } } } return $this->dispatcher->removeListener($eventName, $listener); } /** * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { return $this->dispatcher->removeSubscriber($subscriber); } /** * {@inheritdoc} */ public function getListeners($eventName = null) { return $this->dispatcher->getListeners($eventName); } /** * {@inheritdoc} */ public function hasListeners($eventName = null) { return $this->dispatcher->hasListeners($eventName); } /** * {@inheritdoc} */ public function dispatch($eventName, Event $event = null) { if (null === $event) { $event = new Event(); } $this->preProcess($eventName); $this->preDispatch($eventName, $event); $e = $this->stopwatch->start($eventName, 'section'); $this->dispatcher->dispatch($eventName, $event); if ($e->isStarted()) { $e->stop(); } $this->postDispatch($eventName, $event); $this->postProcess($eventName); return $event; } /** * {@inheritdoc} */ public function getCalledListeners() { $called = array(); foreach ($this->called as $eventName => $listeners) { foreach ($listeners as $listener) { $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName); $called[$eventName.'.'.$info['pretty']] = $info; } } return $called; } /** * {@inheritdoc} */ public function getNotCalledListeners() { try { $allListeners = $this->getListeners(); } catch (\Exception $e) { if (null !== $this->logger) { $this->logger->info(sprintf('An exception was thrown while getting the uncalled listeners (%s)', $e->getMessage()), array('exception' => $e)); } // unable to retrieve the uncalled listeners return array(); } $notCalled = array(); foreach ($allListeners as $eventName => $listeners) { foreach ($listeners as $listener) { $called = false; if (isset($this->called[$eventName])) { foreach ($this->called[$eventName] as $l) { if ($l->getWrappedListener() === $listener) { $called = true; break; } } } if (!$called) { $info = $this->getListenerInfo($listener, $eventName); $notCalled[$eventName.'.'.$info['pretty']] = $info; } } } return $notCalled; } /** * Proxies all method calls to the original event dispatcher. * * @param string $method The method name * @param array $arguments The method arguments * * @return mixed */ public function __call($method, $arguments) { return call_user_func_array(array($this->dispatcher, $method), $arguments); } /** * Called before dispatching the event. * * @param string $eventName The event name * @param Event $event The event */ protected function preDispatch($eventName, Event $event) { } /** * Called after dispatching the event. * * @param string $eventName The event name * @param Event $event The event */ protected function postDispatch($eventName, Event $event) { } private function preProcess($eventName) { foreach ($this->dispatcher->getListeners($eventName) as $listener) { $this->dispatcher->removeListener($eventName, $listener); $info = $this->getListenerInfo($listener, $eventName); $name = isset($info['class']) ? $info['class'] : $info['type']; $wrappedListener = new WrappedListener($listener, $name, $this->stopwatch, $this); $this->wrappedListeners[$eventName][] = $wrappedListener; $this->dispatcher->addListener($eventName, $wrappedListener); } } private function postProcess($eventName) { unset($this->wrappedListeners[$eventName]); $skipped = false; foreach ($this->dispatcher->getListeners($eventName) as $listener) { if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch. continue; } // Unwrap listener $this->dispatcher->removeListener($eventName, $listener); $this->dispatcher->addListener($eventName, $listener->getWrappedListener()); $info = $this->getListenerInfo($listener->getWrappedListener(), $eventName); if ($listener->wasCalled()) { if (null !== $this->logger) { $this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty'])); } if (!isset($this->called[$eventName])) { $this->called[$eventName] = new \SplObjectStorage(); } $this->called[$eventName]->attach($listener); } if (null !== $this->logger && $skipped) { $this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName)); } if ($listener->stoppedPropagation()) { if (null !== $this->logger) { $this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName)); } $skipped = true; } } } /** * Returns information about the listener. * * @param object $listener The listener * @param string $eventName The event name * * @return array Information about the listener */ private function getListenerInfo($listener, $eventName) { $info = array( 'event' => $eventName, ); if ($listener instanceof \Closure) { $info += array( 'type' => 'Closure', 'pretty' => 'closure', ); } elseif (is_string($listener)) { try { $r = new \ReflectionFunction($listener); $file = $r->getFileName(); $line = $r->getStartLine(); } catch (\ReflectionException $e) { $file = null; $line = null; } $info += array( 'type' => 'Function', 'function' => $listener, 'file' => $file, 'line' => $line, 'pretty' => $listener, ); } elseif (is_array($listener) || (is_object($listener) && is_callable($listener))) { if (!is_array($listener)) { $listener = array($listener, '__invoke'); } $class = is_object($listener[0]) ? get_class($listener[0]) : $listener[0]; try { $r = new \ReflectionMethod($class, $listener[1]); $file = $r->getFileName(); $line = $r->getStartLine(); } catch (\ReflectionException $e) { $file = null; $line = null; } $info += array( 'type' => 'Method', 'class' => $class, 'method' => $listener[1], 'file' => $file, 'line' => $line, 'pretty' => $class.'::'.$listener[1], ); } return $info; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\Debug; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * @author Fabien Potencier */ interface TraceableEventDispatcherInterface extends EventDispatcherInterface { /** * Gets the called listeners. * * @return array An array of called listeners */ public function getCalledListeners(); /** * Gets the not called listeners. * * @return array An array of not called listeners */ public function getNotCalledListeners(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\Debug; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * @author Fabien Potencier */ class WrappedListener { private $listener; private $name; private $called; private $stoppedPropagation; private $stopwatch; private $dispatcher; public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) { $this->listener = $listener; $this->name = $name; $this->stopwatch = $stopwatch; $this->dispatcher = $dispatcher; $this->called = false; $this->stoppedPropagation = false; } public function getWrappedListener() { return $this->listener; } public function wasCalled() { return $this->called; } public function stoppedPropagation() { return $this->stoppedPropagation; } public function __invoke(Event $event, $eventName, EventDispatcherInterface $dispatcher) { $this->called = true; $e = $this->stopwatch->start($this->name, 'event_listener'); call_user_func($this->listener, $event, $eventName, $this->dispatcher ?: $dispatcher); if ($e->isStarted()) { $e->stop(); } if ($event->isPropagationStopped()) { $this->stoppedPropagation = true; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; /** * Compiler pass to register tagged services for an event dispatcher. */ class RegisterListenersPass implements CompilerPassInterface { /** * @var string */ protected $dispatcherService; /** * @var string */ protected $listenerTag; /** * @var string */ protected $subscriberTag; /** * Constructor. * * @param string $dispatcherService Service name of the event dispatcher in processed container * @param string $listenerTag Tag name used for listener * @param string $subscriberTag Tag name used for subscribers */ public function __construct($dispatcherService = 'event_dispatcher', $listenerTag = 'kernel.event_listener', $subscriberTag = 'kernel.event_subscriber') { $this->dispatcherService = $dispatcherService; $this->listenerTag = $listenerTag; $this->subscriberTag = $subscriberTag; } public function process(ContainerBuilder $container) { if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) { return; } $definition = $container->findDefinition($this->dispatcherService); foreach ($container->findTaggedServiceIds($this->listenerTag) as $id => $events) { $def = $container->getDefinition($id); if (!$def->isPublic()) { throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event listeners are lazy-loaded.', $id)); } if ($def->isAbstract()) { throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event listeners are lazy-loaded.', $id)); } foreach ($events as $event) { $priority = isset($event['priority']) ? $event['priority'] : 0; if (!isset($event['event'])) { throw new \InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); } if (!isset($event['method'])) { $event['method'] = 'on'.preg_replace_callback(array( '/(?<=\b)[a-z]/i', '/[^a-z0-9]/i', ), function ($matches) { return strtoupper($matches[0]); }, $event['event']); $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); } $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority)); } } foreach ($container->findTaggedServiceIds($this->subscriberTag) as $id => $attributes) { $def = $container->getDefinition($id); if (!$def->isPublic()) { throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id)); } if ($def->isAbstract()) { throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event subscribers are lazy-loaded.', $id)); } // We must assume that the class value has been correctly filled, even if the service is created by a factory $class = $container->getParameterBag()->resolveValue($def->getClass()); $refClass = new \ReflectionClass($class); $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; if (!$refClass->implementsInterface($interface)) { throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); } $definition->addMethodCall('addSubscriberService', array($id, $class)); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * * Listeners are registered on the manager and events are dispatched through the * manager. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * @author Fabien Potencier * @author Jordi Boggiano * @author Jordan Alliot * * @api */ class EventDispatcher implements EventDispatcherInterface { private $listeners = array(); private $sorted = array(); /** * @see EventDispatcherInterface::dispatch() * * @api */ public function dispatch($eventName, Event $event = null) { if (null === $event) { $event = new Event(); } $event->setDispatcher($this); $event->setName($eventName); if (!isset($this->listeners[$eventName])) { return $event; } $this->doDispatch($this->getListeners($eventName), $eventName, $event); return $event; } /** * @see EventDispatcherInterface::getListeners() */ public function getListeners($eventName = null) { if (null !== $eventName) { if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } return $this->sorted[$eventName]; } foreach ($this->listeners as $eventName => $eventListeners) { if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } } return array_filter($this->sorted); } /** * @see EventDispatcherInterface::hasListeners() */ public function hasListeners($eventName = null) { return (bool) count($this->getListeners($eventName)); } /** * @see EventDispatcherInterface::addListener() * * @api */ public function addListener($eventName, $listener, $priority = 0) { $this->listeners[$eventName][$priority][] = $listener; unset($this->sorted[$eventName]); } /** * @see EventDispatcherInterface::removeListener() */ public function removeListener($eventName, $listener) { if (!isset($this->listeners[$eventName])) { return; } foreach ($this->listeners[$eventName] as $priority => $listeners) { if (false !== ($key = array_search($listener, $listeners, true))) { unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]); } } } /** * @see EventDispatcherInterface::addSubscriber() * * @api */ public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { $this->addListener($eventName, array($subscriber, $params)); } elseif (is_string($params[0])) { $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); } else { foreach ($params as $listener) { $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); } } } } /** * @see EventDispatcherInterface::removeSubscriber() */ public function removeSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (is_array($params) && is_array($params[0])) { foreach ($params as $listener) { $this->removeListener($eventName, array($subscriber, $listener[0])); } } else { $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0])); } } } /** * Triggers the listeners of an event. * * This method can be overridden to add functionality that is executed * for each listener. * * @param callable[] $listeners The event listeners. * @param string $eventName The name of the event to dispatch. * @param Event $event The event object to pass to the event handlers/listeners. */ protected function doDispatch($listeners, $eventName, Event $event) { foreach ($listeners as $listener) { call_user_func($listener, $event, $eventName, $this); if ($event->isPropagationStopped()) { break; } } } /** * Sorts the internal list of listeners for the given event by priority. * * @param string $eventName The name of the event. */ private function sortListeners($eventName) { $this->sorted[$eventName] = array(); if (isset($this->listeners[$eventName])) { krsort($this->listeners[$eventName]); $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Extends \SplFileInfo to support relative paths. * * @author Fabien Potencier */ class SplFileInfo extends \SplFileInfo { private $relativePath; private $relativePathname; /** * Constructor. * * @param string $file The file name * @param string $relativePath The relative path * @param string $relativePathname The relative path name */ public function __construct($file, $relativePath, $relativePathname) { parent::__construct($file); $this->relativePath = $relativePath; $this->relativePathname = $relativePathname; } /** * Returns the relative path. * * @return string the relative path */ public function getRelativePath() { return $this->relativePath; } /** * Returns the relative path name. * * @return string the relative path name */ public function getRelativePathname() { return $this->relativePathname; } /** * Returns the contents of the file. * * @return string the contents of the file * * @throws \RuntimeException */ public function getContents() { $level = error_reporting(0); $content = file_get_contents($this->getPathname()); error_reporting($level); if (false === $content) { $error = error_get_last(); throw new \RuntimeException($error['message']); } return $content; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Glob matches globbing patterns against text. * * if match_glob("foo.*", "foo.bar") echo "matched\n"; * * // prints foo.bar and foo.baz * $regex = glob_to_regex("foo.*"); * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t) * { * if (/$regex/) echo "matched: $car\n"; * } * * Glob implements glob(3) style matching that can be used to match * against text, rather than fetching names from a filesystem. * * Based on the Perl Text::Glob module. * * @author Fabien Potencier PHP port * @author Richard Clamp Perl version * @copyright 2004-2005 Fabien Potencier * @copyright 2002 Richard Clamp */ class Glob { /** * Returns a regexp which is the equivalent of the glob pattern. * * @param string $glob The glob pattern * @param bool $strictLeadingDot * @param bool $strictWildcardSlash * * @return string regex The regexp */ public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true) { $firstByte = true; $escaping = false; $inCurlies = 0; $regex = ''; $sizeGlob = strlen($glob); for ($i = 0; $i < $sizeGlob; ++$i) { $car = $glob[$i]; if ($firstByte) { if ($strictLeadingDot && '.' !== $car) { $regex .= '(?=[^\.])'; } $firstByte = false; } if ('/' === $car) { $firstByte = true; } if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { $regex .= "\\$car"; } elseif ('*' === $car) { $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); } elseif ('?' === $car) { $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); } elseif ('{' === $car) { $regex .= $escaping ? '\\{' : '('; if (!$escaping) { ++$inCurlies; } } elseif ('}' === $car && $inCurlies) { $regex .= $escaping ? '}' : ')'; if (!$escaping) { --$inCurlies; } } elseif (',' === $car && $inCurlies) { $regex .= $escaping ? ',' : '|'; } elseif ('\\' === $car) { if ($escaping) { $regex .= '\\\\'; $escaping = false; } else { $escaping = true; } continue; } else { $regex .= $car; } $escaping = false; } return '#^'.$regex.'$#'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Glob implements ValueInterface { /** * @var string */ private $pattern; /** * @param string $pattern */ public function __construct($pattern) { $this->pattern = $pattern; } /** * {@inheritdoc} */ public function render() { return $this->pattern; } /** * {@inheritdoc} */ public function renderPattern() { return $this->pattern; } /** * {@inheritdoc} */ public function getType() { return Expression::TYPE_GLOB; } /** * {@inheritdoc} */ public function isCaseSensitive() { return true; } /** * {@inheritdoc} */ public function prepend($expr) { $this->pattern = $expr.$this->pattern; return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->pattern .= $expr; return $this; } /** * Tests if glob is expandable ("*.{a,b}" syntax). * * @return bool */ public function isExpandable() { return false !== strpos($this->pattern, '{') && false !== strpos($this->pattern, '}'); } /** * @param bool $strictLeadingDot * @param bool $strictWildcardSlash * * @return Regex */ public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true) { $firstByte = true; $escaping = false; $inCurlies = 0; $regex = ''; $sizeGlob = strlen($this->pattern); for ($i = 0; $i < $sizeGlob; ++$i) { $car = $this->pattern[$i]; if ($firstByte) { if ($strictLeadingDot && '.' !== $car) { $regex .= '(?=[^\.])'; } $firstByte = false; } if ('/' === $car) { $firstByte = true; } if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { $regex .= "\\$car"; } elseif ('*' === $car) { $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); } elseif ('?' === $car) { $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); } elseif ('{' === $car) { $regex .= $escaping ? '\\{' : '('; if (!$escaping) { ++$inCurlies; } } elseif ('}' === $car && $inCurlies) { $regex .= $escaping ? '}' : ')'; if (!$escaping) { --$inCurlies; } } elseif (',' === $car && $inCurlies) { $regex .= $escaping ? ',' : '|'; } elseif ('\\' === $car) { if ($escaping) { $regex .= '\\\\'; $escaping = false; } else { $escaping = true; } continue; } else { $regex .= $car; } $escaping = false; } return new Regex('^'.$regex.'$'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ interface ValueInterface { /** * Renders string representation of expression. * * @return string */ public function render(); /** * Renders string representation of pattern. * * @return string */ public function renderPattern(); /** * Returns value case sensitivity. * * @return bool */ public function isCaseSensitive(); /** * Returns expression type. * * @return int */ public function getType(); /** * @param string $expr * * @return ValueInterface */ public function prepend($expr); /** * @param string $expr * * @return ValueInterface */ public function append($expr); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Expression implements ValueInterface { const TYPE_REGEX = 1; const TYPE_GLOB = 2; /** * @var ValueInterface */ private $value; /** * @param string $expr * * @return Expression */ public static function create($expr) { return new self($expr); } /** * @param string $expr */ public function __construct($expr) { try { $this->value = Regex::create($expr); } catch (\InvalidArgumentException $e) { $this->value = new Glob($expr); } } /** * @return string */ public function __toString() { return $this->render(); } /** * {@inheritdoc} */ public function render() { return $this->value->render(); } /** * {@inheritdoc} */ public function renderPattern() { return $this->value->renderPattern(); } /** * @return bool */ public function isCaseSensitive() { return $this->value->isCaseSensitive(); } /** * @return int */ public function getType() { return $this->value->getType(); } /** * {@inheritdoc} */ public function prepend($expr) { $this->value->prepend($expr); return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->value->append($expr); return $this; } /** * @return bool */ public function isRegex() { return self::TYPE_REGEX === $this->value->getType(); } /** * @return bool */ public function isGlob() { return self::TYPE_GLOB === $this->value->getType(); } /** * @throws \LogicException * * @return Glob */ public function getGlob() { if (self::TYPE_GLOB !== $this->value->getType()) { throw new \LogicException('Regex can\'t be transformed to glob.'); } return $this->value; } /** * @return Regex */ public function getRegex() { return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Expression; /** * @author Jean-François Simon */ class Regex implements ValueInterface { const START_FLAG = '^'; const END_FLAG = '$'; const BOUNDARY = '~'; const JOKER = '.*'; const ESCAPING = '\\'; /** * @var string */ private $pattern; /** * @var array */ private $options; /** * @var bool */ private $startFlag; /** * @var bool */ private $endFlag; /** * @var bool */ private $startJoker; /** * @var bool */ private $endJoker; /** * @param string $expr * * @return Regex * * @throws \InvalidArgumentException */ public static function create($expr) { if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) { $start = substr($m[1], 0, 1); $end = substr($m[1], -1); if ( ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start)) || ($start === '{' && $end === '}') || ($start === '(' && $end === ')') ) { return new self(substr($m[1], 1, -1), $m[2], $end); } } throw new \InvalidArgumentException('Given expression is not a regex.'); } /** * @param string $pattern * @param string $options * @param string $delimiter */ public function __construct($pattern, $options = '', $delimiter = null) { if (null !== $delimiter) { // removes delimiter escaping $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern); } $this->parsePattern($pattern); $this->options = $options; } /** * @return string */ public function __toString() { return $this->render(); } /** * {@inheritdoc} */ public function render() { return self::BOUNDARY .$this->renderPattern() .self::BOUNDARY .$this->options; } /** * {@inheritdoc} */ public function renderPattern() { return ($this->startFlag ? self::START_FLAG : '') .($this->startJoker ? self::JOKER : '') .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern) .($this->endJoker ? self::JOKER : '') .($this->endFlag ? self::END_FLAG : ''); } /** * {@inheritdoc} */ public function isCaseSensitive() { return !$this->hasOption('i'); } /** * {@inheritdoc} */ public function getType() { return Expression::TYPE_REGEX; } /** * {@inheritdoc} */ public function prepend($expr) { $this->pattern = $expr.$this->pattern; return $this; } /** * {@inheritdoc} */ public function append($expr) { $this->pattern .= $expr; return $this; } /** * @param string $option * * @return bool */ public function hasOption($option) { return false !== strpos($this->options, $option); } /** * @param string $option * * @return Regex */ public function addOption($option) { if (!$this->hasOption($option)) { $this->options .= $option; } return $this; } /** * @param string $option * * @return Regex */ public function removeOption($option) { $this->options = str_replace($option, '', $this->options); return $this; } /** * @param bool $startFlag * * @return Regex */ public function setStartFlag($startFlag) { $this->startFlag = $startFlag; return $this; } /** * @return bool */ public function hasStartFlag() { return $this->startFlag; } /** * @param bool $endFlag * * @return Regex */ public function setEndFlag($endFlag) { $this->endFlag = (bool) $endFlag; return $this; } /** * @return bool */ public function hasEndFlag() { return $this->endFlag; } /** * @param bool $startJoker * * @return Regex */ public function setStartJoker($startJoker) { $this->startJoker = $startJoker; return $this; } /** * @return bool */ public function hasStartJoker() { return $this->startJoker; } /** * @param bool $endJoker * * @return Regex */ public function setEndJoker($endJoker) { $this->endJoker = (bool) $endJoker; return $this; } /** * @return bool */ public function hasEndJoker() { return $this->endJoker; } /** * @param array $replacement * * @return Regex */ public function replaceJokers($replacement) { $replace = function ($subject) use ($replacement) { $subject = $subject[0]; $replace = 0 === substr_count($subject, '\\') % 2; return $replace ? str_replace('.', $replacement, $subject) : $subject; }; $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern); return $this; } /** * @param string $pattern */ private function parsePattern($pattern) { if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) { $pattern = substr($pattern, 1); } if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) { $pattern = substr($pattern, 2); } if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) { $pattern = substr($pattern, 0, -1); } if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) { $pattern = substr($pattern, 0, -2); } $this->pattern = $pattern; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Shell; /** * @author Jean-François Simon */ class Shell { const TYPE_UNIX = 1; const TYPE_DARWIN = 2; const TYPE_CYGWIN = 3; const TYPE_WINDOWS = 4; const TYPE_BSD = 5; /** * @var string|null */ private $type; /** * Returns guessed OS type. * * @return int */ public function getType() { if (null === $this->type) { $this->type = $this->guessType(); } return $this->type; } /** * Tests if a command is available. * * @param string $command * * @return bool */ public function testCommand($command) { if (!function_exists('exec')) { return false; } // todo: find a better way (command could not be available) $testCommand = 'which '; if (self::TYPE_WINDOWS === $this->type) { $testCommand = 'where '; } $command = escapeshellcmd($command); exec($testCommand.$command, $output, $code); return 0 === $code && count($output) > 0; } /** * Guesses OS type. * * @return int */ private function guessType() { $os = strtolower(PHP_OS); if (false !== strpos($os, 'cygwin')) { return self::TYPE_CYGWIN; } if (false !== strpos($os, 'darwin')) { return self::TYPE_DARWIN; } if (false !== strpos($os, 'bsd')) { return self::TYPE_BSD; } if (0 === strpos($os, 'win')) { return self::TYPE_WINDOWS; } return self::TYPE_UNIX; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Shell; /** * @author Jean-François Simon */ class Command { /** * @var Command|null */ private $parent; /** * @var array */ private $bits = array(); /** * @var array */ private $labels = array(); /** * @var \Closure|null */ private $errorHandler; /** * Constructor. * * @param Command|null $parent Parent command */ public function __construct(Command $parent = null) { $this->parent = $parent; } /** * Returns command as string. * * @return string */ public function __toString() { return $this->join(); } /** * Creates a new Command instance. * * @param Command|null $parent Parent command * * @return Command New Command instance */ public static function create(Command $parent = null) { return new self($parent); } /** * Escapes special chars from input. * * @param string $input A string to escape * * @return string The escaped string */ public static function escape($input) { return escapeshellcmd($input); } /** * Quotes input. * * @param string $input An argument string * * @return string The quoted string */ public static function quote($input) { return escapeshellarg($input); } /** * Appends a string or a Command instance. * * @param string|Command $bit * * @return Command The current Command instance */ public function add($bit) { $this->bits[] = $bit; return $this; } /** * Prepends a string or a command instance. * * @param string|Command $bit * * @return Command The current Command instance */ public function top($bit) { array_unshift($this->bits, $bit); foreach ($this->labels as $label => $index) { $this->labels[$label] += 1; } return $this; } /** * Appends an argument, will be quoted. * * @param string $arg * * @return Command The current Command instance */ public function arg($arg) { $this->bits[] = self::quote($arg); return $this; } /** * Appends escaped special command chars. * * @param string $esc * * @return Command The current Command instance */ public function cmd($esc) { $this->bits[] = self::escape($esc); return $this; } /** * Inserts a labeled command to feed later. * * @param string $label The unique label * * @return Command The current Command instance * * @throws \RuntimeException If label already exists */ public function ins($label) { if (isset($this->labels[$label])) { throw new \RuntimeException(sprintf('Label "%s" already exists.', $label)); } $this->bits[] = self::create($this); $this->labels[$label] = count($this->bits) - 1; return $this->bits[$this->labels[$label]]; } /** * Retrieves a previously labeled command. * * @param string $label * * @return Command The labeled command * * @throws \RuntimeException */ public function get($label) { if (!isset($this->labels[$label])) { throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label)); } return $this->bits[$this->labels[$label]]; } /** * Returns parent command (if any). * * @return Command Parent command * * @throws \RuntimeException If command has no parent */ public function end() { if (null === $this->parent) { throw new \RuntimeException('Calling end on root command doesn\'t make sense.'); } return $this->parent; } /** * Counts bits stored in command. * * @return int The bits count */ public function length() { return count($this->bits); } /** * @param \Closure $errorHandler * * @return Command */ public function setErrorHandler(\Closure $errorHandler) { $this->errorHandler = $errorHandler; return $this; } /** * @return \Closure|null */ public function getErrorHandler() { return $this->errorHandler; } /** * Executes current command. * * @return array The command result * * @throws \RuntimeException */ public function execute() { if (null === $errorHandler = $this->errorHandler) { exec($this->join(), $output); } else { $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes); $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY); if ($error = stream_get_contents($pipes[2])) { $errorHandler($error); } proc_close($process); } return $output ?: array(); } /** * Joins bits. * * @return string */ public function join() { return implode(' ', array_filter( array_map(function ($bit) { return $bit instanceof Command ? $bit->join() : ($bit ?: null); }, $this->bits), function ($bit) { return null !== $bit; } )); } /** * Insert a string or a Command instance before the bit at given position $index (index starts from 0). * * @param string|Command $bit * @param int $index * * @return Command The current Command instance */ public function addAtIndex($bit, $index) { array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit); return $this; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * DateCompare compiles date comparisons. * * @author Fabien Potencier */ class DateComparator extends Comparator { /** * Constructor. * * @param string $test A comparison string * * @throws \InvalidArgumentException If the test is not understood */ public function __construct($test) { if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); } try { $date = new \DateTime($matches[2]); $target = $date->format('U'); } catch (\Exception $e) { throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); } $operator = isset($matches[1]) ? $matches[1] : '=='; if ('since' === $operator || 'after' === $operator) { $operator = '>'; } if ('until' === $operator || 'before' === $operator) { $operator = '<'; } $this->setOperator($operator); $this->setTarget($target); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * Comparator. * * @author Fabien Potencier */ class Comparator { private $target; private $operator = '=='; /** * Gets the target value. * * @return string The target value */ public function getTarget() { return $this->target; } /** * Sets the target value. * * @param string $target The target value */ public function setTarget($target) { $this->target = $target; } /** * Gets the comparison operator. * * @return string The operator */ public function getOperator() { return $this->operator; } /** * Sets the comparison operator. * * @param string $operator A valid operator * * @throws \InvalidArgumentException */ public function setOperator($operator) { if (!$operator) { $operator = '=='; } if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) { throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); } $this->operator = $operator; } /** * Tests against the target. * * @param mixed $test A test value * * @return bool */ public function test($test) { switch ($this->operator) { case '>': return $test > $this->target; case '>=': return $test >= $this->target; case '<': return $test < $this->target; case '<=': return $test <= $this->target; case '!=': return $test != $this->target; } return $test == $this->target; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * NumberComparator compiles a simple comparison to an anonymous * subroutine, which you can call with a value to be tested again. * * Now this would be very pointless, if NumberCompare didn't understand * magnitudes. * * The target value may use magnitudes of kilobytes (k, ki), * megabytes (m, mi), or gigabytes (g, gi). Those suffixed * with an i use the appropriate 2**n version in accordance with the * IEC standard: http://physics.nist.gov/cuu/Units/binary.html * * Based on the Perl Number::Compare module. * * @author Fabien Potencier PHP port * @author Richard Clamp Perl version * @copyright 2004-2005 Fabien Potencier * @copyright 2002 Richard Clamp * * @see http://physics.nist.gov/cuu/Units/binary.html */ class NumberComparator extends Comparator { /** * Constructor. * * @param string $test A comparison string * * @throws \InvalidArgumentException If the test is not understood */ public function __construct($test) { if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test)); } $target = $matches[2]; if (!is_numeric($target)) { throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); } if (isset($matches[3])) { // magnitude switch (strtolower($matches[3])) { case 'k': $target *= 1000; break; case 'ki': $target *= 1024; break; case 'm': $target *= 1000000; break; case 'mi': $target *= 1024 * 1024; break; case 'g': $target *= 1000000000; break; case 'gi': $target *= 1024 * 1024 * 1024; break; } } $this->setTarget($target); $this->setOperator(isset($matches[1]) ? $matches[1] : '=='); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * DepthRangeFilterIterator limits the directory depth. * * @author Fabien Potencier */ class DepthRangeFilterIterator extends FilterIterator { private $minDepth = 0; /** * Constructor. * * @param \RecursiveIteratorIterator $iterator The Iterator to filter * @param int $minDepth The min depth * @param int $maxDepth The max depth */ public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX) { $this->minDepth = $minDepth; $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { return $this->getInnerIterator()->getDepth() >= $this->minDepth; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\SplFileInfo; /** * Iterate over shell command result. * * @author Jean-François Simon */ class FilePathsIterator extends \ArrayIterator { /** * @var string */ private $baseDir; /** * @var int */ private $baseDirLength; /** * @var string */ private $subPath; /** * @var string */ private $subPathname; /** * @var SplFileInfo */ private $current; /** * @param array $paths List of paths returned by shell command * @param string $baseDir Base dir for relative path building */ public function __construct(array $paths, $baseDir) { $this->baseDir = $baseDir; $this->baseDirLength = strlen($baseDir); parent::__construct($paths); } /** * @param string $name * @param array $arguments * * @return mixed */ public function __call($name, array $arguments) { return call_user_func_array(array($this->current(), $name), $arguments); } /** * Return an instance of SplFileInfo with support for relative paths. * * @return SplFileInfo File information */ public function current() { return $this->current; } /** * @return string */ public function key() { return $this->current->getPathname(); } public function next() { parent::next(); $this->buildProperties(); } public function rewind() { parent::rewind(); $this->buildProperties(); } /** * @return string */ public function getSubPath() { return $this->subPath; } /** * @return string */ public function getSubPathname() { return $this->subPathname; } private function buildProperties() { $absolutePath = parent::current(); if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) { $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\'); $dir = dirname($this->subPathname); $this->subPath = '.' === $dir ? '' : $dir; } else { $this->subPath = $this->subPathname = ''; } $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * This iterator just overrides the rewind method in order to correct a PHP bug. * * @see https://bugs.php.net/bug.php?id=49104 * * @author Alex Bogomazov */ abstract class FilterIterator extends \FilterIterator { /** * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after * rewind in some cases. * * @see FilterIterator::rewind() */ public function rewind() { $iterator = $this; while ($iterator instanceof \OuterIterator) { $innerIterator = $iterator->getInnerIterator(); if ($innerIterator instanceof RecursiveDirectoryIterator) { if ($innerIterator->isRewindable()) { $innerIterator->next(); $innerIterator->rewind(); } } elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) { $iterator->getInnerIterator()->next(); $iterator->getInnerIterator()->rewind(); } $iterator = $iterator->getInnerIterator(); } parent::rewind(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Expression\Expression; /** * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). * * @author Fabien Potencier */ abstract class MultiplePcreFilterIterator extends FilterIterator { protected $matchRegexps = array(); protected $noMatchRegexps = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $matchPatterns An array of patterns that need to match * @param array $noMatchPatterns An array of patterns that need to not match */ public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) { foreach ($matchPatterns as $pattern) { $this->matchRegexps[] = $this->toRegex($pattern); } foreach ($noMatchPatterns as $pattern) { $this->noMatchRegexps[] = $this->toRegex($pattern); } parent::__construct($iterator); } /** * Checks whether the string is a regex. * * @param string $str * * @return bool Whether the given string is a regex */ protected function isRegex($str) { return Expression::create($str)->isRegex(); } /** * Converts string into regexp. * * @param string $str Pattern * * @return string regexp corresponding to a given string */ abstract protected function toRegex($str); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * PathFilterIterator filters files by path patterns (e.g. some/special/dir). * * @author Fabien Potencier * @author Włodzimierz Gajda */ class PathFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $filename = $this->current()->getRelativePathname(); if ('\\' === DIRECTORY_SEPARATOR) { $filename = strtr($filename, '\\', '/'); } // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $filename)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $filename)) { return true; } } } return $match; } /** * Converts strings to regexp. * * PCRE patterns are left unchanged. * * Default conversion: * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/' * * Use only / as directory separator (on Windows also). * * @param string $str Pattern: regexp or dirname. * * @return string regexp corresponding to a given string or regexp */ protected function toRegex($str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Expression\Expression; /** * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). * * @author Fabien Potencier */ class FilenameFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $filename = $this->current()->getFilename(); // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $filename)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $filename)) { return true; } } } return $match; } /** * Converts glob to regexp. * * PCRE patterns are left unchanged. * Glob strings are transformed with Glob::toRegex(). * * @param string $str Pattern: glob or regexp * * @return string regexp corresponding to a given glob or regexp */ protected function toRegex($str) { return Expression::create($str)->getRegex()->render(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Comparator\NumberComparator; /** * SizeRangeFilterIterator filters out files that are not in the given size range. * * @author Fabien Potencier */ class SizeRangeFilterIterator extends FilterIterator { private $comparators = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param NumberComparator[] $comparators An array of NumberComparator instances */ public function __construct(\Iterator $iterator, array $comparators) { $this->comparators = $comparators; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (!$fileinfo->isFile()) { return true; } $filesize = $fileinfo->getSize(); foreach ($this->comparators as $compare) { if (!$compare->test($filesize)) { return false; } } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * SortableIterator applies a sort on a given Iterator. * * @author Fabien Potencier */ class SortableIterator implements \IteratorAggregate { const SORT_BY_NAME = 1; const SORT_BY_TYPE = 2; const SORT_BY_ACCESSED_TIME = 3; const SORT_BY_CHANGED_TIME = 4; const SORT_BY_MODIFIED_TIME = 5; private $iterator; private $sort; /** * Constructor. * * @param \Traversable $iterator The Iterator to filter * @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) * * @throws \InvalidArgumentException */ public function __construct(\Traversable $iterator, $sort) { $this->iterator = $iterator; if (self::SORT_BY_NAME === $sort) { $this->sort = function ($a, $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }; } elseif (self::SORT_BY_TYPE === $sort) { $this->sort = function ($a, $b) { if ($a->isDir() && $b->isFile()) { return -1; } elseif ($a->isFile() && $b->isDir()) { return 1; } return strcmp($a->getRealpath(), $b->getRealpath()); }; } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getATime() - $b->getATime()); }; } elseif (self::SORT_BY_CHANGED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getCTime() - $b->getCTime()); }; } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { $this->sort = function ($a, $b) { return ($a->getMTime() - $b->getMTime()); }; } elseif (is_callable($sort)) { $this->sort = $sort; } else { throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.'); } } public function getIterator() { $array = iterator_to_array($this->iterator, true); uasort($array, $this->sort); return new \ArrayIterator($array); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). * * @author Fabien Potencier * @author Włodzimierz Gajda */ class FilecontentFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { if (!$this->matchRegexps && !$this->noMatchRegexps) { return true; } $fileinfo = $this->current(); if ($fileinfo->isDir() || !$fileinfo->isReadable()) { return false; } $content = $fileinfo->getContents(); if (!$content) { return false; } // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $content)) { return false; } } // should at least match one rule $match = true; if ($this->matchRegexps) { $match = false; foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $content)) { return true; } } } return $match; } /** * Converts string to regexp if necessary. * * @param string $str Pattern: string or regexp * * @return string regexp corresponding to a given string or regexp */ protected function toRegex($str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Comparator\DateComparator; /** * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). * * @author Fabien Potencier */ class DateRangeFilterIterator extends FilterIterator { private $comparators = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param DateComparator[] $comparators An array of DateComparator instances */ public function __construct(\Iterator $iterator, array $comparators) { $this->comparators = $comparators; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (!file_exists($fileinfo->getRealPath())) { return false; } $filedate = $fileinfo->getMTime(); foreach ($this->comparators as $compare) { if (!$compare->test($filedate)) { return false; } } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * FileTypeFilterIterator only keeps files, directories, or both. * * @author Fabien Potencier */ class FileTypeFilterIterator extends FilterIterator { const ONLY_FILES = 1; const ONLY_DIRECTORIES = 2; private $mode; /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) */ public function __construct(\Iterator $iterator, $mode) { $this->mode = $mode; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) { return false; } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) { return false; } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * ExcludeDirectoryFilterIterator filters out directories. * * @author Fabien Potencier */ class ExcludeDirectoryFilterIterator extends FilterIterator { private $patterns = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $directories An array of directories to exclude */ public function __construct(\Iterator $iterator, array $directories) { foreach ($directories as $directory) { $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#'; } parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); $path = strtr($path, '\\', '/'); foreach ($this->patterns as $pattern) { if (preg_match($pattern, $path)) { return false; } } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * CustomFilterIterator filters files by applying anonymous functions. * * The anonymous function receives a \SplFileInfo and must return false * to remove files. * * @author Fabien Potencier */ class CustomFilterIterator extends FilterIterator { private $filters = array(); /** * Constructor. * * @param \Iterator $iterator The Iterator to filter * @param array $filters An array of PHP callbacks * * @throws \InvalidArgumentException */ public function __construct(\Iterator $iterator, array $filters) { foreach ($filters as $filter) { if (!is_callable($filter)) { throw new \InvalidArgumentException('Invalid PHP callback.'); } } $this->filters = $filters; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool true if the value should be kept, false otherwise */ public function accept() { $fileinfo = $this->current(); foreach ($this->filters as $filter) { if (false === call_user_func($filter, $fileinfo)) { return false; } } return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Exception\AccessDeniedException; use Symfony\Component\Finder\SplFileInfo; /** * Extends the \RecursiveDirectoryIterator to support relative paths. * * @author Victor Berchet */ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator { /** * @var bool */ private $ignoreUnreadableDirs; /** * @var bool */ private $rewindable; /** * Constructor. * * @param string $path * @param int $flags * @param bool $ignoreUnreadableDirs * * @throws \RuntimeException */ public function __construct($path, $flags, $ignoreUnreadableDirs = false) { if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { throw new \RuntimeException('This iterator only support returning current as fileinfo.'); } parent::__construct($path, $flags); $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; } /** * Return an instance of SplFileInfo with support for relative paths. * * @return SplFileInfo File information */ public function current() { return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname()); } /** * @return \RecursiveIterator * * @throws AccessDeniedException */ public function getChildren() { try { $children = parent::getChildren(); if ($children instanceof self) { // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; } return $children; } catch (\UnexpectedValueException $e) { if ($this->ignoreUnreadableDirs) { // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. return new \RecursiveArrayIterator(array()); } else { throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); } } } /** * Do nothing for non rewindable stream. */ public function rewind() { if (false === $this->isRewindable()) { return; } // @see https://bugs.php.net/bug.php?id=49104 parent::next(); parent::rewind(); } /** * Checks if the stream is rewindable. * * @return bool true when the stream is rewindable, false otherwise */ public function isRewindable() { if (null !== $this->rewindable) { return $this->rewindable; } if (false !== $stream = @opendir($this->getPath())) { $infos = stream_get_meta_data($stream); closedir($stream); if ($infos['seekable']) { return $this->rewindable = true; } } return $this->rewindable = false; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; use Symfony\Component\Finder\Adapter\AdapterInterface; use Symfony\Component\Finder\Adapter\GnuFindAdapter; use Symfony\Component\Finder\Adapter\BsdFindAdapter; use Symfony\Component\Finder\Adapter\PhpAdapter; use Symfony\Component\Finder\Comparator\DateComparator; use Symfony\Component\Finder\Comparator\NumberComparator; use Symfony\Component\Finder\Exception\ExceptionInterface; use Symfony\Component\Finder\Iterator\CustomFilterIterator; use Symfony\Component\Finder\Iterator\DateRangeFilterIterator; use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator; use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator; use Symfony\Component\Finder\Iterator\FilecontentFilterIterator; use Symfony\Component\Finder\Iterator\FilenameFilterIterator; use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator; use Symfony\Component\Finder\Iterator\SortableIterator; /** * Finder allows to build rules to find files and directories. * * It is a thin wrapper around several specialized iterator classes. * * All rules may be invoked several times. * * All methods return the current Finder object to allow easy chaining: * * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); * * @author Fabien Potencier * * @api */ class Finder implements \IteratorAggregate, \Countable { const IGNORE_VCS_FILES = 1; const IGNORE_DOT_FILES = 2; private $mode = 0; private $names = array(); private $notNames = array(); private $exclude = array(); private $filters = array(); private $depths = array(); private $sizes = array(); private $followLinks = false; private $sort = false; private $ignore = 0; private $dirs = array(); private $dates = array(); private $iterators = array(); private $contains = array(); private $notContains = array(); private $adapters = array(); private $paths = array(); private $notPaths = array(); private $ignoreUnreadableDirs = false; private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'); /** * Constructor. */ public function __construct() { $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; $this ->addAdapter(new GnuFindAdapter()) ->addAdapter(new BsdFindAdapter()) ->addAdapter(new PhpAdapter(), -50) ->setAdapter('php') ; } /** * Creates a new Finder. * * @return Finder A new Finder instance * * @api */ public static function create() { return new static(); } /** * Registers a finder engine implementation. * * @param AdapterInterface $adapter An adapter instance * @param int $priority Highest is selected first * * @return Finder The current Finder instance */ public function addAdapter(AdapterInterface $adapter, $priority = 0) { $this->adapters[$adapter->getName()] = array( 'adapter' => $adapter, 'priority' => $priority, 'selected' => false, ); return $this->sortAdapters(); } /** * Sets the selected adapter to the best one according to the current platform the code is run on. * * @return Finder The current Finder instance */ public function useBestAdapter() { $this->resetAdapterSelection(); return $this->sortAdapters(); } /** * Selects the adapter to use. * * @param string $name * * @throws \InvalidArgumentException * * @return Finder The current Finder instance */ public function setAdapter($name) { if (!isset($this->adapters[$name])) { throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name)); } $this->resetAdapterSelection(); $this->adapters[$name]['selected'] = true; return $this->sortAdapters(); } /** * Removes all adapters registered in the finder. * * @return Finder The current Finder instance */ public function removeAdapters() { $this->adapters = array(); return $this; } /** * Returns registered adapters ordered by priority without extra information. * * @return AdapterInterface[] */ public function getAdapters() { return array_values(array_map(function (array $adapter) { return $adapter['adapter']; }, $this->adapters)); } /** * Restricts the matching to directories only. * * @return Finder The current Finder instance * * @api */ public function directories() { $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES; return $this; } /** * Restricts the matching to files only. * * @return Finder The current Finder instance * * @api */ public function files() { $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES; return $this; } /** * Adds tests for the directory depth. * * Usage: * * $finder->depth('> 1') // the Finder will start matching at level 1. * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. * * @param int $level The depth level expression * * @return Finder The current Finder instance * * @see DepthRangeFilterIterator * @see NumberComparator * * @api */ public function depth($level) { $this->depths[] = new Comparator\NumberComparator($level); return $this; } /** * Adds tests for file dates (last modified). * * The date must be something that strtotime() is able to parse: * * $finder->date('since yesterday'); * $finder->date('until 2 days ago'); * $finder->date('> now - 2 hours'); * $finder->date('>= 2005-10-15'); * * @param string $date A date range string * * @return Finder The current Finder instance * * @see strtotime * @see DateRangeFilterIterator * @see DateComparator * * @api */ public function date($date) { $this->dates[] = new Comparator\DateComparator($date); return $this; } /** * Adds rules that files must match. * * You can use patterns (delimited with / sign), globs or simple strings. * * $finder->name('*.php') * $finder->name('/\.php$/') // same as above * $finder->name('test.php') * * @param string $pattern A pattern (a regexp, a glob, or a string) * * @return Finder The current Finder instance * * @see FilenameFilterIterator * * @api */ public function name($pattern) { $this->names[] = $pattern; return $this; } /** * Adds rules that files must not match. * * @param string $pattern A pattern (a regexp, a glob, or a string) * * @return Finder The current Finder instance * * @see FilenameFilterIterator * * @api */ public function notName($pattern) { $this->notNames[] = $pattern; return $this; } /** * Adds tests that file contents must match. * * Strings or PCRE patterns can be used: * * $finder->contains('Lorem ipsum') * $finder->contains('/Lorem ipsum/i') * * @param string $pattern A pattern (string or regexp) * * @return Finder The current Finder instance * * @see FilecontentFilterIterator */ public function contains($pattern) { $this->contains[] = $pattern; return $this; } /** * Adds tests that file contents must not match. * * Strings or PCRE patterns can be used: * * $finder->notContains('Lorem ipsum') * $finder->notContains('/Lorem ipsum/i') * * @param string $pattern A pattern (string or regexp) * * @return Finder The current Finder instance * * @see FilecontentFilterIterator */ public function notContains($pattern) { $this->notContains[] = $pattern; return $this; } /** * Adds rules that filenames must match. * * You can use patterns (delimited with / sign) or simple strings. * * $finder->path('some/special/dir') * $finder->path('/some\/special\/dir/') // same as above * * Use only / as dirname separator. * * @param string $pattern A pattern (a regexp or a string) * * @return Finder The current Finder instance * * @see FilenameFilterIterator */ public function path($pattern) { $this->paths[] = $pattern; return $this; } /** * Adds rules that filenames must not match. * * You can use patterns (delimited with / sign) or simple strings. * * $finder->notPath('some/special/dir') * $finder->notPath('/some\/special\/dir/') // same as above * * Use only / as dirname separator. * * @param string $pattern A pattern (a regexp or a string) * * @return Finder The current Finder instance * * @see FilenameFilterIterator */ public function notPath($pattern) { $this->notPaths[] = $pattern; return $this; } /** * Adds tests for file sizes. * * $finder->size('> 10K'); * $finder->size('<= 1Ki'); * $finder->size(4); * * @param string $size A size range string * * @return Finder The current Finder instance * * @see SizeRangeFilterIterator * @see NumberComparator * * @api */ public function size($size) { $this->sizes[] = new Comparator\NumberComparator($size); return $this; } /** * Excludes directories. * * @param string|array $dirs A directory path or an array of directories * * @return Finder The current Finder instance * * @see ExcludeDirectoryFilterIterator * * @api */ public function exclude($dirs) { $this->exclude = array_merge($this->exclude, (array) $dirs); return $this; } /** * Excludes "hidden" directories and files (starting with a dot). * * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not * * @return Finder The current Finder instance * * @see ExcludeDirectoryFilterIterator * * @api */ public function ignoreDotFiles($ignoreDotFiles) { if ($ignoreDotFiles) { $this->ignore |= static::IGNORE_DOT_FILES; } else { $this->ignore &= ~static::IGNORE_DOT_FILES; } return $this; } /** * Forces the finder to ignore version control directories. * * @param bool $ignoreVCS Whether to exclude VCS files or not * * @return Finder The current Finder instance * * @see ExcludeDirectoryFilterIterator * * @api */ public function ignoreVCS($ignoreVCS) { if ($ignoreVCS) { $this->ignore |= static::IGNORE_VCS_FILES; } else { $this->ignore &= ~static::IGNORE_VCS_FILES; } return $this; } /** * Adds VCS patterns. * * @see ignoreVCS() * * @param string|string[] $pattern VCS patterns to ignore */ public static function addVCSPattern($pattern) { foreach ((array) $pattern as $p) { self::$vcsPatterns[] = $p; } self::$vcsPatterns = array_unique(self::$vcsPatterns); } /** * Sorts files and directories by an anonymous function. * * The anonymous function receives two \SplFileInfo instances to compare. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @param \Closure $closure An anonymous function * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sort(\Closure $closure) { $this->sort = $closure; return $this; } /** * Sorts files and directories by name. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sortByName() { $this->sort = Iterator\SortableIterator::SORT_BY_NAME; return $this; } /** * Sorts files and directories by type (directories before files), then by name. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sortByType() { $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; return $this; } /** * Sorts files and directories by the last accessed time. * * This is the time that the file was last accessed, read or written to. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sortByAccessedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; return $this; } /** * Sorts files and directories by the last inode changed time. * * This is the time that the inode information was last modified (permissions, owner, group or other metadata). * * On Windows, since inode is not available, changed time is actually the file creation time. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sortByChangedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; return $this; } /** * Sorts files and directories by the last modified time. * * This is the last time the actual contents of the file were last modified. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return Finder The current Finder instance * * @see SortableIterator * * @api */ public function sortByModifiedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; return $this; } /** * Filters the iterator with an anonymous function. * * The anonymous function receives a \SplFileInfo and must return false * to remove files. * * @param \Closure $closure An anonymous function * * @return Finder The current Finder instance * * @see CustomFilterIterator * * @api */ public function filter(\Closure $closure) { $this->filters[] = $closure; return $this; } /** * Forces the following of symlinks. * * @return Finder The current Finder instance * * @api */ public function followLinks() { $this->followLinks = true; return $this; } /** * Tells finder to ignore unreadable directories. * * By default, scanning unreadable directories content throws an AccessDeniedException. * * @param bool $ignore * * @return Finder The current Finder instance */ public function ignoreUnreadableDirs($ignore = true) { $this->ignoreUnreadableDirs = (bool) $ignore; return $this; } /** * Searches files and directories which match defined rules. * * @param string|array $dirs A directory path or an array of directories * * @return Finder The current Finder instance * * @throws \InvalidArgumentException if one of the directories does not exist * * @api */ public function in($dirs) { $resolvedDirs = array(); foreach ((array) $dirs as $dir) { if (is_dir($dir)) { $resolvedDirs[] = $dir; } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) { $resolvedDirs = array_merge($resolvedDirs, $glob); } else { throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir)); } } $this->dirs = array_merge($this->dirs, $resolvedDirs); return $this; } /** * Returns an Iterator for the current Finder configuration. * * This method implements the IteratorAggregate interface. * * @return \Iterator An iterator * * @throws \LogicException if the in() method has not been called */ public function getIterator() { if (0 === count($this->dirs) && 0 === count($this->iterators)) { throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.'); } if (1 === count($this->dirs) && 0 === count($this->iterators)) { return $this->searchInDirectory($this->dirs[0]); } $iterator = new \AppendIterator(); foreach ($this->dirs as $dir) { $iterator->append($this->searchInDirectory($dir)); } foreach ($this->iterators as $it) { $iterator->append($it); } return $iterator; } /** * Appends an existing set of files/directories to the finder. * * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. * * @param mixed $iterator * * @return Finder The finder * * @throws \InvalidArgumentException When the given argument is not iterable. */ public function append($iterator) { if ($iterator instanceof \IteratorAggregate) { $this->iterators[] = $iterator->getIterator(); } elseif ($iterator instanceof \Iterator) { $this->iterators[] = $iterator; } elseif ($iterator instanceof \Traversable || is_array($iterator)) { $it = new \ArrayIterator(); foreach ($iterator as $file) { $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file)); } $this->iterators[] = $it; } else { throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); } return $this; } /** * Counts all the results collected by the iterators. * * @return int */ public function count() { return iterator_count($this->getIterator()); } /** * @return Finder The current Finder instance */ private function sortAdapters() { uasort($this->adapters, function (array $a, array $b) { if ($a['selected'] || $b['selected']) { return $a['selected'] ? -1 : 1; } return $a['priority'] > $b['priority'] ? -1 : 1; }); return $this; } /** * @param $dir * * @return \Iterator * * @throws \RuntimeException When none of the adapters are supported */ private function searchInDirectory($dir) { if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { $this->exclude = array_merge($this->exclude, self::$vcsPatterns); } if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { $this->notPaths[] = '#(^|/)\..+(/|$)#'; } foreach ($this->adapters as $adapter) { if ($adapter['adapter']->isSupported()) { try { return $this ->buildAdapter($adapter['adapter']) ->searchInDirectory($dir); } catch (ExceptionInterface $e) { } } } throw new \RuntimeException('No supported adapter found.'); } /** * @param AdapterInterface $adapter * * @return AdapterInterface */ private function buildAdapter(AdapterInterface $adapter) { return $adapter ->setFollowLinks($this->followLinks) ->setDepths($this->depths) ->setMode($this->mode) ->setExclude($this->exclude) ->setNames($this->names) ->setNotNames($this->notNames) ->setContains($this->contains) ->setNotContains($this->notContains) ->setSizes($this->sizes) ->setDates($this->dates) ->setFilters($this->filters) ->setSort($this->sort) ->setPath($this->paths) ->setNotPath($this->notPaths) ->ignoreUnreadableDirs($this->ignoreUnreadableDirs); } /** * Unselects all adapters. */ private function resetAdapterSelection() { $this->adapters = array_map(function (array $properties) { $properties['selected'] = false; return $properties; }, $this->adapters); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; /** * Interface for finder engine implementations. * * @author Jean-François Simon */ abstract class AbstractAdapter implements AdapterInterface { protected $followLinks = false; protected $mode = 0; protected $minDepth = 0; protected $maxDepth = PHP_INT_MAX; protected $exclude = array(); protected $names = array(); protected $notNames = array(); protected $contains = array(); protected $notContains = array(); protected $sizes = array(); protected $dates = array(); protected $filters = array(); protected $sort = false; protected $paths = array(); protected $notPaths = array(); protected $ignoreUnreadableDirs = false; private static $areSupported = array(); /** * {@inheritdoc} */ public function isSupported() { $name = $this->getName(); if (!array_key_exists($name, self::$areSupported)) { self::$areSupported[$name] = $this->canBeUsed(); } return self::$areSupported[$name]; } /** * {@inheritdoc} */ public function setFollowLinks($followLinks) { $this->followLinks = $followLinks; return $this; } /** * {@inheritdoc} */ public function setMode($mode) { $this->mode = $mode; return $this; } /** * {@inheritdoc} */ public function setDepths(array $depths) { $this->minDepth = 0; $this->maxDepth = PHP_INT_MAX; foreach ($depths as $comparator) { switch ($comparator->getOperator()) { case '>': $this->minDepth = $comparator->getTarget() + 1; break; case '>=': $this->minDepth = $comparator->getTarget(); break; case '<': $this->maxDepth = $comparator->getTarget() - 1; break; case '<=': $this->maxDepth = $comparator->getTarget(); break; default: $this->minDepth = $this->maxDepth = $comparator->getTarget(); } } return $this; } /** * {@inheritdoc} */ public function setExclude(array $exclude) { $this->exclude = $exclude; return $this; } /** * {@inheritdoc} */ public function setNames(array $names) { $this->names = $names; return $this; } /** * {@inheritdoc} */ public function setNotNames(array $notNames) { $this->notNames = $notNames; return $this; } /** * {@inheritdoc} */ public function setContains(array $contains) { $this->contains = $contains; return $this; } /** * {@inheritdoc} */ public function setNotContains(array $notContains) { $this->notContains = $notContains; return $this; } /** * {@inheritdoc} */ public function setSizes(array $sizes) { $this->sizes = $sizes; return $this; } /** * {@inheritdoc} */ public function setDates(array $dates) { $this->dates = $dates; return $this; } /** * {@inheritdoc} */ public function setFilters(array $filters) { $this->filters = $filters; return $this; } /** * {@inheritdoc} */ public function setSort($sort) { $this->sort = $sort; return $this; } /** * {@inheritdoc} */ public function setPath(array $paths) { $this->paths = $paths; return $this; } /** * {@inheritdoc} */ public function setNotPath(array $notPaths) { $this->notPaths = $notPaths; return $this; } /** * {@inheritdoc} */ public function ignoreUnreadableDirs($ignore = true) { $this->ignoreUnreadableDirs = (bool) $ignore; return $this; } /** * Returns whether the adapter is supported in the current environment. * * This method should be implemented in all adapters. Do not implement * isSupported in the adapters as the generic implementation provides a cache * layer. * * @see isSupported() * * @return bool Whether the adapter is supported */ abstract protected function canBeUsed(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; /** * @author Jean-François Simon */ interface AdapterInterface { /** * @param bool $followLinks * * @return AdapterInterface Current instance */ public function setFollowLinks($followLinks); /** * @param int $mode * * @return AdapterInterface Current instance */ public function setMode($mode); /** * @param array $exclude * * @return AdapterInterface Current instance */ public function setExclude(array $exclude); /** * @param array $depths * * @return AdapterInterface Current instance */ public function setDepths(array $depths); /** * @param array $names * * @return AdapterInterface Current instance */ public function setNames(array $names); /** * @param array $notNames * * @return AdapterInterface Current instance */ public function setNotNames(array $notNames); /** * @param array $contains * * @return AdapterInterface Current instance */ public function setContains(array $contains); /** * @param array $notContains * * @return AdapterInterface Current instance */ public function setNotContains(array $notContains); /** * @param array $sizes * * @return AdapterInterface Current instance */ public function setSizes(array $sizes); /** * @param array $dates * * @return AdapterInterface Current instance */ public function setDates(array $dates); /** * @param array $filters * * @return AdapterInterface Current instance */ public function setFilters(array $filters); /** * @param \Closure|int $sort * * @return AdapterInterface Current instance */ public function setSort($sort); /** * @param array $paths * * @return AdapterInterface Current instance */ public function setPath(array $paths); /** * @param array $notPaths * * @return AdapterInterface Current instance */ public function setNotPath(array $notPaths); /** * @param bool $ignore * * @return AdapterInterface Current instance */ public function ignoreUnreadableDirs($ignore = true); /** * @param string $dir * * @return \Iterator Result iterator */ public function searchInDirectory($dir); /** * Tests adapter support for current platform. * * @return bool */ public function isSupported(); /** * Returns adapter name. * * @return string */ public function getName(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; use Symfony\Component\Finder\Expression\Expression; /** * Shell engine implementation using GNU find command. * * @author Jean-François Simon */ class GnuFindAdapter extends AbstractFindAdapter { /** * {@inheritdoc} */ public function getName() { return 'gnu_find'; } /** * {@inheritdoc} */ protected function buildFormatSorting(Command $command, $sort) { switch ($sort) { case SortableIterator::SORT_BY_NAME: $command->ins('sort')->add('| sort'); return; case SortableIterator::SORT_BY_TYPE: $format = '%y'; break; case SortableIterator::SORT_BY_ACCESSED_TIME: $format = '%A@'; break; case SortableIterator::SORT_BY_CHANGED_TIME: $format = '%C@'; break; case SortableIterator::SORT_BY_MODIFIED_TIME: $format = '%T@'; break; default: throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); } $command ->get('find') ->add('-printf') ->arg($format.' %h/%f\\n') ->add('| sort | cut') ->arg('-d ') ->arg('-f2-') ; } /** * {@inheritdoc} */ protected function canBeUsed() { return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed(); } /** * {@inheritdoc} */ protected function buildFindCommand(Command $command, $dir) { return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended'); } /** * {@inheritdoc} */ protected function buildContentFiltering(Command $command, array $contains, $not = false) { foreach ($contains as $contain) { $expr = Expression::create($contain); // todo: avoid forking process for each $pattern by using multiple -e options $command ->add('| xargs -I{} -r grep -I') ->add($expr->isCaseSensitive() ? null : '-i') ->add($not ? '-L' : '-l') ->add('-Ee')->arg($expr->renderPattern()) ->add('{}') ; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Iterator; /** * PHP finder engine implementation. * * @author Jean-François Simon */ class PhpAdapter extends AbstractAdapter { /** * {@inheritdoc} */ public function searchInDirectory($dir) { $flags = \RecursiveDirectoryIterator::SKIP_DOTS; if ($this->followLinks) { $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; } $iterator = new \RecursiveIteratorIterator( new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs), \RecursiveIteratorIterator::SELF_FIRST ); if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) { $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth); } if ($this->mode) { $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); } if ($this->exclude) { $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); } if ($this->names || $this->notNames) { $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); } if ($this->contains || $this->notContains) { $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); } if ($this->sizes) { $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); } if ($this->dates) { $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); } if ($this->filters) { $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } if ($this->sort) { $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); $iterator = $iteratorAggregate->getIterator(); } if ($this->paths || $this->notPaths) { $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); } return $iterator; } /** * {@inheritdoc} */ public function getName() { return 'php'; } /** * {@inheritdoc} */ protected function canBeUsed() { return true; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Exception\AccessDeniedException; use Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Expression\Expression; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Comparator\NumberComparator; use Symfony\Component\Finder\Comparator\DateComparator; /** * Shell engine implementation using GNU find command. * * @author Jean-François Simon */ abstract class AbstractFindAdapter extends AbstractAdapter { /** * @var Shell */ protected $shell; /** * Constructor. */ public function __construct() { $this->shell = new Shell(); } /** * {@inheritdoc} */ public function searchInDirectory($dir) { // having "/../" in path make find fail $dir = realpath($dir); // searching directories containing or not containing strings leads to no result if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) { return new Iterator\FilePathsIterator(array(), $dir); } $command = Command::create(); $find = $this->buildFindCommand($command, $dir); if ($this->followLinks) { $find->add('-follow'); } $find->add('-mindepth')->add($this->minDepth + 1); if (PHP_INT_MAX !== $this->maxDepth) { $find->add('-maxdepth')->add($this->maxDepth + 1); } if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) { $find->add('-type d'); } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) { $find->add('-type f'); } $this->buildNamesFiltering($find, $this->names); $this->buildNamesFiltering($find, $this->notNames, true); $this->buildPathsFiltering($find, $dir, $this->paths); $this->buildPathsFiltering($find, $dir, $this->notPaths, true); $this->buildSizesFiltering($find, $this->sizes); $this->buildDatesFiltering($find, $this->dates); $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs'); $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut'); if ($useGrep && ($this->contains || $this->notContains)) { $grep = $command->ins('grep'); $this->buildContentFiltering($grep, $this->contains); $this->buildContentFiltering($grep, $this->notContains, true); } if ($useSort) { $this->buildSorting($command, $this->sort); } $command->setErrorHandler( $this->ignoreUnreadableDirs // If directory is unreadable and finder is set to ignore it, `stderr` is ignored. ? function ($stderr) { return; } : function ($stderr) { throw new AccessDeniedException($stderr); } ); $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute()); $iterator = new Iterator\FilePathsIterator($paths, $dir); if ($this->exclude) { $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); } if (!$useGrep && ($this->contains || $this->notContains)) { $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); } if ($this->filters) { $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } if (!$useSort && $this->sort) { $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); $iterator = $iteratorAggregate->getIterator(); } return $iterator; } /** * {@inheritdoc} */ protected function canBeUsed() { return $this->shell->testCommand('find'); } /** * @param Command $command * @param string $dir * * @return Command */ protected function buildFindCommand(Command $command, $dir) { return $command ->ins('find') ->add('find ') ->arg($dir) ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions } /** * @param Command $command * @param string[] $names * @param bool $not */ private function buildNamesFiltering(Command $command, array $names, $not = false) { if (0 === count($names)) { return; } $command->add($not ? '-not' : null)->cmd('('); foreach ($names as $i => $name) { $expr = Expression::create($name); // Find does not support expandable globs ("*.{a,b}" syntax). if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { $expr = Expression::create($expr->getGlob()->toRegex(false)); } // Fixes 'not search' and 'full path matching' regex problems. // - Jokers '.' are replaced by [^/]. // - We add '[^/]*' before and after regex (if no ^|$ flags are present). if ($expr->isRegex()) { $regex = $expr->getRegex(); $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*') ->setStartFlag(false) ->setStartJoker(true) ->replaceJokers('[^/]'); if (!$regex->hasEndFlag() || $regex->hasEndJoker()) { $regex->setEndJoker(false)->append('[^/]*'); } } $command ->add($i > 0 ? '-or' : null) ->add($expr->isRegex() ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') : ($expr->isCaseSensitive() ? '-name' : '-iname') ) ->arg($expr->renderPattern()); } $command->cmd(')'); } /** * @param Command $command * @param string $dir * @param string[] $paths * @param bool $not */ private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false) { if (0 === count($paths)) { return; } $command->add($not ? '-not' : null)->cmd('('); foreach ($paths as $i => $path) { $expr = Expression::create($path); // Find does not support expandable globs ("*.{a,b}" syntax). if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { $expr = Expression::create($expr->getGlob()->toRegex(false)); } // Fixes 'not search' regex problems. if ($expr->isRegex()) { $regex = $expr->getRegex(); $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag()); } else { $expr->prepend('*')->append('*'); } $command ->add($i > 0 ? '-or' : null) ->add($expr->isRegex() ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') : ($expr->isCaseSensitive() ? '-path' : '-ipath') ) ->arg($expr->renderPattern()); } $command->cmd(')'); } /** * @param Command $command * @param NumberComparator[] $sizes */ private function buildSizesFiltering(Command $command, array $sizes) { foreach ($sizes as $i => $size) { $command->add($i > 0 ? '-and' : null); switch ($size->getOperator()) { case '<=': $command->add('-size -'.($size->getTarget() + 1).'c'); break; case '>=': $command->add('-size +'.($size->getTarget() - 1).'c'); break; case '>': $command->add('-size +'.$size->getTarget().'c'); break; case '!=': $command->add('-size -'.$size->getTarget().'c'); $command->add('-size +'.$size->getTarget().'c'); break; case '<': default: $command->add('-size -'.$size->getTarget().'c'); } } } /** * @param Command $command * @param DateComparator[] $dates */ private function buildDatesFiltering(Command $command, array $dates) { foreach ($dates as $i => $date) { $command->add($i > 0 ? '-and' : null); $mins = (int) round((time() - $date->getTarget()) / 60); if (0 > $mins) { // mtime is in the future $command->add(' -mmin -0'); // we will have no result so we don't need to continue return; } switch ($date->getOperator()) { case '<=': $command->add('-mmin +'.($mins - 1)); break; case '>=': $command->add('-mmin -'.($mins + 1)); break; case '>': $command->add('-mmin -'.$mins); break; case '!=': $command->add('-mmin +'.$mins.' -or -mmin -'.$mins); break; case '<': default: $command->add('-mmin +'.$mins); } } } /** * @param Command $command * @param string $sort * * @throws \InvalidArgumentException */ private function buildSorting(Command $command, $sort) { $this->buildFormatSorting($command, $sort); } /** * @param Command $command * @param string $sort */ abstract protected function buildFormatSorting(Command $command, $sort); /** * @param Command $command * @param array $contains * @param bool $not */ abstract protected function buildContentFiltering(Command $command, array $contains, $not = false); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Adapter; use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; use Symfony\Component\Finder\Expression\Expression; /** * Shell engine implementation using BSD find command. * * @author Jean-François Simon */ class BsdFindAdapter extends AbstractFindAdapter { /** * {@inheritdoc} */ public function getName() { return 'bsd_find'; } /** * {@inheritdoc} */ protected function canBeUsed() { return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed(); } /** * {@inheritdoc} */ protected function buildFormatSorting(Command $command, $sort) { switch ($sort) { case SortableIterator::SORT_BY_NAME: $command->ins('sort')->add('| sort'); return; case SortableIterator::SORT_BY_TYPE: $format = '%HT'; break; case SortableIterator::SORT_BY_ACCESSED_TIME: $format = '%a'; break; case SortableIterator::SORT_BY_CHANGED_TIME: $format = '%c'; break; case SortableIterator::SORT_BY_MODIFIED_TIME: $format = '%m'; break; default: throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort)); } $command ->add('-print0 | xargs -0 stat -f') ->arg($format.'%t%N') ->add('| sort | cut -f 2'); } /** * {@inheritdoc} */ protected function buildFindCommand(Command $command, $dir) { parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1); return $command; } /** * {@inheritdoc} */ protected function buildContentFiltering(Command $command, array $contains, $not = false) { foreach ($contains as $contain) { $expr = Expression::create($contain); // todo: avoid forking process for each $pattern by using multiple -e options $command ->add('| grep -v \'^$\'') ->add('| xargs -I{} grep -I') ->add($expr->isCaseSensitive() ? null : '-i') ->add($not ? '-L' : '-l') ->add('-Ee')->arg($expr->renderPattern()) ->add('{}') ; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ class AccessDeniedException extends \UnexpectedValueException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ interface ExceptionInterface { /** * @return \Symfony\Component\Finder\Adapter\AdapterInterface */ public function getAdapter(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ class OperationNotPermitedException extends AdapterFailureException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; use Symfony\Component\Finder\Adapter\AdapterInterface; /** * Base exception for all adapter failures. * * @author Jean-François Simon */ class AdapterFailureException extends \RuntimeException implements ExceptionInterface { /** * @var \Symfony\Component\Finder\Adapter\AdapterInterface */ private $adapter; /** * @param AdapterInterface $adapter * @param string|null $message * @param \Exception|null $previous */ public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null) { $this->adapter = $adapter; parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous); } /** * {@inheritdoc} */ public function getAdapter() { return $this->adapter; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; use Symfony\Component\Finder\Adapter\AdapterInterface; use Symfony\Component\Finder\Shell\Command; /** * @author Jean-François Simon */ class ShellCommandFailureException extends AdapterFailureException { /** * @var Command */ private $command; /** * @param AdapterInterface $adapter * @param Command $command * @param \Exception|null $previous */ public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null) { $this->command = $command; parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous); } /** * @return Command */ public function getCommand() { return $this->command; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; use Symfony\Component\Yaml\Exception\ParseException; /** * Yaml offers convenience methods to load and dump YAML. * * @author Fabien Potencier * * @api */ class Yaml { /** * Parses YAML into a PHP array. * * The parse method, when supplied with a YAML stream (string or file), * will do its best to convert YAML in a file into a PHP array. * * Usage: * * $array = Yaml::parse('config.yml'); * print_r($array); * * * As this method accepts both plain strings and file names as an input, * you must validate the input before calling this method. Passing a file * as an input is a deprecated feature and will be removed in 3.0. * * Note: the ability to pass file names to the Yaml::parse method is deprecated since version 2.2 and will be removed in 3.0. Pass the YAML contents of the file instead. * * @param string $input Path to a YAML file or a string containing YAML * @param bool $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise * @param bool $objectSupport True if object support is enabled, false otherwise * * @return array The YAML converted to a PHP array * * @throws ParseException If the YAML is not valid * * @api */ public static function parse($input, $exceptionOnInvalidType = false, $objectSupport = false) { // if input is a file, process it $file = ''; if (strpos($input, "\n") === false && is_file($input)) { if (false === is_readable($input)) { throw new ParseException(sprintf('Unable to parse "%s" as the file is not readable.', $input)); } $file = $input; $input = file_get_contents($file); } $yaml = new Parser(); try { return $yaml->parse($input, $exceptionOnInvalidType, $objectSupport); } catch (ParseException $e) { if ($file) { $e->setParsedFile($file); } throw $e; } } /** * Dumps a PHP array to a YAML string. * * The dump method, when supplied with an array, will do its best * to convert the array into friendly YAML. * * @param array $array PHP array * @param int $inline The level where you switch to inline YAML * @param int $indent The amount of spaces to use for indentation of nested nodes. * @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param bool $objectSupport true if object support is enabled, false otherwise * * @return string A YAML string representing the original PHP array * * @api */ public static function dump($array, $inline = 2, $indent = 4, $exceptionOnInvalidType = false, $objectSupport = false) { $yaml = new Dumper(); $yaml->setIndentation($indent); return $yaml->dump($array, $inline, 0, $exceptionOnInvalidType, $objectSupport); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; use Symfony\Component\Yaml\Exception\ParseException; /** * Parser parses YAML strings to convert them to PHP arrays. * * @author Fabien Potencier */ class Parser { const FOLDED_SCALAR_PATTERN = '(?P\||>)(?P\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P +#.*)?'; private $offset = 0; private $lines = array(); private $currentLineNb = -1; private $currentLine = ''; private $refs = array(); /** * Constructor. * * @param int $offset The offset of YAML document (used for line numbers in error messages) */ public function __construct($offset = 0) { $this->offset = $offset; } /** * Parses a YAML string to a PHP value. * * @param string $value A YAML string * @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param bool $objectSupport true if object support is enabled, false otherwise * @param bool $objectForMap true if maps should return a stdClass instead of array() * * @return mixed A PHP value * * @throws ParseException If the YAML is not valid */ public function parse($value, $exceptionOnInvalidType = false, $objectSupport = false, $objectForMap = false) { if (!preg_match('//u', $value)) { throw new ParseException('The YAML value does not appear to be valid UTF-8.'); } $this->currentLineNb = -1; $this->currentLine = ''; $value = $this->cleanup($value); $this->lines = explode("\n", $value); if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { $mbEncoding = mb_internal_encoding(); mb_internal_encoding('UTF-8'); } $data = array(); $context = null; $allowOverwrite = false; while ($this->moveToNextLine()) { if ($this->isCurrentLineEmpty()) { continue; } // tab? if ("\t" === $this->currentLine[0]) { throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } $isRef = $mergeNode = false; if (preg_match('#^\-((?P\s+)(?P.+?))?\s*$#u', $this->currentLine, $values)) { if ($context && 'mapping' == $context) { throw new ParseException('You cannot define a sequence item when in a mapping'); } $context = 'sequence'; if (isset($values['value']) && preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; $values['value'] = $matches['value']; } // array if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { $c = $this->getRealCurrentLineNb() + 1; $parser = new self($c); $parser->refs = &$this->refs; $data[] = $parser->parse($this->getNextEmbedBlock(null, true), $exceptionOnInvalidType, $objectSupport, $objectForMap); } else { if (isset($values['leadspaces']) && preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P.+?))?\s*$#u', $values['value'], $matches) ) { // this is a compact notation element, add to next block and parse $c = $this->getRealCurrentLineNb(); $parser = new self($c); $parser->refs = &$this->refs; $block = $values['value']; if ($this->isNextLineIndented()) { $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + strlen($values['leadspaces']) + 1); } $data[] = $parser->parse($block, $exceptionOnInvalidType, $objectSupport, $objectForMap); } else { $data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap); } } } elseif (preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P.+?))?\s*$#u', $this->currentLine, $values) && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'")))) { if ($context && 'sequence' == $context) { throw new ParseException('You cannot define a mapping item when in a sequence'); } $context = 'mapping'; // force correct settings Inline::parse(null, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs); try { $key = Inline::parseScalar($values['key']); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); throw $e; } if ('<<' === $key) { $mergeNode = true; $allowOverwrite = true; if (isset($values['value']) && 0 === strpos($values['value'], '*')) { $refName = substr($values['value'], 1); if (!array_key_exists($refName, $this->refs)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine); } $refValue = $this->refs[$refName]; if (!is_array($refValue)) { throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } foreach ($refValue as $key => $value) { if (!isset($data[$key])) { $data[$key] = $value; } } } else { if (isset($values['value']) && $values['value'] !== '') { $value = $values['value']; } else { $value = $this->getNextEmbedBlock(); } $c = $this->getRealCurrentLineNb() + 1; $parser = new self($c); $parser->refs = &$this->refs; $parsed = $parser->parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap); if (!is_array($parsed)) { throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } if (isset($parsed[0])) { // If the value associated with the merge key is a sequence, then this sequence is expected to contain mapping nodes // and each of these nodes is merged in turn according to its order in the sequence. Keys in mapping nodes earlier // in the sequence override keys specified in later mapping nodes. foreach ($parsed as $parsedItem) { if (!is_array($parsedItem)) { throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem); } foreach ($parsedItem as $key => $value) { if (!isset($data[$key])) { $data[$key] = $value; } } } } else { // If the value associated with the key is a single mapping node, each of its key/value pairs is inserted into the // current mapping, unless the key already exists in it. foreach ($parsed as $key => $value) { if (!isset($data[$key])) { $data[$key] = $value; } } } } } elseif (isset($values['value']) && preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; $values['value'] = $matches['value']; } if ($mergeNode) { // Merge keys } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { // hash // if next line is less indented or equal, then it means that the current value is null if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) { // Spec: Keys MUST be unique; first one wins. // But overwriting is allowed when a merge node is used in current block. if ($allowOverwrite || !isset($data[$key])) { $data[$key] = null; } } else { $c = $this->getRealCurrentLineNb() + 1; $parser = new self($c); $parser->refs = &$this->refs; $value = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport, $objectForMap); // Spec: Keys MUST be unique; first one wins. // But overwriting is allowed when a merge node is used in current block. if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; } } } else { $value = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap); // Spec: Keys MUST be unique; first one wins. // But overwriting is allowed when a merge node is used in current block. if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; } } } else { // multiple documents are not supported if ('---' === $this->currentLine) { throw new ParseException('Multiple documents are not supported.'); } // 1-liner optionally followed by newline(s) if (is_string($value) && $this->lines[0] === trim($value)) { try { $value = Inline::parse($this->lines[0], $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); throw $e; } if (is_array($value)) { $first = reset($value); if (is_string($first) && 0 === strpos($first, '*')) { $data = array(); foreach ($value as $alias) { $data[] = $this->refs[substr($alias, 1)]; } $value = $data; } } if (isset($mbEncoding)) { mb_internal_encoding($mbEncoding); } return $value; } switch (preg_last_error()) { case PREG_INTERNAL_ERROR: $error = 'Internal PCRE error.'; break; case PREG_BACKTRACK_LIMIT_ERROR: $error = 'pcre.backtrack_limit reached.'; break; case PREG_RECURSION_LIMIT_ERROR: $error = 'pcre.recursion_limit reached.'; break; case PREG_BAD_UTF8_ERROR: $error = 'Malformed UTF-8 data.'; break; case PREG_BAD_UTF8_OFFSET_ERROR: $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.'; break; default: $error = 'Unable to parse.'; } throw new ParseException($error, $this->getRealCurrentLineNb() + 1, $this->currentLine); } if ($isRef) { $this->refs[$isRef] = end($data); } } if (isset($mbEncoding)) { mb_internal_encoding($mbEncoding); } return empty($data) ? null : $data; } /** * Returns the current line number (takes the offset into account). * * @return int The current line number */ private function getRealCurrentLineNb() { return $this->currentLineNb + $this->offset; } /** * Returns the current line indentation. * * @return int The current line indentation */ private function getCurrentLineIndentation() { return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' ')); } /** * Returns the next embed block of YAML. * * @param int $indentation The indent level at which the block is to be read, or null for default * @param bool $inSequence True if the enclosing data structure is a sequence * * @return string A YAML string * * @throws ParseException When indentation problem are detected */ private function getNextEmbedBlock($indentation = null, $inSequence = false) { $oldLineIndentation = $this->getCurrentLineIndentation(); if (!$this->moveToNextLine()) { return; } if (null === $indentation) { $newIndent = $this->getCurrentLineIndentation(); $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem($this->currentLine); if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) { throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } } else { $newIndent = $indentation; } $data = array(); if ($this->getCurrentLineIndentation() >= $newIndent) { $data[] = substr($this->currentLine, $newIndent); } else { $this->moveToPreviousLine(); return; } if ($inSequence && $oldLineIndentation === $newIndent && '-' === $data[0][0]) { // the previous line contained a dash but no item content, this line is a sequence item with the same indentation // and therefore no nested list or mapping $this->moveToPreviousLine(); return; } $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem($this->currentLine); // Comments must not be removed inside a string block (ie. after a line ending with "|") $removeCommentsPattern = '~'.self::FOLDED_SCALAR_PATTERN.'$~'; $removeComments = !preg_match($removeCommentsPattern, $this->currentLine); while ($this->moveToNextLine()) { $indent = $this->getCurrentLineIndentation(); if ($indent === $newIndent) { $removeComments = !preg_match($removeCommentsPattern, $this->currentLine); } if ($isItUnindentedCollection && !$this->isStringUnIndentedCollectionItem($this->currentLine) && $newIndent === $indent) { $this->moveToPreviousLine(); break; } if ($this->isCurrentLineBlank()) { $data[] = substr($this->currentLine, $newIndent); continue; } if ($removeComments && $this->isCurrentLineComment()) { continue; } if ($indent >= $newIndent) { $data[] = substr($this->currentLine, $newIndent); } elseif (0 == $indent) { $this->moveToPreviousLine(); break; } else { throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } } return implode("\n", $data); } /** * Moves the parser to the next line. * * @return bool */ private function moveToNextLine() { if ($this->currentLineNb >= count($this->lines) - 1) { return false; } $this->currentLine = $this->lines[++$this->currentLineNb]; return true; } /** * Moves the parser to the previous line. */ private function moveToPreviousLine() { $this->currentLine = $this->lines[--$this->currentLineNb]; } /** * Parses a YAML value. * * @param string $value A YAML value * @param bool $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise * @param bool $objectSupport True if object support is enabled, false otherwise * @param bool $objectForMap true if maps should return a stdClass instead of array() * * @return mixed A PHP value * * @throws ParseException When reference does not exist */ private function parseValue($value, $exceptionOnInvalidType, $objectSupport, $objectForMap) { if (0 === strpos($value, '*')) { if (false !== $pos = strpos($value, '#')) { $value = substr($value, 1, $pos - 2); } else { $value = substr($value, 1); } if (!array_key_exists($value, $this->refs)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLine); } return $this->refs[$value]; } if (preg_match('/^'.self::FOLDED_SCALAR_PATTERN.'$/', $value, $matches)) { $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : ''; return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); } try { return Inline::parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); throw $e; } } /** * Parses a folded scalar. * * @param string $separator The separator that was used to begin this folded scalar (| or >) * @param string $indicator The indicator that was used to begin this folded scalar (+ or -) * @param int $indentation The indentation that was used to begin this folded scalar * * @return string The text value */ private function parseFoldedScalar($separator, $indicator = '', $indentation = 0) { $notEOF = $this->moveToNextLine(); if (!$notEOF) { return ''; } $isCurrentLineBlank = $this->isCurrentLineBlank(); $text = ''; // leading blank lines are consumed before determining indentation while ($notEOF && $isCurrentLineBlank) { // newline only if not EOF if ($notEOF = $this->moveToNextLine()) { $text .= "\n"; $isCurrentLineBlank = $this->isCurrentLineBlank(); } } // determine indentation if not specified if (0 === $indentation) { if (preg_match('/^ +/', $this->currentLine, $matches)) { $indentation = strlen($matches[0]); } } if ($indentation > 0) { $pattern = sprintf('/^ {%d}(.*)$/', $indentation); while ( $notEOF && ( $isCurrentLineBlank || preg_match($pattern, $this->currentLine, $matches) ) ) { if ($isCurrentLineBlank) { $text .= substr($this->currentLine, $indentation); } else { $text .= $matches[1]; } // newline only if not EOF if ($notEOF = $this->moveToNextLine()) { $text .= "\n"; $isCurrentLineBlank = $this->isCurrentLineBlank(); } } } elseif ($notEOF) { $text .= "\n"; } if ($notEOF) { $this->moveToPreviousLine(); } // replace all non-trailing single newlines with spaces in folded blocks if ('>' === $separator) { preg_match('/(\n*)$/', $text, $matches); $text = preg_replace('/(?getCurrentLineIndentation(); $EOF = !$this->moveToNextLine(); while (!$EOF && $this->isCurrentLineEmpty()) { $EOF = !$this->moveToNextLine(); } if ($EOF) { return false; } $ret = false; if ($this->getCurrentLineIndentation() > $currentIndentation) { $ret = true; } $this->moveToPreviousLine(); return $ret; } /** * Returns true if the current line is blank or if it is a comment line. * * @return bool Returns true if the current line is empty or if it is a comment line, false otherwise */ private function isCurrentLineEmpty() { return $this->isCurrentLineBlank() || $this->isCurrentLineComment(); } /** * Returns true if the current line is blank. * * @return bool Returns true if the current line is blank, false otherwise */ private function isCurrentLineBlank() { return '' == trim($this->currentLine, ' '); } /** * Returns true if the current line is a comment line. * * @return bool Returns true if the current line is a comment line, false otherwise */ private function isCurrentLineComment() { //checking explicitly the first char of the trim is faster than loops or strpos $ltrimmedLine = ltrim($this->currentLine, ' '); return $ltrimmedLine[0] === '#'; } /** * Cleanups a YAML string to be parsed. * * @param string $value The input YAML string * * @return string A cleaned up YAML string */ private function cleanup($value) { $value = str_replace(array("\r\n", "\r"), "\n", $value); // strip YAML header $count = 0; $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#u', '', $value, -1, $count); $this->offset += $count; // remove leading comments $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count); if ($count == 1) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; } // remove start of the document marker (---) $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count); if ($count == 1) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; // remove end of the document marker (...) $value = preg_replace('#\.\.\.\s*$#', '', $value); } return $value; } /** * Returns true if the next line starts unindented collection. * * @return bool Returns true if the next line starts unindented collection, false otherwise */ private function isNextLineUnIndentedCollection() { $currentIndentation = $this->getCurrentLineIndentation(); $notEOF = $this->moveToNextLine(); while ($notEOF && $this->isCurrentLineEmpty()) { $notEOF = $this->moveToNextLine(); } if (false === $notEOF) { return false; } $ret = false; if ( $this->getCurrentLineIndentation() == $currentIndentation && $this->isStringUnIndentedCollectionItem($this->currentLine) ) { $ret = true; } $this->moveToPreviousLine(); return $ret; } /** * Returns true if the string is un-indented collection item. * * @return bool Returns true if the string is un-indented collection item, false otherwise */ private function isStringUnIndentedCollectionItem() { return (0 === strpos($this->currentLine, '- ')); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; /** * Dumper dumps PHP variables to YAML strings. * * @author Fabien Potencier */ class Dumper { /** * The amount of spaces to use for indentation of nested nodes. * * @var int */ protected $indentation = 4; /** * Sets the indentation. * * @param int $num The amount of spaces to use for indentation of nested nodes. */ public function setIndentation($num) { $this->indentation = (int) $num; } /** * Dumps a PHP value to YAML. * * @param mixed $input The PHP value * @param int $inline The level where you switch to inline YAML * @param int $indent The level of indentation (used internally) * @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param bool $objectSupport true if object support is enabled, false otherwise * * @return string The YAML representation of the PHP value */ public function dump($input, $inline = 0, $indent = 0, $exceptionOnInvalidType = false, $objectSupport = false) { $output = ''; $prefix = $indent ? str_repeat(' ', $indent) : ''; if ($inline <= 0 || !is_array($input) || empty($input)) { $output .= $prefix.Inline::dump($input, $exceptionOnInvalidType, $objectSupport); } else { $isAHash = array_keys($input) !== range(0, count($input) - 1); foreach ($input as $key => $value) { $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value); $output .= sprintf('%s%s%s%s', $prefix, $isAHash ? Inline::dump($key, $exceptionOnInvalidType, $objectSupport).':' : '-', $willBeInlined ? ' ' : "\n", $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $exceptionOnInvalidType, $objectSupport) ).($willBeInlined ? "\n" : ''); } } return $output; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Exception\DumpException; /** * Inline implements a YAML parser/dumper for the YAML inline syntax. * * @author Fabien Potencier */ class Inline { const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')'; private static $exceptionOnInvalidType = false; private static $objectSupport = false; private static $objectForMap = false; /** * Converts a YAML string to a PHP array. * * @param string $value A YAML string * @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param bool $objectSupport true if object support is enabled, false otherwise * @param bool $objectForMap true if maps should return a stdClass instead of array() * @param array $references Mapping of variable names to values * * @return array A PHP array representing the YAML string * * @throws ParseException */ public static function parse($value, $exceptionOnInvalidType = false, $objectSupport = false, $objectForMap = false, $references = array()) { self::$exceptionOnInvalidType = $exceptionOnInvalidType; self::$objectSupport = $objectSupport; self::$objectForMap = $objectForMap; $value = trim($value); if ('' === $value) { return ''; } if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { $mbEncoding = mb_internal_encoding(); mb_internal_encoding('ASCII'); } $i = 0; switch ($value[0]) { case '[': $result = self::parseSequence($value, $i, $references); ++$i; break; case '{': $result = self::parseMapping($value, $i, $references); ++$i; break; default: $result = self::parseScalar($value, null, array('"', "'"), $i, true, $references); } // some comments are allowed at the end if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) { throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i))); } if (isset($mbEncoding)) { mb_internal_encoding($mbEncoding); } return $result; } /** * Dumps a given PHP variable to a YAML string. * * @param mixed $value The PHP variable to convert * @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param bool $objectSupport true if object support is enabled, false otherwise * * @return string The YAML string representing the PHP array * * @throws DumpException When trying to dump PHP resource */ public static function dump($value, $exceptionOnInvalidType = false, $objectSupport = false) { switch (true) { case is_resource($value): if ($exceptionOnInvalidType) { throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value))); } return 'null'; case is_object($value): if ($objectSupport) { return '!!php/object:'.serialize($value); } if ($exceptionOnInvalidType) { throw new DumpException('Object support when dumping a YAML file has been disabled.'); } return 'null'; case is_array($value): return self::dumpArray($value, $exceptionOnInvalidType, $objectSupport); case null === $value: return 'null'; case true === $value: return 'true'; case false === $value: return 'false'; case ctype_digit($value): return is_string($value) ? "'$value'" : (int) $value; case is_numeric($value): $locale = setlocale(LC_NUMERIC, 0); if (false !== $locale) { setlocale(LC_NUMERIC, 'C'); } if (is_float($value)) { $repr = (string) $value; if (is_infinite($value)) { $repr = str_ireplace('INF', '.Inf', $repr); } elseif (floor($value) == $value && $repr == $value) { // Preserve float data type since storing a whole number will result in integer value. $repr = '!!float '.$repr; } } else { $repr = is_string($value) ? "'$value'" : (string) $value; } if (false !== $locale) { setlocale(LC_NUMERIC, $locale); } return $repr; case '' == $value: return "''"; case Escaper::requiresDoubleQuoting($value): return Escaper::escapeWithDoubleQuotes($value); case Escaper::requiresSingleQuoting($value): case preg_match(self::getHexRegex(), $value): case preg_match(self::getTimestampRegex(), $value): return Escaper::escapeWithSingleQuotes($value); default: return $value; } } /** * Dumps a PHP array to a YAML string. * * @param array $value The PHP array to dump * @param bool $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise * @param bool $objectSupport true if object support is enabled, false otherwise * * @return string The YAML string representing the PHP array */ private static function dumpArray($value, $exceptionOnInvalidType, $objectSupport) { // array $keys = array_keys($value); $keysCount = count($keys); if ((1 === $keysCount && '0' == $keys[0]) || ($keysCount > 1 && array_reduce($keys, function ($v, $w) { return (int) $v + $w; }, 0) === $keysCount * ($keysCount - 1) / 2) ) { $output = array(); foreach ($value as $val) { $output[] = self::dump($val, $exceptionOnInvalidType, $objectSupport); } return sprintf('[%s]', implode(', ', $output)); } // mapping $output = array(); foreach ($value as $key => $val) { $output[] = sprintf('%s: %s', self::dump($key, $exceptionOnInvalidType, $objectSupport), self::dump($val, $exceptionOnInvalidType, $objectSupport)); } return sprintf('{ %s }', implode(', ', $output)); } /** * Parses a scalar to a YAML string. * * @param string $scalar * @param string $delimiters * @param array $stringDelimiters * @param int &$i * @param bool $evaluate * @param array $references * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ public static function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true, $references = array()) { if (in_array($scalar[$i], $stringDelimiters)) { // quoted scalar $output = self::parseQuotedScalar($scalar, $i); if (null !== $delimiters) { $tmp = ltrim(substr($scalar, $i), ' '); if (!in_array($tmp[0], $delimiters)) { throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i))); } } } else { // "normal" string if (!$delimiters) { $output = substr($scalar, $i); $i += strlen($output); // remove comments if (false !== $strpos = strpos($output, ' #')) { $output = rtrim(substr($output, 0, $strpos)); } } elseif (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { $output = $match[1]; $i += strlen($output); } else { throw new ParseException(sprintf('Malformed inline YAML string (%s).', $scalar)); } if ($evaluate) { $output = self::evaluateScalar($output, $references); } } return $output; } /** * Parses a quoted scalar to YAML. * * @param string $scalar * @param int &$i * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ private static function parseQuotedScalar($scalar, &$i) { if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { throw new ParseException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i))); } $output = substr($match[0], 1, strlen($match[0]) - 2); $unescaper = new Unescaper(); if ('"' == $scalar[$i]) { $output = $unescaper->unescapeDoubleQuotedString($output); } else { $output = $unescaper->unescapeSingleQuotedString($output); } $i += strlen($match[0]); return $output; } /** * Parses a sequence to a YAML string. * * @param string $sequence * @param int &$i * @param array $references * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ private static function parseSequence($sequence, &$i = 0, $references = array()) { $output = array(); $len = strlen($sequence); ++$i; // [foo, bar, ...] while ($i < $len) { switch ($sequence[$i]) { case '[': // nested sequence $output[] = self::parseSequence($sequence, $i, $references); break; case '{': // nested mapping $output[] = self::parseMapping($sequence, $i, $references); break; case ']': return $output; case ',': case ' ': break; default: $isQuoted = in_array($sequence[$i], array('"', "'")); $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i, true, $references); // the value can be an array if a reference has been resolved to an array var if (!is_array($value) && !$isQuoted && false !== strpos($value, ': ')) { // embedded mapping? try { $pos = 0; $value = self::parseMapping('{'.$value.'}', $pos, $references); } catch (\InvalidArgumentException $e) { // no, it's not } } $output[] = $value; --$i; } ++$i; } throw new ParseException(sprintf('Malformed inline YAML string %s', $sequence)); } /** * Parses a mapping to a YAML string. * * @param string $mapping * @param int &$i * @param array $references * * @return string A YAML string * * @throws ParseException When malformed inline YAML string is parsed */ private static function parseMapping($mapping, &$i = 0, $references = array()) { $output = array(); $len = strlen($mapping); ++$i; // {foo: bar, bar:foo, ...} while ($i < $len) { switch ($mapping[$i]) { case ' ': case ',': ++$i; continue 2; case '}': if (self::$objectForMap) { return (object) $output; } return $output; } // key $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false); // value $done = false; while ($i < $len) { switch ($mapping[$i]) { case '[': // nested sequence $value = self::parseSequence($mapping, $i, $references); // Spec: Keys MUST be unique; first one wins. // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (!isset($output[$key])) { $output[$key] = $value; } $done = true; break; case '{': // nested mapping $value = self::parseMapping($mapping, $i, $references); // Spec: Keys MUST be unique; first one wins. // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (!isset($output[$key])) { $output[$key] = $value; } $done = true; break; case ':': case ' ': break; default: $value = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i, true, $references); // Spec: Keys MUST be unique; first one wins. // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (!isset($output[$key])) { $output[$key] = $value; } $done = true; --$i; } ++$i; if ($done) { continue 2; } } } throw new ParseException(sprintf('Malformed inline YAML string %s', $mapping)); } /** * Evaluates scalars and replaces magic values. * * @param string $scalar * @param array $references * * @return string A YAML string * * @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved */ private static function evaluateScalar($scalar, $references = array()) { $scalar = trim($scalar); $scalarLower = strtolower($scalar); if (0 === strpos($scalar, '*')) { if (false !== $pos = strpos($scalar, '#')) { $value = substr($scalar, 1, $pos - 2); } else { $value = substr($scalar, 1); } // an unquoted * if (false === $value || '' === $value) { throw new ParseException('A reference must contain at least one character.'); } if (!array_key_exists($value, $references)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $value)); } return $references[$value]; } switch (true) { case 'null' === $scalarLower: case '' === $scalar: case '~' === $scalar: return; case 'true' === $scalarLower: return true; case 'false' === $scalarLower: return false; // Optimise for returning strings. case $scalar[0] === '+' || $scalar[0] === '-' || $scalar[0] === '.' || $scalar[0] === '!' || is_numeric($scalar[0]): switch (true) { case 0 === strpos($scalar, '!str'): return (string) substr($scalar, 5); case 0 === strpos($scalar, '! '): return (int) self::parseScalar(substr($scalar, 2)); case 0 === strpos($scalar, '!!php/object:'): if (self::$objectSupport) { return unserialize(substr($scalar, 13)); } if (self::$exceptionOnInvalidType) { throw new ParseException('Object support when parsing a YAML file has been disabled.'); } return; case 0 === strpos($scalar, '!!float '): return (float) substr($scalar, 8); case ctype_digit($scalar): $raw = $scalar; $cast = (int) $scalar; return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw); case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)): $raw = $scalar; $cast = (int) $scalar; return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw === (string) $cast) ? $cast : $raw); case is_numeric($scalar): case preg_match(self::getHexRegex(), $scalar): return '0x' === $scalar[0].$scalar[1] ? hexdec($scalar) : (float) $scalar; case '.inf' === $scalarLower: case '.nan' === $scalarLower: return -log(0); case '-.inf' === $scalarLower: return log(0); case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar): return (float) str_replace(',', '', $scalar); case preg_match(self::getTimestampRegex(), $scalar): return strtotime($scalar); } default: return (string) $scalar; } } /** * Gets a regex that matches a YAML date. * * @return string The regular expression * * @see http://www.yaml.org/spec/1.2/spec.html#id2761573 */ private static function getTimestampRegex() { return <<[0-9][0-9][0-9][0-9]) -(?P[0-9][0-9]?) -(?P[0-9][0-9]?) (?:(?:[Tt]|[ \t]+) (?P[0-9][0-9]?) :(?P[0-9][0-9]) :(?P[0-9][0-9]) (?:\.(?P[0-9]*))? (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) (?::(?P[0-9][0-9]))?))?)? $~x EOF; } /** * Gets a regex that matches a YAML number in hexadecimal notation. * * @return string */ private static function getHexRegex() { return '~^0x[0-9a-f]++$~i'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; /** * Unescaper encapsulates unescaping rules for single and double-quoted * YAML strings. * * @author Matthew Lewinski */ class Unescaper { // Parser and Inline assume UTF-8 encoding, so escaped Unicode characters // must be converted to that encoding. // @deprecated since 2.5, to be removed in 3.0 const ENCODING = 'UTF-8'; // Regex fragment that matches an escaped character in a double quoted // string. const REGEX_ESCAPED_CHARACTER = "\\\\([0abt\tnvfre \\\"\\/\\\\N_LP]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})"; /** * Unescapes a single quoted string. * * @param string $value A single quoted string. * * @return string The unescaped string. */ public function unescapeSingleQuotedString($value) { return str_replace('\'\'', '\'', $value); } /** * Unescapes a double quoted string. * * @param string $value A double quoted string. * * @return string The unescaped string. */ public function unescapeDoubleQuotedString($value) { $self = $this; $callback = function ($match) use ($self) { return $self->unescapeCharacter($match[0]); }; // evaluate the string return preg_replace_callback('/'.self::REGEX_ESCAPED_CHARACTER.'/u', $callback, $value); } /** * Unescapes a character that was found in a double-quoted string. * * @param string $value An escaped character * * @return string The unescaped character */ public function unescapeCharacter($value) { switch ($value{1}) { case '0': return "\x0"; case 'a': return "\x7"; case 'b': return "\x8"; case 't': return "\t"; case "\t": return "\t"; case 'n': return "\n"; case 'v': return "\xB"; case 'f': return "\xC"; case 'r': return "\r"; case 'e': return "\x1B"; case ' ': return ' '; case '"': return '"'; case '/': return '/'; case '\\': return '\\'; case 'N': // U+0085 NEXT LINE return "\xC2\x85"; case '_': // U+00A0 NO-BREAK SPACE return "\xC2\xA0"; case 'L': // U+2028 LINE SEPARATOR return "\xE2\x80\xA8"; case 'P': // U+2029 PARAGRAPH SEPARATOR return "\xE2\x80\xA9"; case 'x': return self::utf8chr(hexdec(substr($value, 2, 2))); case 'u': return self::utf8chr(hexdec(substr($value, 2, 4))); case 'U': return self::utf8chr(hexdec(substr($value, 2, 8))); } } /** * Get the UTF-8 character for the given code point. * * @param int $c The unicode code point * * @return string The corresponding UTF-8 character */ private static function utf8chr($c) { if (0x80 > $c %= 0x200000) { return chr($c); } if (0x800 > $c) { return chr(0xC0 | $c >> 6).chr(0x80 | $c & 0x3F); } if (0x10000 > $c) { return chr(0xE0 | $c >> 12).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F); } return chr(0xF0 | $c >> 18).chr(0x80 | $c >> 12 & 0x3F).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Fabien Potencier * * @api */ interface ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; /** * Exception class thrown when an error occurs during dumping. * * @author Fabien Potencier * * @api */ class DumpException extends RuntimeException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; /** * Exception class thrown when an error occurs during parsing. * * @author Fabien Potencier * * @api */ class ParseException extends RuntimeException { private $parsedFile; private $parsedLine; private $snippet; private $rawMessage; /** * Constructor. * * @param string $message The error message * @param int $parsedLine The line where the error occurred * @param int $snippet The snippet of code near the problem * @param string $parsedFile The file name where the error occurred * @param \Exception $previous The previous exception */ public function __construct($message, $parsedLine = -1, $snippet = null, $parsedFile = null, \Exception $previous = null) { $this->parsedFile = $parsedFile; $this->parsedLine = $parsedLine; $this->snippet = $snippet; $this->rawMessage = $message; $this->updateRepr(); parent::__construct($this->message, 0, $previous); } /** * Gets the snippet of code near the error. * * @return string The snippet of code */ public function getSnippet() { return $this->snippet; } /** * Sets the snippet of code near the error. * * @param string $snippet The code snippet */ public function setSnippet($snippet) { $this->snippet = $snippet; $this->updateRepr(); } /** * Gets the filename where the error occurred. * * This method returns null if a string is parsed. * * @return string The filename */ public function getParsedFile() { return $this->parsedFile; } /** * Sets the filename where the error occurred. * * @param string $parsedFile The filename */ public function setParsedFile($parsedFile) { $this->parsedFile = $parsedFile; $this->updateRepr(); } /** * Gets the line where the error occurred. * * @return int The file line */ public function getParsedLine() { return $this->parsedLine; } /** * Sets the line where the error occurred. * * @param int $parsedLine The file line */ public function setParsedLine($parsedLine) { $this->parsedLine = $parsedLine; $this->updateRepr(); } private function updateRepr() { $this->message = $this->rawMessage; $dot = false; if ('.' === substr($this->message, -1)) { $this->message = substr($this->message, 0, -1); $dot = true; } if (null !== $this->parsedFile) { if (PHP_VERSION_ID >= 50400) { $jsonOptions = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; } else { $jsonOptions = 0; } $this->message .= sprintf(' in %s', json_encode($this->parsedFile, $jsonOptions)); } if ($this->parsedLine >= 0) { $this->message .= sprintf(' at line %d', $this->parsedLine); } if ($this->snippet) { $this->message .= sprintf(' (near "%s")', $this->snippet); } if ($dot) { $this->message .= '.'; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Exception; /** * Exception class thrown when an error occurs during parsing. * * @author Romain Neutron * * @api */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml; /** * Escaper encapsulates escaping rules for single and double-quoted * YAML strings. * * @author Matthew Lewinski */ class Escaper { // Characters that would cause a dumped string to require double quoting. const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9"; // Mapping arrays for escaping a double quoted string. The backslash is // first to ensure proper escaping because str_replace operates iteratively // on the input arrays. This ordering of the characters avoids the use of strtr, // which performs more slowly. private static $escapees = array('\\', '\\\\', '\\"', '"', "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07", "\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f", "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f", "\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9",); private static $escaped = array('\\\\', '\\"', '\\\\', '\\"', '\\0', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\a', '\\b', '\\t', '\\n', '\\v', '\\f', '\\r', '\\x0e', '\\x0f', '\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17', '\\x18', '\\x19', '\\x1a', '\\e', '\\x1c', '\\x1d', '\\x1e', '\\x1f', '\\N', '\\_', '\\L', '\\P',); /** * Determines if a PHP value would require double quoting in YAML. * * @param string $value A PHP value * * @return bool True if the value would require double quotes. */ public static function requiresDoubleQuoting($value) { return preg_match('/'.self::REGEX_CHARACTER_TO_ESCAPE.'/u', $value); } /** * Escapes and surrounds a PHP value with double quotes. * * @param string $value A PHP value * * @return string The quoted, escaped string */ public static function escapeWithDoubleQuotes($value) { return sprintf('"%s"', str_replace(self::$escapees, self::$escaped, $value)); } /** * Determines if a PHP value would require single quoting in YAML. * * @param string $value A PHP value * * @return bool True if the value would require single quotes. */ public static function requiresSingleQuoting($value) { // Determines if a PHP value is entirely composed of a value that would // require single quoting in YAML. if (in_array(strtolower($value), array('null', '~', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off'))) { return true; } // Determines if the PHP value contains any single characters that would // cause it to require single quoting in YAML. return preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ \- ? | < > = ! % @ ` ]/x', $value); } /** * Escapes and surrounds a PHP value with single quotes. * * @param string $value A PHP value * * @return string The quoted, escaped string */ public static function escapeWithSingleQuotes($value) { return sprintf("'%s'", str_replace('\'', '\'\'', $value)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ApcClassLoader implements a wrapping autoloader cached in APC for PHP 5.3. * * It expects an object implementing a findFile method to find the file. This * allows using it as a wrapper around the other loaders of the component (the * ClassLoader and the UniversalClassLoader for instance) but also around any * other autoloaders following this convention (the Composer one for instance). * * // with a Symfony autoloader * use Symfony\Component\ClassLoader\ClassLoader; * * $loader = new ClassLoader(); * $loader->addPrefix('Symfony\Component', __DIR__.'/component'); * $loader->addPrefix('Symfony', __DIR__.'/framework'); * * // or with a Composer autoloader * use Composer\Autoload\ClassLoader; * * $loader = new ClassLoader(); * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * $cachedLoader = new ApcClassLoader('my_prefix', $loader); * * // activate the cached autoloader * $cachedLoader->register(); * * // eventually deactivate the non-cached loader if it was registered previously * // to be sure to use the cached one. * $loader->unregister(); * * @author Fabien Potencier * @author Kris Wallsmith * * @api */ class ApcClassLoader { private $prefix; /** * A class loader object that implements the findFile() method. * * @var object */ protected $decorated; /** * Constructor. * * @param string $prefix The APC namespace prefix to use. * @param object $decorated A class loader object that implements the findFile() method. * * @throws \RuntimeException * @throws \InvalidArgumentException * * @api */ public function __construct($prefix, $decorated) { if (!extension_loaded('apc')) { throw new \RuntimeException('Unable to use ApcClassLoader as APC is not enabled.'); } if (!method_exists($decorated, 'findFile')) { throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); } $this->prefix = $prefix; $this->decorated = $decorated; } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return bool|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds a file by class name while caching lookups to APC. * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { if (false === $file = apc_fetch($this->prefix.$class)) { apc_store($this->prefix.$class, $file = $this->decorated->findFile($class)); } return $file; } /** * Passes through all unknown calls onto the decorated object. */ public function __call($method, $args) { return call_user_func_array(array($this->decorated, $method), $args); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ClassLoader implements an PSR-0 class loader. * * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md * * $loader = new ClassLoader(); * * // register classes with namespaces * $loader->addPrefix('Symfony\Component', __DIR__.'/component'); * $loader->addPrefix('Symfony', __DIR__.'/framework'); * * // activate the autoloader * $loader->register(); * * // to enable searching the include path (e.g. for PEAR packages) * $loader->setUseIncludePath(true); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * @author Fabien Potencier * @author Jordi Boggiano */ class ClassLoader { private $prefixes = array(); private $fallbackDirs = array(); private $useIncludePath = false; /** * Returns prefixes. * * @return array */ public function getPrefixes() { return $this->prefixes; } /** * Returns fallback directories. * * @return array */ public function getFallbackDirs() { return $this->fallbackDirs; } /** * Adds prefixes. * * @param array $prefixes Prefixes to add */ public function addPrefixes(array $prefixes) { foreach ($prefixes as $prefix => $path) { $this->addPrefix($prefix, $path); } } /** * Registers a set of classes. * * @param string $prefix The classes prefix * @param array|string $paths The location(s) of the classes */ public function addPrefix($prefix, $paths) { if (!$prefix) { foreach ((array) $paths as $path) { $this->fallbackDirs[] = $path; } return; } if (isset($this->prefixes[$prefix])) { $this->prefixes[$prefix] = array_merge( $this->prefixes[$prefix], (array) $paths ); } else { $this->prefixes[$prefix] = (array) $paths; } } /** * Turns on searching the include for class files. * * @param bool $useIncludePath */ public function setUseIncludePath($useIncludePath) { $this->useIncludePath = (bool) $useIncludePath; } /** * Can be used to check if the autoloader uses the include path to check * for classes. * * @return bool */ public function getUseIncludePath() { return $this->useIncludePath; } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return bool|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|null The path, if found */ public function findFile($class) { if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR; $className = substr($class, $pos + 1); } else { // PEAR-like class name $classPath = null; $className = $class; } $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; foreach ($this->prefixes as $prefix => $dirs) { if ($class === strstr($class, $prefix)) { foreach ($dirs as $dir) { if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { return $dir.DIRECTORY_SEPARATOR.$classPath; } } } } foreach ($this->fallbackDirs as $dir) { if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { return $dir.DIRECTORY_SEPARATOR.$classPath; } } if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) { return $file; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ApcUniversalClassLoader implements a "universal" autoloader cached in APC for PHP 5.3. * * It is able to load classes that use either: * * * The technical interoperability standards for PHP 5.3 namespaces and * class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md); * * * The PEAR naming convention for classes (http://pear.php.net/). * * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be * looked for in a list of locations to ease the vendoring of a sub-set of * classes for large projects. * * Example usage: * * require 'vendor/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; * require 'vendor/symfony/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; * * use Symfony\Component\ClassLoader\ApcUniversalClassLoader; * * $loader = new ApcUniversalClassLoader('apc.prefix.'); * * // register classes with namespaces * $loader->registerNamespaces(array( * 'Symfony\Component' => __DIR__.'/component', * 'Symfony' => __DIR__.'/framework', * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), * )); * * // register a library using the PEAR naming convention * $loader->registerPrefixes(array( * 'Swift_' => __DIR__.'/Swift', * )); * * // activate the autoloader * $loader->register(); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * @author Fabien Potencier * @author Kris Wallsmith * * @api * * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use the ApcClassLoader class instead. */ class ApcUniversalClassLoader extends UniversalClassLoader { private $prefix; /** * Constructor. * * @param string $prefix A prefix to create a namespace in APC * * @throws \RuntimeException * * @api */ public function __construct($prefix) { if (!extension_loaded('apc')) { throw new \RuntimeException('Unable to use ApcUniversalClassLoader as APC is not enabled.'); } $this->prefix = $prefix; } /** * Finds a file by class name while caching lookups to APC. * * @param string $class A class name to resolve to file * * @return string|null The path, if found */ public function findFile($class) { if (false === $file = apc_fetch($this->prefix.$class)) { apc_store($this->prefix.$class, $file = parent::findFile($class)); } return $file; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; if (!defined('SYMFONY_TRAIT')) { if (PHP_VERSION_ID >= 50400) { define('SYMFONY_TRAIT', T_TRAIT); } else { define('SYMFONY_TRAIT', 0); } } /** * ClassMapGenerator. * * @author Gyula Sallai */ class ClassMapGenerator { /** * Generate a class map file. * * @param array|string $dirs Directories or a single path to search in * @param string $file The name of the class map file */ public static function dump($dirs, $file) { $dirs = (array) $dirs; $maps = array(); foreach ($dirs as $dir) { $maps = array_merge($maps, static::createMap($dir)); } file_put_contents($file, sprintf('isFile()) { continue; } $path = $file->getRealPath(); if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') { continue; } $classes = self::findClasses($path); foreach ($classes as $class) { $map[$class] = $path; } } return $map; } /** * Extract the classes in the given file. * * @param string $path The file to check * * @return array The found classes */ private static function findClasses($path) { $contents = file_get_contents($path); $tokens = token_get_all($contents); $classes = array(); $namespace = ''; for ($i = 0, $max = count($tokens); $i < $max; ++$i) { $token = $tokens[$i]; if (is_string($token)) { continue; } $class = ''; switch ($token[0]) { case T_NAMESPACE: $namespace = ''; // If there is a namespace, extract it while (($t = $tokens[++$i]) && is_array($t)) { if (in_array($t[0], array(T_STRING, T_NS_SEPARATOR))) { $namespace .= $t[1]; } } $namespace .= '\\'; break; case T_CLASS: case T_INTERFACE: case SYMFONY_TRAIT: // Find the classname while (($t = $tokens[++$i]) && is_array($t)) { if (T_STRING === $t[0]) { $class .= $t[1]; } elseif ($class !== '' && T_WHITESPACE == $t[0]) { break; } } $classes[] = ltrim($namespace.$class, '\\'); break; default: break; } } return $classes; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * WinCacheClassLoader implements a wrapping autoloader cached in WinCache. * * It expects an object implementing a findFile method to find the file. This * allow using it as a wrapper around the other loaders of the component (the * ClassLoader and the UniversalClassLoader for instance) but also around any * other autoloaders following this convention (the Composer one for instance). * * // with a Symfony autoloader * use Symfony\Component\ClassLoader\ClassLoader; * * $loader = new ClassLoader(); * $loader->addPrefix('Symfony\Component', __DIR__.'/component'); * $loader->addPrefix('Symfony', __DIR__.'/framework'); * * // or with a Composer autoloader * use Composer\Autoload\ClassLoader; * * $loader = new ClassLoader(); * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * $cachedLoader = new WinCacheClassLoader('my_prefix', $loader); * * // activate the cached autoloader * $cachedLoader->register(); * * // eventually deactivate the non-cached loader if it was registered previously * // to be sure to use the cached one. * $loader->unregister(); * * @author Fabien Potencier * @author Kris Wallsmith * @author Artem Ryzhkov */ class WinCacheClassLoader { private $prefix; /** * A class loader object that implements the findFile() method. * * @var object */ protected $decorated; /** * Constructor. * * @param string $prefix The WinCache namespace prefix to use. * @param object $decorated A class loader object that implements the findFile() method. * * @throws \RuntimeException * @throws \InvalidArgumentException */ public function __construct($prefix, $decorated) { if (!extension_loaded('wincache')) { throw new \RuntimeException('Unable to use WinCacheClassLoader as WinCache is not enabled.'); } if (!method_exists($decorated, 'findFile')) { throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); } $this->prefix = $prefix; $this->decorated = $decorated; } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return bool|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds a file by class name while caching lookups to WinCache. * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { if (false === $file = wincache_ucache_get($this->prefix.$class)) { wincache_ucache_set($this->prefix.$class, $file = $this->decorated->findFile($class), 0); } return $file; } /** * Passes through all unknown calls onto the decorated object. */ public function __call($method, $args) { return call_user_func_array(array($this->decorated, $method), $args); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * Checks that the class is actually declared in the included file. * * @author Fabien Potencier * * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use the DebugClassLoader provided by the Debug component instead. */ class DebugUniversalClassLoader extends UniversalClassLoader { /** * Replaces all regular UniversalClassLoader instances by a DebugUniversalClassLoader ones. */ public static function enable() { if (!is_array($functions = spl_autoload_functions())) { return; } foreach ($functions as $function) { spl_autoload_unregister($function); } foreach ($functions as $function) { if (is_array($function) && $function[0] instanceof UniversalClassLoader) { $loader = new static(); $loader->registerNamespaceFallbacks($function[0]->getNamespaceFallbacks()); $loader->registerPrefixFallbacks($function[0]->getPrefixFallbacks()); $loader->registerNamespaces($function[0]->getNamespaces()); $loader->registerPrefixes($function[0]->getPrefixes()); $loader->useIncludePath($function[0]->getUseIncludePath()); $function[0] = $loader; } spl_autoload_register($function); } } /** * {@inheritdoc} */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) { throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * A PSR-4 compatible class loader. * * See http://www.php-fig.org/psr/psr-4/ * * @author Alexander M. Turek */ class Psr4ClassLoader { /** * @var array */ private $prefixes = array(); /** * @param string $prefix * @param string $baseDir */ public function addPrefix($prefix, $baseDir) { $prefix = trim($prefix, '\\').'\\'; $baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; $this->prefixes[] = array($prefix, $baseDir); } /** * @param string $class * * @return string|null */ public function findFile($class) { $class = ltrim($class, '\\'); foreach ($this->prefixes as $current) { list($currentPrefix, $currentBaseDir) = $current; if (0 === strpos($class, $currentPrefix)) { $classWithoutPrefix = substr($class, strlen($currentPrefix)); $file = $currentBaseDir.str_replace('\\', DIRECTORY_SEPARATOR, $classWithoutPrefix).'.php'; if (file_exists($file)) { return $file; } } } } /** * @param string $class * * @return bool */ public function loadClass($class) { $file = $this->findFile($class); if (null !== $file) { require $file; return true; } return false; } /** * Registers this instance as an autoloader. * * @param bool $prepend */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Removes this instance from the registered autoloaders. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * XcacheClassLoader implements a wrapping autoloader cached in XCache for PHP 5.3. * * It expects an object implementing a findFile method to find the file. This * allows using it as a wrapper around the other loaders of the component (the * ClassLoader and the UniversalClassLoader for instance) but also around any * other autoloaders following this convention (the Composer one for instance). * * // with a Symfony autoloader * use Symfony\Component\ClassLoader\ClassLoader; * * $loader = new ClassLoader(); * $loader->addPrefix('Symfony\Component', __DIR__.'/component'); * $loader->addPrefix('Symfony', __DIR__.'/framework'); * * // or with a Composer autoloader * use Composer\Autoload\ClassLoader; * * $loader = new ClassLoader(); * $loader->add('Symfony\Component', __DIR__.'/component'); * $loader->add('Symfony', __DIR__.'/framework'); * * $cachedLoader = new XcacheClassLoader('my_prefix', $loader); * * // activate the cached autoloader * $cachedLoader->register(); * * // eventually deactivate the non-cached loader if it was registered previously * // to be sure to use the cached one. * $loader->unregister(); * * @author Fabien Potencier * @author Kris Wallsmith * @author Kim Hemsø Rasmussen * * @api */ class XcacheClassLoader { private $prefix; /** * A class loader object that implements the findFile() method. * * @var object */ private $decorated; /** * Constructor. * * @param string $prefix The XCache namespace prefix to use. * @param object $decorated A class loader object that implements the findFile() method. * * @throws \RuntimeException * @throws \InvalidArgumentException * * @api */ public function __construct($prefix, $decorated) { if (!extension_loaded('xcache')) { throw new \RuntimeException('Unable to use XcacheClassLoader as XCache is not enabled.'); } if (!method_exists($decorated, 'findFile')) { throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); } $this->prefix = $prefix; $this->decorated = $decorated; } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return bool|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds a file by class name while caching lookups to Xcache. * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { if (xcache_isset($this->prefix.$class)) { $file = xcache_get($this->prefix.$class); } else { $file = $this->decorated->findFile($class); xcache_set($this->prefix.$class, $file); } return $file; } /** * Passes through all unknown calls onto the decorated object. */ public function __call($method, $args) { return call_user_func_array(array($this->decorated, $method), $args); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * ClassCollectionLoader. * * @author Fabien Potencier */ class ClassCollectionLoader { private static $loaded; private static $seen; private static $useTokenizer = true; /** * Loads a list of classes and caches them in one big file. * * @param array $classes An array of classes to load * @param string $cacheDir A cache directory * @param string $name The cache name prefix * @param bool $autoReload Whether to flush the cache when the cache is stale or not * @param bool $adaptive Whether to remove already declared classes or not * @param string $extension File extension of the resulting file * * @throws \InvalidArgumentException When class can't be loaded */ public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = false, $extension = '.php') { // each $name can only be loaded once per PHP process if (isset(self::$loaded[$name])) { return; } self::$loaded[$name] = true; $declared = array_merge(get_declared_classes(), get_declared_interfaces()); if (function_exists('get_declared_traits')) { $declared = array_merge($declared, get_declared_traits()); } if ($adaptive) { // don't include already declared classes $classes = array_diff($classes, $declared); // the cache is different depending on which classes are already declared $name = $name.'-'.substr(hash('sha256', implode('|', $classes)), 0, 5); } $classes = array_unique($classes); $cache = $cacheDir.'/'.$name.$extension; // auto-reload $reload = false; if ($autoReload) { $metadata = $cache.'.meta'; if (!is_file($metadata) || !is_file($cache)) { $reload = true; } else { $time = filemtime($cache); $meta = unserialize(file_get_contents($metadata)); sort($meta[1]); sort($classes); if ($meta[1] != $classes) { $reload = true; } else { foreach ($meta[0] as $resource) { if (!is_file($resource) || filemtime($resource) > $time) { $reload = true; break; } } } } } if (!$reload && is_file($cache)) { require_once $cache; return; } $files = array(); $content = ''; foreach (self::getOrderedClasses($classes) as $class) { if (in_array($class->getName(), $declared)) { continue; } $files[] = $class->getFileName(); $c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($class->getFileName())); // fakes namespace declaration for global code if (!$class->inNamespace()) { $c = "\nnamespace\n{\n".$c."\n}\n"; } $c = self::fixNamespaceDeclarations('getName()])) { return array(); } self::$seen[$class->getName()] = true; $classes = array($class); $parent = $class; while (($parent = $parent->getParentClass()) && $parent->isUserDefined() && !isset(self::$seen[$parent->getName()])) { self::$seen[$parent->getName()] = true; array_unshift($classes, $parent); } $traits = array(); if (function_exists('get_declared_traits')) { foreach ($classes as $c) { foreach (self::resolveDependencies(self::computeTraitDeps($c), $c) as $trait) { if ($trait !== $c) { $traits[] = $trait; } } } } return array_merge(self::getInterfaces($class), $traits, $classes); } private static function getInterfaces(\ReflectionClass $class) { $classes = array(); foreach ($class->getInterfaces() as $interface) { $classes = array_merge($classes, self::getInterfaces($interface)); } if ($class->isUserDefined() && $class->isInterface() && !isset(self::$seen[$class->getName()])) { self::$seen[$class->getName()] = true; $classes[] = $class; } return $classes; } private static function computeTraitDeps(\ReflectionClass $class) { $traits = $class->getTraits(); $deps = array($class->getName() => $traits); while ($trait = array_pop($traits)) { if ($trait->isUserDefined() && !isset(self::$seen[$trait->getName()])) { self::$seen[$trait->getName()] = true; $traitDeps = $trait->getTraits(); $deps[$trait->getName()] = $traitDeps; $traits = array_merge($traits, $traitDeps); } } return $deps; } /** * Dependencies resolution. * * This function does not check for circular dependencies as it should never * occur with PHP traits. * * @param array $tree The dependency tree * @param \ReflectionClass $node The node * @param \ArrayObject $resolved An array of already resolved dependencies * @param \ArrayObject $unresolved An array of dependencies to be resolved * * @return \ArrayObject The dependencies for the given node * * @throws \RuntimeException if a circular dependency is detected */ private static function resolveDependencies(array $tree, $node, \ArrayObject $resolved = null, \ArrayObject $unresolved = null) { if (null === $resolved) { $resolved = new \ArrayObject(); } if (null === $unresolved) { $unresolved = new \ArrayObject(); } $nodeName = $node->getName(); if (isset($tree[$nodeName])) { $unresolved[$nodeName] = $node; foreach ($tree[$nodeName] as $dependency) { if (!$resolved->offsetExists($dependency->getName())) { self::resolveDependencies($tree, $dependency, $resolved, $unresolved); } } $resolved[$nodeName] = $node; unset($unresolved[$nodeName]); } return $resolved; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * UniversalClassLoader implements a "universal" autoloader for PHP 5.3. * * It is able to load classes that use either: * * * The technical interoperability standards for PHP 5.3 namespaces and * class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md); * * * The PEAR naming convention for classes (http://pear.php.net/). * * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be * looked for in a list of locations to ease the vendoring of a sub-set of * classes for large projects. * * Example usage: * * $loader = new UniversalClassLoader(); * * // register classes with namespaces * $loader->registerNamespaces(array( * 'Symfony\Component' => __DIR__.'/component', * 'Symfony' => __DIR__.'/framework', * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), * )); * * // register a library using the PEAR naming convention * $loader->registerPrefixes(array( * 'Swift_' => __DIR__.'/Swift', * )); * * * // to enable searching the include path (e.g. for PEAR packages) * $loader->useIncludePath(true); * * // activate the autoloader * $loader->register(); * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ * directory, and it will then fallback to the framework/ directory if not * found before giving up. * * @author Fabien Potencier * * @api * * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use the ClassLoader class instead. */ class UniversalClassLoader { private $namespaces = array(); private $prefixes = array(); private $namespaceFallbacks = array(); private $prefixFallbacks = array(); private $useIncludePath = false; /** * Turns on searching the include for class files. Allows easy loading * of installed PEAR packages. * * @param bool $useIncludePath */ public function useIncludePath($useIncludePath) { $this->useIncludePath = (bool) $useIncludePath; } /** * Can be used to check if the autoloader uses the include path to check * for classes. * * @return bool */ public function getUseIncludePath() { return $this->useIncludePath; } /** * Gets the configured namespaces. * * @return array A hash with namespaces as keys and directories as values */ public function getNamespaces() { return $this->namespaces; } /** * Gets the configured class prefixes. * * @return array A hash with class prefixes as keys and directories as values */ public function getPrefixes() { return $this->prefixes; } /** * Gets the directory(ies) to use as a fallback for namespaces. * * @return array An array of directories */ public function getNamespaceFallbacks() { return $this->namespaceFallbacks; } /** * Gets the directory(ies) to use as a fallback for class prefixes. * * @return array An array of directories */ public function getPrefixFallbacks() { return $this->prefixFallbacks; } /** * Registers the directory to use as a fallback for namespaces. * * @param array $dirs An array of directories * * @api */ public function registerNamespaceFallbacks(array $dirs) { $this->namespaceFallbacks = $dirs; } /** * Registers a directory to use as a fallback for namespaces. * * @param string $dir A directory */ public function registerNamespaceFallback($dir) { $this->namespaceFallbacks[] = $dir; } /** * Registers directories to use as a fallback for class prefixes. * * @param array $dirs An array of directories * * @api */ public function registerPrefixFallbacks(array $dirs) { $this->prefixFallbacks = $dirs; } /** * Registers a directory to use as a fallback for class prefixes. * * @param string $dir A directory */ public function registerPrefixFallback($dir) { $this->prefixFallbacks[] = $dir; } /** * Registers an array of namespaces. * * @param array $namespaces An array of namespaces (namespaces as keys and locations as values) * * @api */ public function registerNamespaces(array $namespaces) { foreach ($namespaces as $namespace => $locations) { $this->namespaces[$namespace] = (array) $locations; } } /** * Registers a namespace. * * @param string $namespace The namespace * @param array|string $paths The location(s) of the namespace * * @api */ public function registerNamespace($namespace, $paths) { $this->namespaces[$namespace] = (array) $paths; } /** * Registers an array of classes using the PEAR naming convention. * * @param array $classes An array of classes (prefixes as keys and locations as values) * * @api */ public function registerPrefixes(array $classes) { foreach ($classes as $prefix => $locations) { $this->prefixes[$prefix] = (array) $locations; } } /** * Registers a set of classes using the PEAR naming convention. * * @param string $prefix The classes prefix * @param array|string $paths The location(s) of the classes * * @api */ public function registerPrefix($prefix, $paths) { $this->prefixes[$prefix] = (array) $paths; } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not * * @api */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return bool|null True, if loaded */ public function loadClass($class) { if ($file = $this->findFile($class)) { require $file; return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|null The path, if found */ public function findFile($class) { if (false !== $pos = strrpos($class, '\\')) { // namespaced class name $namespace = substr($class, 0, $pos); $className = substr($class, $pos + 1); $normalizedClass = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; foreach ($this->namespaces as $ns => $dirs) { if (0 !== strpos($namespace, $ns)) { continue; } foreach ($dirs as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } foreach ($this->namespaceFallbacks as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } else { // PEAR-like class name $normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; foreach ($this->prefixes as $prefix => $dirs) { if (0 !== strpos($class, $prefix)) { continue; } foreach ($dirs as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } foreach ($this->prefixFallbacks as $dir) { $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass; if (is_file($file)) { return $file; } } } if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) { return $file; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * A class loader that uses a mapping file to look up paths. * * @author Fabien Potencier */ class MapClassLoader { private $map = array(); /** * Constructor. * * @param array $map A map where keys are classes and values the absolute file path */ public function __construct(array $map) { $this->map = $map; } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Loads the given class or interface. * * @param string $class The name of the class */ public function loadClass($class) { if (isset($this->map[$class])) { require $this->map[$class]; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|null The path, if found */ public function findFile($class) { if (isset($this->map[$class])) { return $this->map[$class]; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ClassLoader; /** * Autoloader checking if the class is really defined in the file found. * * The DebugClassLoader will wrap all registered autoloaders providing a * findFile method and will throw an exception if a file is found but does * not declare the class. * * @author Fabien Potencier * @author Christophe Coevoet * * @api * * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use the DebugClassLoader provided by the Debug component instead. */ class DebugClassLoader { private $classFinder; /** * Constructor. * * @param object $classFinder * * @api */ public function __construct($classFinder) { $this->classFinder = $classFinder; } /** * Gets the wrapped class loader. * * @return object a class loader instance */ public function getClassLoader() { return $this->classFinder; } /** * Replaces all autoloaders implementing a findFile method by a DebugClassLoader wrapper. */ public static function enable() { if (!is_array($functions = spl_autoload_functions())) { return; } foreach ($functions as $function) { spl_autoload_unregister($function); } foreach ($functions as $function) { if (is_array($function) && !$function[0] instanceof self && method_exists($function[0], 'findFile')) { $function = array(new static($function[0]), 'loadClass'); } spl_autoload_register($function); } } /** * Unregisters this instance as an autoloader. */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Finds a file by class name. * * @param string $class A class name to resolve to file * * @return string|null */ public function findFile($class) { return $this->classFinder->findFile($class); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return bool|null True, if loaded * * @throws \RuntimeException */ public function loadClass($class) { if ($file = $this->classFinder->findFile($class)) { require $file; if (!class_exists($class, false) && !interface_exists($class, false) && (!function_exists('trait_exists') || !trait_exists($class, false))) { if (false !== strpos($class, '/')) { throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); } throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); } return true; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * IdentityTranslator does not translate anything. * * @author Fabien Potencier * * @api */ class IdentityTranslator implements TranslatorInterface { private $selector; /** * Constructor. * * @param MessageSelector $selector The message selector for pluralization * * @api */ public function __construct(MessageSelector $selector) { $this->selector = $selector; } /** * {@inheritdoc} * * @api */ public function setLocale($locale) { } /** * {@inheritdoc} * * @api */ public function getLocale() { } /** * {@inheritdoc} * * @api */ public function trans($id, array $parameters = array(), $domain = 'messages', $locale = null) { return strtr((string) $id, $parameters); } /** * {@inheritdoc} * * @api */ public function transChoice($id, $number, array $parameters = array(), $domain = 'messages', $locale = null) { return strtr($this->selector->choose((string) $id, (int) $number, $locale), $parameters); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Writer; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Dumper\DumperInterface; /** * TranslationWriter writes translation messages. * * @author Michel Salib */ class TranslationWriter { /** * Dumpers used for export. * * @var array */ private $dumpers = array(); /** * Adds a dumper to the writer. * * @param string $format The format of the dumper * @param DumperInterface $dumper The dumper */ public function addDumper($format, DumperInterface $dumper) { $this->dumpers[$format] = $dumper; } /** * Obtains the list of supported formats. * * @return array */ public function getFormats() { return array_keys($this->dumpers); } /** * Writes translation from the catalogue according to the selected format. * * @param MessageCatalogue $catalogue The message catalogue to dump * @param string $format The format to use to dump the messages * @param array $options Options that are passed to the dumper * * @throws \InvalidArgumentException */ public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array()) { if (!isset($this->dumpers[$format])) { throw new \InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format)); } // get the right dumper $dumper = $this->dumpers[$format]; // save $dumper->dump($catalogue, $options); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * Returns the plural rules for a given locale. * * @author Fabien Potencier */ class PluralizationRules { // @codeCoverageIgnoreStart private static $rules = array(); /** * Returns the plural position to use for the given locale and number. * * @param integer $number The number * @param string $locale The locale * * @return integer The plural position */ public static function get($number, $locale) { if ("pt_BR" == $locale) { // temporary set a locale for brazilian $locale = "xbr"; } if (strlen($locale) > 3) { $locale = substr($locale, 0, -strlen(strrchr($locale, '_'))); } if (isset(self::$rules[$locale])) { $return = call_user_func(self::$rules[$locale], $number); if (!is_int($return) || $return < 0) { return 0; } return $return; } /* * The plural rules are derived from code of the Zend Framework (2010-09-25), * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd). * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) */ switch ($locale) { case 'bo': case 'dz': case 'id': case 'ja': case 'jv': case 'ka': case 'km': case 'kn': case 'ko': case 'ms': case 'th': case 'tr': case 'vi': case 'zh': return 0; break; case 'af': case 'az': case 'bn': case 'bg': case 'ca': case 'da': case 'de': case 'el': case 'en': case 'eo': case 'es': case 'et': case 'eu': case 'fa': case 'fi': case 'fo': case 'fur': case 'fy': case 'gl': case 'gu': case 'ha': case 'he': case 'hu': case 'is': case 'it': case 'ku': case 'lb': case 'ml': case 'mn': case 'mr': case 'nah': case 'nb': case 'ne': case 'nl': case 'nn': case 'no': case 'om': case 'or': case 'pa': case 'pap': case 'ps': case 'pt': case 'so': case 'sq': case 'sv': case 'sw': case 'ta': case 'te': case 'tk': case 'ur': case 'zu': return ($number == 1) ? 0 : 1; case 'am': case 'bh': case 'fil': case 'fr': case 'gun': case 'hi': case 'ln': case 'mg': case 'nso': case 'xbr': case 'ti': case 'wa': return (($number == 0) || ($number == 1)) ? 0 : 1; case 'be': case 'bs': case 'hr': case 'ru': case 'sr': case 'uk': return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'cs': case 'sk': return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); case 'ga': return ($number == 1) ? 0 : (($number == 2) ? 1 : 2); case 'lt': return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'sl': return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3)); case 'mk': return ($number % 10 == 1) ? 0 : 1; case 'mt': return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); case 'lv': return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2); case 'pl': return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); case 'cy': return ($number == 1) ? 0 : (($number == 2) ? 1 : ((($number == 8) || ($number == 11)) ? 2 : 3)); case 'ro': return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); case 'ar': return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number >= 3) && ($number <= 10)) ? 3 : ((($number >= 11) && ($number <= 99)) ? 4 : 5)))); default: return 0; } } /** * Overrides the default plural rule for a given locale. * * @param string $rule A PHP callable * @param string $locale The locale * * @return null * * @throws \LogicException */ public static function set($rule, $locale) { if ("pt_BR" == $locale) { // temporary set a locale for brazilian $locale = "xbr"; } if (strlen($locale) > 3) { $locale = substr($locale, 0, -strlen(strrchr($locale, '_'))); } if (!is_callable($rule)) { throw new \LogicException('The given rule can not be called'); } self::$rules[$locale] = $rule; } // @codeCoverageIgnoreEnd } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Extractor; use Symfony\Component\Translation\MessageCatalogue; /** * Extracts translation messages from a template directory to the catalogue. * New found messages are injected to the catalogue using the prefix. * * @author Michel Salib */ interface ExtractorInterface { /** * Extracts translation messages from a template directory to the catalogue. * * @param string $directory The path to look into * @param MessageCatalogue $catalogue The catalogue */ public function extract($directory, MessageCatalogue $catalogue); /** * Sets the prefix that should be used for new found messages. * * @param string $prefix The prefix */ public function setPrefix($prefix); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Extractor; use Symfony\Component\Translation\MessageCatalogue; /** * ChainExtractor extracts translation messages from template files. * * @author Michel Salib */ class ChainExtractor implements ExtractorInterface { /** * The extractors. * * @var ExtractorInterface[] */ private $extractors = array(); /** * Adds a loader to the translation extractor. * * @param string $format The format of the loader * @param ExtractorInterface $extractor The loader */ public function addExtractor($format, ExtractorInterface $extractor) { $this->extractors[$format] = $extractor; } /** * {@inheritDoc} */ public function setPrefix($prefix) { foreach ($this->extractors as $extractor) { $extractor->setPrefix($prefix); } } /** * {@inheritDoc} */ public function extract($directory, MessageCatalogue $catalogue) { foreach ($this->extractors as $extractor) { $extractor->extract($directory, $catalogue); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * TranslatorInterface. * * @author Fabien Potencier * * @api */ interface TranslatorInterface { /** * Translates the given message. * * @param string $id The message id (may also be an object that can be cast to string) * @param array $parameters An array of parameters for the message * @param string $domain The domain for the message * @param string $locale The locale * * @return string The translated string * * @api */ public function trans($id, array $parameters = array(), $domain = null, $locale = null); /** * Translates the given choice message by choosing a translation according to a number. * * @param string $id The message id (may also be an object that can be cast to string) * @param integer $number The number to use to find the indice of the message * @param array $parameters An array of parameters for the message * @param string $domain The domain for the message * @param string $locale The locale * * @return string The translated string * * @api */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null); /** * Sets the current locale. * * @param string $locale The locale * * @api */ public function setLocale($locale); /** * Returns the current locale. * * @return string The locale * * @api */ public function getLocale(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; use Symfony\Component\Config\Resource\ResourceInterface; /** * MessageCatalogue. * * @author Fabien Potencier * * @api */ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface { private $messages = array(); private $metadata = array(); private $resources = array(); private $locale; private $fallbackCatalogue; private $parent; /** * Constructor. * * @param string $locale The locale * @param array $messages An array of messages classified by domain * * @api */ public function __construct($locale, array $messages = array()) { $this->locale = $locale; $this->messages = $messages; } /** * {@inheritdoc} * * @api */ public function getLocale() { return $this->locale; } /** * {@inheritdoc} * * @api */ public function getDomains() { return array_keys($this->messages); } /** * {@inheritdoc} * * @api */ public function all($domain = null) { if (null === $domain) { return $this->messages; } return isset($this->messages[$domain]) ? $this->messages[$domain] : array(); } /** * {@inheritdoc} * * @api */ public function set($id, $translation, $domain = 'messages') { $this->add(array($id => $translation), $domain); } /** * {@inheritdoc} * * @api */ public function has($id, $domain = 'messages') { if (isset($this->messages[$domain][$id])) { return true; } if (null !== $this->fallbackCatalogue) { return $this->fallbackCatalogue->has($id, $domain); } return false; } /** * {@inheritdoc} */ public function defines($id, $domain = 'messages') { return isset($this->messages[$domain][$id]); } /** * {@inheritdoc} * * @api */ public function get($id, $domain = 'messages') { if (isset($this->messages[$domain][$id])) { return $this->messages[$domain][$id]; } if (null !== $this->fallbackCatalogue) { return $this->fallbackCatalogue->get($id, $domain); } return $id; } /** * {@inheritdoc} * * @api */ public function replace($messages, $domain = 'messages') { $this->messages[$domain] = array(); $this->add($messages, $domain); } /** * {@inheritdoc} * * @api */ public function add($messages, $domain = 'messages') { if (!isset($this->messages[$domain])) { $this->messages[$domain] = $messages; } else { $this->messages[$domain] = array_replace($this->messages[$domain], $messages); } } /** * {@inheritdoc} * * @api */ public function addCatalogue(MessageCatalogueInterface $catalogue) { if ($catalogue->getLocale() !== $this->locale) { throw new \LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s"', $catalogue->getLocale(), $this->locale)); } foreach ($catalogue->all() as $domain => $messages) { $this->add($messages, $domain); } foreach ($catalogue->getResources() as $resource) { $this->addResource($resource); } if ($catalogue instanceof MetadataAwareInterface) { $metadata = $catalogue->getMetadata('', ''); $this->addMetadata($metadata); } } /** * {@inheritdoc} * * @api */ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue) { // detect circular references $c = $this; do { if ($c->getLocale() === $catalogue->getLocale()) { throw new \LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale())); } } while ($c = $c->parent); $catalogue->parent = $this; $this->fallbackCatalogue = $catalogue; foreach ($catalogue->getResources() as $resource) { $this->addResource($resource); } } /** * {@inheritdoc} * * @api */ public function getFallbackCatalogue() { return $this->fallbackCatalogue; } /** * {@inheritdoc} * * @api */ public function getResources() { return array_values($this->resources); } /** * {@inheritdoc} * * @api */ public function addResource(ResourceInterface $resource) { $this->resources[$resource->__toString()] = $resource; } /** * {@inheritdoc} */ public function getMetadata($key = '', $domain = 'messages') { if ('' == $domain) { return $this->metadata; } if (isset($this->metadata[$domain])) { if ('' == $key) { return $this->metadata[$domain]; } if (isset($this->metadata[$domain][$key])) { return $this->metadata[$domain][$key]; } } return null; } /** * {@inheritdoc} */ public function setMetadata($key, $value, $domain = 'messages') { $this->metadata[$domain][$key] = $value; } /** * {@inheritdoc} */ public function deleteMetadata($key = '', $domain = 'messages') { if ('' == $domain) { $this->metadata = array(); } elseif ('' == $key) { unset($this->metadata[$domain]); } else { unset($this->metadata[$domain][$key]); } } /** * Adds current values with the new values. * * @param array $values Values to add */ private function addMetadata(array $values) { foreach ($values as $domain => $keys) { foreach ($keys as $key => $value) { $this->setMetadata($key, $value, $domain); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * MessageSelector. * * @author Fabien Potencier * * @api */ class MessageSelector { /** * Given a message with different plural translations separated by a * pipe (|), this method returns the correct portion of the message based * on the given number, locale and the pluralization rules in the message * itself. * * The message supports two different types of pluralization rules: * * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples * indexed: There is one apple|There are %count% apples * * The indexed solution can also contain labels (e.g. one: There is one apple). * This is purely for making the translations more clear - it does not * affect the functionality. * * The two methods can also be mixed: * {0} There are no apples|one: There is one apple|more: There are %count% apples * * @param string $message The message being translated * @param integer $number The number of items represented for the message * @param string $locale The locale to use for choosing * * @return string * * @throws \InvalidArgumentException * * @api */ public function choose($message, $number, $locale) { $parts = explode('|', $message); $explicitRules = array(); $standardRules = array(); foreach ($parts as $part) { $part = trim($part); if (preg_match('/^(?P'.Interval::getIntervalRegexp().')\s*(?P.*?)$/x', $part, $matches)) { $explicitRules[$matches['interval']] = $matches['message']; } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) { $standardRules[] = $matches[1]; } else { $standardRules[] = $part; } } // try to match an explicit rule, then fallback to the standard ones foreach ($explicitRules as $interval => $m) { if (Interval::test($number, $interval)) { return $m; } } $position = PluralizationRules::get($number, $locale); if (!isset($standardRules[$position])) { throw new \InvalidArgumentException(sprintf('Unable to choose a translation for "%s" with locale "%s". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $message, $locale)); } return $standardRules[$position]; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; use Symfony\Component\Config\Resource\ResourceInterface; /** * MessageCatalogueInterface. * * @author Fabien Potencier * * @api */ interface MessageCatalogueInterface { /** * Gets the catalogue locale. * * @return string The locale * * @api */ public function getLocale(); /** * Gets the domains. * * @return array An array of domains * * @api */ public function getDomains(); /** * Gets the messages within a given domain. * * If $domain is null, it returns all messages. * * @param string $domain The domain name * * @return array An array of messages * * @api */ public function all($domain = null); /** * Sets a message translation. * * @param string $id The message id * @param string $translation The messages translation * @param string $domain The domain name * * @api */ public function set($id, $translation, $domain = 'messages'); /** * Checks if a message has a translation. * * @param string $id The message id * @param string $domain The domain name * * @return Boolean true if the message has a translation, false otherwise * * @api */ public function has($id, $domain = 'messages'); /** * Checks if a message has a translation (it does not take into account the fallback mechanism). * * @param string $id The message id * @param string $domain The domain name * * @return Boolean true if the message has a translation, false otherwise * * @api */ public function defines($id, $domain = 'messages'); /** * Gets a message translation. * * @param string $id The message id * @param string $domain The domain name * * @return string The message translation * * @api */ public function get($id, $domain = 'messages'); /** * Sets translations for a given domain. * * @param array $messages An array of translations * @param string $domain The domain name * * @api */ public function replace($messages, $domain = 'messages'); /** * Adds translations for a given domain. * * @param array $messages An array of translations * @param string $domain The domain name * * @api */ public function add($messages, $domain = 'messages'); /** * Merges translations from the given Catalogue into the current one. * * The two catalogues must have the same locale. * * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance * * @api */ public function addCatalogue(MessageCatalogueInterface $catalogue); /** * Merges translations from the given Catalogue into the current one * only when the translation does not exist. * * This is used to provide default translations when they do not exist for the current locale. * * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance * * @api */ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue); /** * Gets the fallback catalogue. * * @return MessageCatalogueInterface|null A MessageCatalogueInterface instance or null when no fallback has been set * * @api */ public function getFallbackCatalogue(); /** * Returns an array of resources loaded to build this collection. * * @return ResourceInterface[] An array of resources * * @api */ public function getResources(); /** * Adds a resource for this collection. * * @param ResourceInterface $resource A resource instance * * @api */ public function addResource(ResourceInterface $resource); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * PoFileDumper generates a gettext formatted string representation of a message catalogue. * * @author Stealth35 */ class PoFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $output = ''; $newLine = false; foreach ($messages->all($domain) as $source => $target) { if ($newLine) { $output .= "\n"; } else { $newLine = true; } $output .= sprintf('msgid "%s"'."\n", $this->escape($source)); $output .= sprintf('msgstr "%s"', $this->escape($target)); } return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'po'; } private function escape($str) { return addcslashes($str, "\0..\37\42\134"); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * DumperInterface is the interface implemented by all translation dumpers. * There is no common option. * * @author Michel Salib */ interface DumperInterface { /** * Dumps the message catalogue. * * @param MessageCatalogue $messages The message catalogue * @param array $options Options that are used by the dumper */ public function dump(MessageCatalogue $messages, $options = array()); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * IniFileDumper generates an ini formatted string representation of a message catalogue. * * @author Stealth35 */ class IniFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $output = ''; foreach ($messages->all($domain) as $source => $target) { $escapeTarget = str_replace('"', '\"', $target); $output .= $source.'="'.$escapeTarget."\"\n"; } return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'ini'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * PhpFileDumper generates php files from a message catalogue. * * @author Michel Salib */ class PhpFileDumper extends FileDumper { /** * {@inheritDoc} */ protected function format(MessageCatalogue $messages, $domain) { $output = "all($domain), true).";\n"; return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'php'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue. * * @author Stealth35 */ class IcuResFileDumper implements DumperInterface { /** * {@inheritDoc} */ public function dump(MessageCatalogue $messages, $options = array()) { if (!array_key_exists('path', $options)) { throw new \InvalidArgumentException('The file dumper need a path options.'); } // save a file for each domain foreach ($messages->getDomains() as $domain) { $file = $messages->getLocale().'.'.$this->getExtension(); $path = $options['path'].'/'.$domain.'/'; if (!file_exists($path)) { mkdir($path); } // backup if (file_exists($path.$file)) { copy($path.$file, $path.$file.'~'); } // save file file_put_contents($path.$file, $this->format($messages, $domain)); } } /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $data = $indexes = $resources = ''; foreach ($messages->all($domain) as $source => $target) { $indexes .= pack('v', strlen($data) + 28); $data .= $source."\0"; } $data .= $this->writePadding($data); $keyTop = $this->getPosition($data); foreach ($messages->all($domain) as $source => $target) { $resources .= pack('V', $this->getPosition($data)); $data .= pack('V', strlen($target)) .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8') .$this->writePadding($data) ; } $resOffset = $this->getPosition($data); $data .= pack('v', count($messages)) .$indexes .$this->writePadding($data) .$resources ; $bundleTop = $this->getPosition($data); $root = pack('V7', $resOffset + (2 << 28), // Resource Offset + Resource Type 6, // Index length $keyTop, // Index keys top $bundleTop, // Index resources top $bundleTop, // Index bundle top count($messages), // Index max table length 0 // Index attributes ); $header = pack('vC2v4C12@32', 32, // Header size 0xDA, 0x27, // Magic number 1 and 2 20, 0, 0, 2, // Rest of the header, ..., Size of a char 0x52, 0x65, 0x73, 0x42, // Data format identifier 1, 2, 0, 0, // Data version 1, 4, 0, 0 // Unicode version ); $output = $header .$root .$data; return $output; } private function writePadding($data) { $padding = strlen($data) % 4; if ($padding) { return str_repeat("\xAA", 4 - $padding); } } private function getPosition($data) { $position = (strlen($data) + 28) / 4; return $position; } /** * {@inheritDoc} */ protected function getExtension() { return 'res'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * CsvFileDumper generates a csv formatted string representation of a message catalogue. * * @author Stealth35 */ class CsvFileDumper extends FileDumper { private $delimiter = ';'; private $enclosure = '"'; /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $handle = fopen('php://memory', 'rb+'); foreach ($messages->all($domain) as $source => $target) { fputcsv($handle, array($source, $target), $this->delimiter, $this->enclosure); } rewind($handle); $output = stream_get_contents($handle); fclose($handle); return $output; } /** * Sets the delimiter and escape character for CSV. * * @param string $delimiter delimiter character * @param string $enclosure enclosure character */ public function setCsvControl($delimiter = ';', $enclosure = '"') { $this->delimiter = $delimiter; $this->enclosure = $enclosure; } /** * {@inheritDoc} */ protected function getExtension() { return 'csv'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Yaml\Yaml; /** * YamlFileDumper generates yaml files from a message catalogue. * * @author Michel Salib */ class YamlFileDumper extends FileDumper { /** * {@inheritDoc} */ protected function format(MessageCatalogue $messages, $domain) { return Yaml::dump($messages->all($domain)); } /** * {@inheritDoc} */ protected function getExtension() { return 'yml'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * XliffFileDumper generates xliff files from a message catalogue. * * @author Michel Salib */ class XliffFileDumper extends FileDumper { /** * {@inheritDoc} */ protected function format(MessageCatalogue $messages, $domain) { $dom = new \DOMDocument('1.0', 'utf-8'); $dom->formatOutput = true; $xliff = $dom->appendChild($dom->createElement('xliff')); $xliff->setAttribute('version', '1.2'); $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2'); $xliffFile = $xliff->appendChild($dom->createElement('file')); $xliffFile->setAttribute('source-language', $messages->getLocale()); $xliffFile->setAttribute('datatype', 'plaintext'); $xliffFile->setAttribute('original', 'file.ext'); $xliffBody = $xliffFile->appendChild($dom->createElement('body')); foreach ($messages->all($domain) as $source => $target) { $translation = $dom->createElement('trans-unit'); $translation->setAttribute('id', md5($source)); $translation->setAttribute('resname', $source); $s = $translation->appendChild($dom->createElement('source')); $s->appendChild($dom->createTextNode($source)); $t = $translation->appendChild($dom->createElement('target')); $t->appendChild($dom->createTextNode($target)); $xliffBody->appendChild($translation); } return $dom->saveXML(); } /** * {@inheritDoc} */ protected function getExtension() { return 'xlf'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s). * Performs backup of already existing files. * * Options: * - path (mandatory): the directory where the files should be saved * * @author Michel Salib */ abstract class FileDumper implements DumperInterface { /** * {@inheritDoc} */ public function dump(MessageCatalogue $messages, $options = array()) { if (!array_key_exists('path', $options)) { throw new \InvalidArgumentException('The file dumper need a path options.'); } // save a file for each domain foreach ($messages->getDomains() as $domain) { $file = $domain.'.'.$messages->getLocale().'.'.$this->getExtension(); // backup $fullpath = $options['path'].'/'.$file; if (file_exists($fullpath)) { copy($fullpath, $fullpath.'~'); } // save file file_put_contents($fullpath, $this->format($messages, $domain)); } } /** * Transforms a domain of a message catalogue to its string representation. * * @param MessageCatalogue $messages * @param string $domain * * @return string representation */ abstract protected function format(MessageCatalogue $messages, $domain); /** * Gets the file extension of the dumper. * * @return string file extension */ abstract protected function getExtension(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; /** * QtFileDumper generates ts files from a message catalogue. * * @author Benjamin Eberlei */ class QtFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain) { $dom = new \DOMDocument('1.0', 'utf-8'); $dom->formatOutput = true; $ts = $dom->appendChild($dom->createElement('TS')); $context = $ts->appendChild($dom->createElement('context')); $context->appendChild($dom->createElement('name', $domain)); foreach ($messages->all($domain) as $source => $target) { $message = $context->appendChild($dom->createElement('message')); $message->appendChild($dom->createElement('source', $source)); $message->appendChild($dom->createElement('translation', $target)); } return $dom->saveXML(); } /** * {@inheritDoc} */ protected function getExtension() { return 'ts'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Dumper; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Loader\MoFileLoader; /** * MoFileDumper generates a gettext formatted string representation of a message catalogue. * * @author Stealth35 */ class MoFileDumper extends FileDumper { /** * {@inheritDoc} */ public function format(MessageCatalogue $messages, $domain = 'messages') { $output = $sources = $targets = $sourceOffsets = $targetOffsets = ''; $offsets = array(); $size = 0; foreach ($messages->all($domain) as $source => $target) { $offsets[] = array_map('strlen', array($sources, $source, $targets, $target)); $sources .= "\0".$source; $targets .= "\0".$target; ++$size; } $header = array( 'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC, 'formatRevision' => 0, 'count' => $size, 'offsetId' => MoFileLoader::MO_HEADER_SIZE, 'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size), 'sizeHashes' => 0, 'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size), ); $sourcesSize = strlen($sources); $sourcesStart = $header['offsetHashes'] + 1; foreach ($offsets as $offset) { $sourceOffsets .= $this->writeLong($offset[1]) .$this->writeLong($offset[0] + $sourcesStart); $targetOffsets .= $this->writeLong($offset[3]) .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize); } $output = implode(array_map(array($this, 'writeLong'), $header)) .$sourceOffsets .$targetOffsets .$sources .$targets ; return $output; } /** * {@inheritDoc} */ protected function getExtension() { return 'mo'; } private function writeLong($str) { return pack('V*', $str); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; use Symfony\Component\Translation\Loader\LoaderInterface; use Symfony\Component\Translation\Exception\NotFoundResourceException; /** * Translator. * * @author Fabien Potencier * * @api */ class Translator implements TranslatorInterface { /** * @var MessageCatalogueInterface[] */ protected $catalogues = array(); /** * @var string */ protected $locale; /** * @var array */ private $fallbackLocales = array(); /** * @var LoaderInterface[] */ private $loaders = array(); /** * @var array */ private $resources = array(); /** * @var MessageSelector */ private $selector; /** * Constructor. * * @param string $locale The locale * @param MessageSelector|null $selector The message selector for pluralization * * @api */ public function __construct($locale, MessageSelector $selector = null) { $this->locale = $locale; $this->selector = $selector ?: new MessageSelector(); } /** * Adds a Loader. * * @param string $format The name of the loader (@see addResource()) * @param LoaderInterface $loader A LoaderInterface instance * * @api */ public function addLoader($format, LoaderInterface $loader) { $this->loaders[$format] = $loader; } /** * Adds a Resource. * * @param string $format The name of the loader (@see addLoader()) * @param mixed $resource The resource name * @param string $locale The locale * @param string $domain The domain * * @api */ public function addResource($format, $resource, $locale, $domain = null) { if (null === $domain) { $domain = 'messages'; } $this->resources[$locale][] = array($format, $resource, $domain); if (in_array($locale, $this->fallbackLocales)) { $this->catalogues = array(); } else { unset($this->catalogues[$locale]); } } /** * {@inheritdoc} * * @api */ public function setLocale($locale) { $this->locale = $locale; } /** * {@inheritdoc} * * @api */ public function getLocale() { return $this->locale; } /** * Sets the fallback locale(s). * * @param string|array $locales The fallback locale(s) * * @deprecated since 2.3, to be removed in 3.0. Use setFallbackLocales() instead. * * @api */ public function setFallbackLocale($locales) { $this->setFallbackLocales(is_array($locales) ? $locales : array($locales)); } /** * Sets the fallback locales. * * @param array $locales The fallback locales * * @api */ public function setFallbackLocales(array $locales) { // needed as the fallback locales are linked to the already loaded catalogues $this->catalogues = array(); $this->fallbackLocales = $locales; } /** * Gets the fallback locales. * * @return array $locales The fallback locales * * @api */ public function getFallbackLocales() { return $this->fallbackLocales; } /** * {@inheritdoc} * * @api */ public function trans($id, array $parameters = array(), $domain = null, $locale = null) { if (null === $locale) { $locale = $this->getLocale(); } if (null === $domain) { $domain = 'messages'; } if (!isset($this->catalogues[$locale])) { $this->loadCatalogue($locale); } return strtr($this->catalogues[$locale]->get((string) $id, $domain), $parameters); } /** * {@inheritdoc} * * @api */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) { if (null === $locale) { $locale = $this->getLocale(); } if (null === $domain) { $domain = 'messages'; } if (!isset($this->catalogues[$locale])) { $this->loadCatalogue($locale); } $id = (string) $id; $catalogue = $this->catalogues[$locale]; while (!$catalogue->defines($id, $domain)) { if ($cat = $catalogue->getFallbackCatalogue()) { $catalogue = $cat; $locale = $catalogue->getLocale(); } else { break; } } return strtr($this->selector->choose($catalogue->get($id, $domain), (int) $number, $locale), $parameters); } protected function loadCatalogue($locale) { try { $this->doLoadCatalogue($locale); } catch (NotFoundResourceException $e) { if (!$this->computeFallbackLocales($locale)) { throw $e; } } $this->loadFallbackCatalogues($locale); } private function doLoadCatalogue($locale) { $this->catalogues[$locale] = new MessageCatalogue($locale); if (isset($this->resources[$locale])) { foreach ($this->resources[$locale] as $resource) { if (!isset($this->loaders[$resource[0]])) { throw new \RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0])); } $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2])); } } } private function loadFallbackCatalogues($locale) { $current = $this->catalogues[$locale]; foreach ($this->computeFallbackLocales($locale) as $fallback) { if (!isset($this->catalogues[$fallback])) { $this->doLoadCatalogue($fallback); } $current->addFallbackCatalogue($this->catalogues[$fallback]); $current = $this->catalogues[$fallback]; } } protected function computeFallbackLocales($locale) { $locales = array(); foreach ($this->fallbackLocales as $fallback) { if ($fallback === $locale) { continue; } $locales[] = $fallback; } if (strrchr($locale, '_') !== false) { array_unshift($locales, substr($locale, 0, -strlen(strrchr($locale, '_')))); } return array_unique($locales); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; use Symfony\Component\Translation\MessageCatalogueInterface; /** * Represents an operation on catalogue(s). * * @author Jean-François Simon */ interface OperationInterface { /** * Returns domains affected by operation. * * @return array */ public function getDomains(); /** * Returns all valid messages after operation. * * @param string $domain * * @return array */ public function getMessages($domain); /** * Returns new messages after operation. * * @param string $domain * * @return array */ public function getNewMessages($domain); /** * Returns obsolete messages after operation. * * @param string $domain * * @return array */ public function getObsoleteMessages($domain); /** * Returns resulting catalogue. * * @return MessageCatalogueInterface */ public function getResult(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\MessageCatalogueInterface; /** * Base catalogues binary operation class. * * @author Jean-François Simon */ abstract class AbstractOperation implements OperationInterface { /** * @var MessageCatalogueInterface */ protected $source; /** * @var MessageCatalogueInterface */ protected $target; /** * @var MessageCatalogue */ protected $result; /** * @var null|array */ private $domains; /** * @var array */ protected $messages; /** * @param MessageCatalogueInterface $source * @param MessageCatalogueInterface $target * * @throws \LogicException */ public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target) { if ($source->getLocale() !== $target->getLocale()) { throw new \LogicException('Operated catalogues must belong to the same locale.'); } $this->source = $source; $this->target = $target; $this->result = new MessageCatalogue($source->getLocale()); $this->domains = null; $this->messages = array(); } /** * {@inheritdoc} */ public function getDomains() { if (null === $this->domains) { $this->domains = array_values(array_unique(array_merge($this->source->getDomains(), $this->target->getDomains()))); } return $this->domains; } /** * {@inheritdoc} */ public function getMessages($domain) { if (!in_array($domain, $this->getDomains())) { throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain)); } if (!isset($this->messages[$domain]['all'])) { $this->processDomain($domain); } return $this->messages[$domain]['all']; } /** * {@inheritdoc} */ public function getNewMessages($domain) { if (!in_array($domain, $this->getDomains())) { throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain)); } if (!isset($this->messages[$domain]['new'])) { $this->processDomain($domain); } return $this->messages[$domain]['new']; } /** * {@inheritdoc} */ public function getObsoleteMessages($domain) { if (!in_array($domain, $this->getDomains())) { throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain)); } if (!isset($this->messages[$domain]['obsolete'])) { $this->processDomain($domain); } return $this->messages[$domain]['obsolete']; } /** * {@inheritdoc} */ public function getResult() { foreach ($this->getDomains() as $domain) { if (!isset($this->messages[$domain])) { $this->processDomain($domain); } } return $this->result; } /** * @param string $domain */ abstract protected function processDomain($domain); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; /** * Diff operation between two catalogues. * * @author Jean-François Simon */ class DiffOperation extends AbstractOperation { /** * {@inheritdoc} */ protected function processDomain($domain) { $this->messages[$domain] = array( 'all' => array(), 'new' => array(), 'obsolete' => array(), ); foreach ($this->source->all($domain) as $id => $message) { if ($this->target->has($id, $domain)) { $this->messages[$domain]['all'][$id] = $message; $this->result->add(array($id => $message), $domain); } else { $this->messages[$domain]['obsolete'][$id] = $message; } } foreach ($this->target->all($domain) as $id => $message) { if (!$this->source->has($id, $domain)) { $this->messages[$domain]['all'][$id] = $message; $this->messages[$domain]['new'][$id] = $message; $this->result->add(array($id => $message), $domain); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Catalogue; /** * Merge operation between two catalogues. * * @author Jean-François Simon */ class MergeOperation extends AbstractOperation { /** * {@inheritdoc} */ protected function processDomain($domain) { $this->messages[$domain] = array( 'all' => array(), 'new' => array(), 'obsolete' => array(), ); foreach ($this->source->all($domain) as $id => $message) { $this->messages[$domain]['all'][$id] = $message; $this->result->add(array($id => $message), $domain); } foreach ($this->target->all($domain) as $id => $message) { if (!$this->source->has($id, $domain)) { $this->messages[$domain]['all'][$id] = $message; $this->messages[$domain]['new'][$id] = $message; $this->result->add(array($id => $message), $domain); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * MetadataAwareInterface. * * @author Fabien Potencier */ interface MetadataAwareInterface { /** * Gets metadata for the given domain and key. * * Passing an empty domain will return an array with all metadata indexed by * domain and then by key. Passing an empty key will return an array with all * metadata for the given domain. * * @param string $domain The domain name * @param string $key The key * * @return mixed The value that was set or an array with the domains/keys or null */ public function getMetadata($key = '', $domain = 'messages'); /** * Adds metadata to a message domain. * * @param string $key The key * @param mixed $value The value * @param string $domain The domain name */ public function setMetadata($key, $value, $domain = 'messages'); /** * Deletes metadata for the given key and domain. * * Passing an empty domain will delete all metadata. Passing an empty key will * delete all metadata for the given domain. * * @param string $domain The domain name * @param string $key The key */ public function deleteMetadata($key = '', $domain = 'messages'); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Exception; /** * Exception interface for all exceptions thrown by the component. * * @author Fabien Potencier * * @api */ interface ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Exception; /** * Thrown when a resource cannot be loaded. * * @author Fabien Potencier * * @api */ class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Exception; /** * Thrown when a resource does not exist. * * @author Fabien Potencier * * @api */ class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * XliffFileLoader loads translations from XLIFF files. * * @author Fabien Potencier * * @api */ class XliffFileLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } list($xml, $encoding) = $this->parseFile($resource); $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2'); $catalogue = new MessageCatalogue($locale); foreach ($xml->xpath('//xliff:trans-unit') as $translation) { $attributes = $translation->attributes(); if (!(isset($attributes['resname']) || isset($translation->source)) || !isset($translation->target)) { continue; } $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source; $target = (string) $translation->target; // If the xlf file has another encoding specified, try to convert it because // simple_xml will always return utf-8 encoded values if ('UTF-8' !== $encoding && !empty($encoding)) { if (function_exists('mb_convert_encoding')) { $target = mb_convert_encoding($target, $encoding, 'UTF-8'); } elseif (function_exists('iconv')) { $target = iconv('UTF-8', $encoding, $target); } else { throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).'); } } $catalogue->set((string) $source, $target, $domain); } $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Validates and parses the given file into a SimpleXMLElement * * @param string $file * * @throws \RuntimeException * * @return \SimpleXMLElement * * @throws InvalidResourceException */ private function parseFile($file) { $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); libxml_clear_errors(); $dom = new \DOMDocument(); $dom->validateOnParse = true; if (!@$dom->loadXML(file_get_contents($file), LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) { libxml_disable_entity_loader($disableEntities); throw new InvalidResourceException(implode("\n", $this->getXmlErrors($internalErrors))); } libxml_disable_entity_loader($disableEntities); foreach ($dom->childNodes as $child) { if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { libxml_use_internal_errors($internalErrors); throw new InvalidResourceException('Document types are not allowed.'); } } $location = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd'; $parts = explode('/', $location); if (0 === stripos($location, 'phar://')) { $tmpfile = tempnam(sys_get_temp_dir(), 'sf2'); if ($tmpfile) { copy($location, $tmpfile); $parts = explode('/', str_replace('\\', '/', $tmpfile)); } } $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts)); $source = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-1.2-strict.xsd'); $source = str_replace('http://www.w3.org/2001/xml.xsd', $location, $source); if (!@$dom->schemaValidateSource($source)) { throw new InvalidResourceException(implode("\n", $this->getXmlErrors($internalErrors))); } $dom->normalizeDocument(); libxml_use_internal_errors($internalErrors); return array(simplexml_import_dom($dom), strtoupper($dom->encoding)); } /** * Returns the XML errors of the internal XML parser * * @param Boolean $internalErrors * * @return array An array of errors */ private function getXmlErrors($internalErrors) { $errors = array(); foreach (libxml_get_errors() as $error) { $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', $error->code, trim($error->message), $error->file ? $error->file : 'n/a', $error->line, $error->column ); } libxml_clear_errors(); libxml_use_internal_errors($internalErrors); return $errors; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * IcuResFileLoader loads translations from a resource bundle. * * @author stealth35 */ class IcuDatFileLoader extends IcuResFileLoader { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource.'.dat')) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource.'.dat')) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $rb = new \ResourceBundle($locale, $resource); if (!$rb) { throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource)); } elseif (intl_is_failure($rb->getErrorCode())) { throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode()); } $messages = $this->flatten($rb); $catalogue = new MessageCatalogue($locale); $catalogue->add($messages, $domain); $catalogue->addResource(new FileResource($resource.'.dat')); return $catalogue; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/) */ class MoFileLoader extends ArrayLoader implements LoaderInterface { /** * Magic used for validating the format of a MO file as well as * detecting if the machine used to create that file was little endian. * * @var float */ const MO_LITTLE_ENDIAN_MAGIC = 0x950412de; /** * Magic used for validating the format of a MO file as well as * detecting if the machine used to create that file was big endian. * * @var float */ const MO_BIG_ENDIAN_MAGIC = 0xde120495; /** * The size of the header of a MO file in bytes. * * @var integer Number of bytes. */ const MO_HEADER_SIZE = 28; public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = $this->parse($resource); // empty file if (null === $messages) { $messages = array(); } // not an array if (!is_array($messages)) { throw new InvalidResourceException(sprintf('The file "%s" must contain a valid mo file.', $resource)); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Parses machine object (MO) format, independent of the machine's endian it * was created on. Both 32bit and 64bit systems are supported. * * @param resource $resource * * @return array * @throws InvalidResourceException If stream content has an invalid format. */ private function parse($resource) { $stream = fopen($resource, 'r'); $stat = fstat($stream); if ($stat['size'] < self::MO_HEADER_SIZE) { throw new InvalidResourceException("MO stream content has an invalid format."); } $magic = unpack('V1', fread($stream, 4)); $magic = hexdec(substr(dechex(current($magic)), -8)); if ($magic == self::MO_LITTLE_ENDIAN_MAGIC) { $isBigEndian = false; } elseif ($magic == self::MO_BIG_ENDIAN_MAGIC) { $isBigEndian = true; } else { throw new InvalidResourceException("MO stream content has an invalid format."); } $formatRevision = $this->readLong($stream, $isBigEndian); $count = $this->readLong($stream, $isBigEndian); $offsetId = $this->readLong($stream, $isBigEndian); $offsetTranslated = $this->readLong($stream, $isBigEndian); $sizeHashes = $this->readLong($stream, $isBigEndian); $offsetHashes = $this->readLong($stream, $isBigEndian); $messages = array(); for ($i = 0; $i < $count; $i++) { $singularId = $pluralId = null; $translated = null; fseek($stream, $offsetId + $i * 8); $length = $this->readLong($stream, $isBigEndian); $offset = $this->readLong($stream, $isBigEndian); if ($length < 1) { continue; } fseek($stream, $offset); $singularId = fread($stream, $length); if (strpos($singularId, "\000") !== false) { list($singularId, $pluralId) = explode("\000", $singularId); } fseek($stream, $offsetTranslated + $i * 8); $length = $this->readLong($stream, $isBigEndian); $offset = $this->readLong($stream, $isBigEndian); fseek($stream, $offset); $translated = fread($stream, $length); if (strpos($translated, "\000") !== false) { $translated = explode("\000", $translated); } $ids = array('singular' => $singularId, 'plural' => $pluralId); $item = compact('ids', 'translated'); if (is_array($item['translated'])) { $messages[$item['ids']['singular']] = stripcslashes($item['translated'][0]); if (isset($item['ids']['plural'])) { $plurals = array(); foreach ($item['translated'] as $plural => $translated) { $plurals[] = sprintf('{%d} %s', $plural, $translated); } $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals)); } } elseif (!empty($item['ids']['singular'])) { $messages[$item['ids']['singular']] = stripcslashes($item['translated']); } } fclose($stream); return array_filter($messages); } /** * Reads an unsigned long from stream respecting endianess. * * @param resource $stream * @param boolean $isBigEndian * @return integer */ private function readLong($stream, $isBigEndian) { $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4)); $result = current($result); return (integer) substr($result, -8); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/) * @copyright Copyright (c) 2012, Clemens Tolboom */ class PoFileLoader extends ArrayLoader implements LoaderInterface { public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = $this->parse($resource); // empty file if (null === $messages) { $messages = array(); } // not an array if (!is_array($messages)) { throw new InvalidResourceException(sprintf('The file "%s" must contain a valid po file.', $resource)); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Parses portable object (PO) format. * * From http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files * we should be able to parse files having: * * white-space * # translator-comments * #. extracted-comments * #: reference... * #, flag... * #| msgid previous-untranslated-string * msgid untranslated-string * msgstr translated-string * * extra or different lines are: * * #| msgctxt previous-context * #| msgid previous-untranslated-string * msgctxt context * * #| msgid previous-untranslated-string-singular * #| msgid_plural previous-untranslated-string-plural * msgid untranslated-string-singular * msgid_plural untranslated-string-plural * msgstr[0] translated-string-case-0 * ... * msgstr[N] translated-string-case-n * * The definition states: * - white-space and comments are optional. * - msgid "" that an empty singleline defines a header. * * This parser sacrifices some features of the reference implementation the * differences to that implementation are as follows. * - No support for comments spanning multiple lines. * - Translator and extracted comments are treated as being the same type. * - Message IDs are allowed to have other encodings as just US-ASCII. * * Items with an empty id are ignored. * * @param resource $resource * * @return array */ private function parse($resource) { $stream = fopen($resource, 'r'); $defaults = array( 'ids' => array(), 'translated' => null, ); $messages = array(); $item = $defaults; while ($line = fgets($stream)) { $line = trim($line); if ($line === '') { // Whitespace indicated current item is done $this->addMessage($messages, $item); $item = $defaults; } elseif (substr($line, 0, 7) === 'msgid "') { // We start a new msg so save previous // TODO: this fails when comments or contexts are added $this->addMessage($messages, $item); $item = $defaults; $item['ids']['singular'] = substr($line, 7, -1); } elseif (substr($line, 0, 8) === 'msgstr "') { $item['translated'] = substr($line, 8, -1); } elseif ($line[0] === '"') { $continues = isset($item['translated']) ? 'translated' : 'ids'; if (is_array($item[$continues])) { end($item[$continues]); $item[$continues][key($item[$continues])] .= substr($line, 1, -1); } else { $item[$continues] .= substr($line, 1, -1); } } elseif (substr($line, 0, 14) === 'msgid_plural "') { $item['ids']['plural'] = substr($line, 14, -1); } elseif (substr($line, 0, 7) === 'msgstr[') { $size = strpos($line, ']'); $item['translated'][(integer) substr($line, 7, 1)] = substr($line, $size + 3, -1); } } // save last item $this->addMessage($messages, $item); fclose($stream); return $messages; } /** * Save a translation item to the messeages. * * A .po file could contain by error missing plural indexes. We need to * fix these before saving them. * * @param array $messages * @param array $item */ private function addMessage(array &$messages, array $item) { if (is_array($item['translated'])) { $messages[$item['ids']['singular']] = stripslashes($item['translated'][0]); if (isset($item['ids']['plural'])) { $plurals = $item['translated']; // PO are by definition indexed so sort by index. ksort($plurals); // Make sure every index is filled. end($plurals); $count = key($plurals); // Fill missing spots with '-'. $empties = array_fill(0, $count+1, '-'); $plurals += $empties; ksort($plurals); $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals)); } } elseif (!empty($item['ids']['singular'])) { $messages[$item['ids']['singular']] = stripslashes($item['translated']); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; /** * LoaderInterface is the interface implemented by all translation loaders. * * @author Fabien Potencier * * @api */ interface LoaderInterface { /** * Loads a locale. * * @param mixed $resource A resource * @param string $locale A locale * @param string $domain The domain * * @return MessageCatalogue A MessageCatalogue instance * * @api * * @throws NotFoundResourceException when the resource cannot be found * @throws InvalidResourceException when the resource cannot be loaded */ public function load($resource, $locale, $domain = 'messages'); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\Yaml\Exception\ParseException; /** * YamlFileLoader loads translations from Yaml files. * * @author Fabien Potencier * * @api */ class YamlFileLoader extends ArrayLoader implements LoaderInterface { private $yamlParser; /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } try { $messages = $this->yamlParser->parse(file_get_contents($resource)); } catch (ParseException $e) { throw new InvalidResourceException('Error parsing YAML.', 0, $e); } // empty file if (null === $messages) { $messages = array(); } // not an array if (!is_array($messages)) { throw new InvalidResourceException(sprintf('The file "%s" must contain a YAML array.', $resource)); } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\DirectoryResource; /** * IcuResFileLoader loads translations from a resource bundle. * * @author stealth35 */ class IcuResFileLoader implements LoaderInterface { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!is_dir($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $rb = new \ResourceBundle($locale, $resource); if (!$rb) { throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource)); } elseif (intl_is_failure($rb->getErrorCode())) { throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode()); } $messages = $this->flatten($rb); $catalogue = new MessageCatalogue($locale); $catalogue->add($messages, $domain); $catalogue->addResource(new DirectoryResource($resource)); return $catalogue; } /** * Flattens an ResourceBundle * * The scheme used is: * key { key2 { key3 { "value" } } } * Becomes: * 'key.key2.key3' => 'value' * * This function takes an array by reference and will modify it * * @param \ResourceBundle $rb the ResourceBundle that will be flattened * @param array $messages used internally for recursive calls * @param string $path current path being parsed, used internally for recursive calls * * @return array the flattened ResourceBundle */ protected function flatten(\ResourceBundle $rb, array &$messages = array(), $path = null) { foreach ($rb as $key => $value) { $nodePath = $path ? $path.'.'.$key : $key; if ($value instanceof \ResourceBundle) { $this->flatten($value, $messages, $nodePath); } else { $messages[$nodePath] = $value; } } return $messages; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * PhpFileLoader loads translations from PHP files returning an array of translations. * * @author Fabien Potencier * * @api */ class PhpFileLoader extends ArrayLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = require($resource); $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * QtFileLoader loads translations from QT Translations XML files. * * @author Benjamin Eberlei * * @api */ class QtFileLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $dom = new \DOMDocument(); $current = libxml_use_internal_errors(true); if (!@$dom->load($resource, defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0)) { throw new InvalidResourceException(implode("\n", $this->getXmlErrors())); } $xpath = new \DOMXPath($dom); $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]'); $catalogue = new MessageCatalogue($locale); if ($nodes->length == 1) { $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message'); foreach ($translations as $translation) { $catalogue->set( (string) $translation->getElementsByTagName('source')->item(0)->nodeValue, (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue, $domain ); $translation = $translation->nextSibling; } $catalogue->addResource(new FileResource($resource)); } libxml_use_internal_errors($current); return $catalogue; } /** * Returns the XML errors of the internal XML parser * * @return array An array of errors */ private function getXmlErrors() { $errors = array(); foreach (libxml_get_errors() as $error) { $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', $error->code, trim($error->message), $error->file ? $error->file : 'n/a', $error->line, $error->column ); } libxml_clear_errors(); libxml_use_internal_errors(false); return $errors; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * CsvFileLoader loads translations from CSV files. * * @author Saša Stamenković * * @api */ class CsvFileLoader extends ArrayLoader implements LoaderInterface { private $delimiter = ';'; private $enclosure = '"'; private $escape = '\\'; /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = array(); try { $file = new \SplFileObject($resource, 'rb'); } catch (\RuntimeException $e) { throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e); } $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY); $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape); foreach ($file as $data) { if (substr($data[0], 0, 1) === '#') { continue; } if (!isset($data[1])) { continue; } if (count($data) == 2) { $messages[$data[0]] = $data[1]; } else { continue; } } $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } /** * Sets the delimiter, enclosure, and escape character for CSV. * * @param string $delimiter delimiter character * @param string $enclosure enclosure character * @param string $escape escape character */ public function setCsvControl($delimiter = ';', $enclosure = '"', $escape = '\\') { $this->delimiter = $delimiter; $this->enclosure = $enclosure; $this->escape = $escape; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\Exception\InvalidResourceException; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Config\Resource\FileResource; /** * IniFileLoader loads translations from an ini file. * * @author stealth35 */ class IniFileLoader extends ArrayLoader implements LoaderInterface { /** * {@inheritdoc} */ public function load($resource, $locale, $domain = 'messages') { if (!stream_is_local($resource)) { throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); } if (!file_exists($resource)) { throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); } $messages = parse_ini_file($resource, true); $catalogue = parent::load($messages, $locale, $domain); $catalogue->addResource(new FileResource($resource)); return $catalogue; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation\Loader; use Symfony\Component\Translation\MessageCatalogue; /** * ArrayLoader loads translations from a PHP array. * * @author Fabien Potencier * * @api */ class ArrayLoader implements LoaderInterface { /** * {@inheritdoc} * * @api */ public function load($resource, $locale, $domain = 'messages') { $this->flatten($resource); $catalogue = new MessageCatalogue($locale); $catalogue->add($resource, $domain); return $catalogue; } /** * Flattens an nested array of translations * * The scheme used is: * 'key' => array('key2' => array('key3' => 'value')) * Becomes: * 'key.key2.key3' => 'value' * * This function takes an array by reference and will modify it * * @param array &$messages The array that will be flattened * @param array $subnode Current subnode being parsed, used internally for recursive calls * @param string $path Current path being parsed, used internally for recursive calls */ private function flatten(array &$messages, array $subnode = null, $path = null) { if (null === $subnode) { $subnode =& $messages; } foreach ($subnode as $key => $value) { if (is_array($value)) { $nodePath = $path ? $path.'.'.$key : $key; $this->flatten($messages, $value, $nodePath); if (null === $path) { unset($messages[$key]); } } elseif (null !== $path) { $messages[$path.'.'.$key] = $value; } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Translation; /** * Tests if a given number belongs to a given math interval. * * An interval can represent a finite set of numbers: * * {1,2,3,4} * * An interval can represent numbers between two numbers: * * [1, +Inf] * ]-1,2[ * * The left delimiter can be [ (inclusive) or ] (exclusive). * The right delimiter can be [ (exclusive) or ] (inclusive). * Beside numbers, you can use -Inf and +Inf for the infinite. * * @author Fabien Potencier * * @see http://en.wikipedia.org/wiki/Interval_%28mathematics%29#The_ISO_notation */ class Interval { /** * Tests if the given number is in the math interval. * * @param integer $number A number * @param string $interval An interval * * @return Boolean * * @throws \InvalidArgumentException */ public static function test($number, $interval) { $interval = trim($interval); if (!preg_match('/^'.self::getIntervalRegexp().'$/x', $interval, $matches)) { throw new \InvalidArgumentException(sprintf('"%s" is not a valid interval.', $interval)); } if ($matches[1]) { foreach (explode(',', $matches[2]) as $n) { if ($number == $n) { return true; } } } else { $leftNumber = self::convertNumber($matches['left']); $rightNumber = self::convertNumber($matches['right']); return ('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber) && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber) ; } return false; } /** * Returns a Regexp that matches valid intervals. * * @return string A Regexp (without the delimiters) */ public static function getIntervalRegexp() { return <<[\[\]]) \s* (?P-Inf|\-?\d+(\.\d+)?) \s*,\s* (?P\+?Inf|\-?\d+(\.\d+)?) \s* (?P[\[\]]) EOF; } private static function convertNumber($number) { if ('-Inf' === $number) { return log(0); } elseif ('+Inf' === $number || 'Inf' === $number) { return -log(0); } return (float) $number; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Stopwatch; /** * Stopwatch provides a way to profile code. * * @author Fabien Potencier */ class Stopwatch { /** * @var Section[] */ private $sections; /** * @var Section[] */ private $activeSections; public function __construct() { $this->sections = $this->activeSections = array('__root__' => new Section('__root__')); } /** * @return Section[] */ public function getSections() { return $this->sections; } /** * Creates a new section or re-opens an existing section. * * @param string|null $id The id of the session to re-open, null to create a new one * * @throws \LogicException When the section to re-open is not reachable */ public function openSection($id = null) { $current = end($this->activeSections); if (null !== $id && null === $current->get($id)) { throw new \LogicException(sprintf('The section "%s" has been started at an other level and can not be opened.', $id)); } $this->start('__section__.child', 'section'); $this->activeSections[] = $current->open($id); $this->start('__section__'); } /** * Stops the last started section. * * The id parameter is used to retrieve the events from this section. * * @see getSectionEvents() * * @param string $id The identifier of the section * * @throws \LogicException When there's no started section to be stopped */ public function stopSection($id) { $this->stop('__section__'); if (1 == count($this->activeSections)) { throw new \LogicException('There is no started section to stop.'); } $this->sections[$id] = array_pop($this->activeSections)->setId($id); $this->stop('__section__.child'); } /** * Starts an event. * * @param string $name The event name * @param string $category The event category * * @return StopwatchEvent A StopwatchEvent instance */ public function start($name, $category = null) { return end($this->activeSections)->startEvent($name, $category); } /** * Checks if the event was started. * * @param string $name The event name * * @return bool */ public function isStarted($name) { return end($this->activeSections)->isEventStarted($name); } /** * Stops an event. * * @param string $name The event name * * @return StopwatchEvent A StopwatchEvent instance */ public function stop($name) { return end($this->activeSections)->stopEvent($name); } /** * Stops then restarts an event. * * @param string $name The event name * * @return StopwatchEvent A StopwatchEvent instance */ public function lap($name) { return end($this->activeSections)->stopEvent($name)->start(); } /** * Returns a specific event by name * * @param string $name The event name * * @return StopwatchEvent A StopwatchEvent instance */ public function getEvent($name) { return end($this->activeSections)->getEvent($name); } /** * Gets all events for a given section. * * @param string $id A section identifier * * @return StopwatchEvent[] An array of StopwatchEvent instances */ public function getSectionEvents($id) { return isset($this->sections[$id]) ? $this->sections[$id]->getEvents() : array(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Stopwatch; /** * Represents an Period for an Event. * * @author Fabien Potencier */ class StopwatchPeriod { private $start; private $end; private $memory; /** * Constructor. * * @param int $start The relative time of the start of the period (in milliseconds) * @param int $end The relative time of the end of the period (in milliseconds) */ public function __construct($start, $end) { $this->start = (int) $start; $this->end = (int) $end; $this->memory = memory_get_usage(true); } /** * Gets the relative time of the start of the period. * * @return int The time (in milliseconds) */ public function getStartTime() { return $this->start; } /** * Gets the relative time of the end of the period. * * @return int The time (in milliseconds) */ public function getEndTime() { return $this->end; } /** * Gets the time spent in this period. * * @return int The period duration (in milliseconds) */ public function getDuration() { return $this->end - $this->start; } /** * Gets the memory usage. * * @return int The memory usage (in bytes) */ public function getMemory() { return $this->memory; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Stopwatch; /** * Represents an Event managed by Stopwatch. * * @author Fabien Potencier */ class StopwatchEvent { /** * @var StopwatchPeriod[] */ private $periods = array(); /** * @var float */ private $origin; /** * @var string */ private $category; /** * @var float[] */ private $started = array(); /** * Constructor. * * @param float $origin The origin time in milliseconds * @param string|null $category The event category or null to use the default * * @throws \InvalidArgumentException When the raw time is not valid */ public function __construct($origin, $category = null) { $this->origin = $this->formatTime($origin); $this->category = is_string($category) ? $category : 'default'; } /** * Gets the category. * * @return string The category */ public function getCategory() { return $this->category; } /** * Gets the origin. * * @return float The origin in milliseconds */ public function getOrigin() { return $this->origin; } /** * Starts a new event period. * * @return StopwatchEvent The event */ public function start() { $this->started[] = $this->getNow(); return $this; } /** * Stops the last started event period. * * @throws \LogicException When start wasn't called before stopping * * @return StopwatchEvent The event * * @throws \LogicException When stop() is called without a matching call to start() */ public function stop() { if (!count($this->started)) { throw new \LogicException('stop() called but start() has not been called before.'); } $this->periods[] = new StopwatchPeriod(array_pop($this->started), $this->getNow()); return $this; } /** * Checks if the event was started. * * @return bool */ public function isStarted() { return !empty($this->started); } /** * Stops the current period and then starts a new one. * * @return StopwatchEvent The event */ public function lap() { return $this->stop()->start(); } /** * Stops all non already stopped periods. */ public function ensureStopped() { while (count($this->started)) { $this->stop(); } } /** * Gets all event periods. * * @return StopwatchPeriod[] An array of StopwatchPeriod instances */ public function getPeriods() { return $this->periods; } /** * Gets the relative time of the start of the first period. * * @return int The time (in milliseconds) */ public function getStartTime() { return isset($this->periods[0]) ? $this->periods[0]->getStartTime() : 0; } /** * Gets the relative time of the end of the last period. * * @return int The time (in milliseconds) */ public function getEndTime() { $count = count($this->periods); return $count ? $this->periods[$count - 1]->getEndTime() : 0; } /** * Gets the duration of the events (including all periods). * * @return int The duration (in milliseconds) */ public function getDuration() { $periods = $this->periods; $stopped = count($periods); $left = count($this->started) - $stopped; for ($i = 0; $i < $left; $i++) { $index = $stopped + $i; $periods[] = new StopwatchPeriod($this->started[$index], $this->getNow()); } $total = 0; foreach ($periods as $period) { $total += $period->getDuration(); } return $total; } /** * Gets the max memory usage of all periods. * * @return int The memory usage (in bytes) */ public function getMemory() { $memory = 0; foreach ($this->periods as $period) { if ($period->getMemory() > $memory) { $memory = $period->getMemory(); } } return $memory; } /** * Return the current time relative to origin. * * @return float Time in ms */ protected function getNow() { return $this->formatTime(microtime(true) * 1000 - $this->origin); } /** * Formats a time. * * @param int|float $time A raw time * * @return float The formatted time * * @throws \InvalidArgumentException When the raw time is not valid */ private function formatTime($time) { if (!is_numeric($time)) { throw new \InvalidArgumentException('The time must be a numerical value'); } return round($time, 1); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Stopwatch; /** * Stopwatch section. * * @author Fabien Potencier */ class Section { /** * @var StopwatchEvent[] */ private $events = array(); /** * @var null|float */ private $origin; /** * @var string */ private $id; /** * @var Section[] */ private $children = array(); /** * Constructor. * * @param float|null $origin Set the origin of the events in this section, use null to set their origin to their start time */ public function __construct($origin = null) { $this->origin = is_numeric($origin) ? $origin : null; } /** * Returns the child section. * * @param string $id The child section identifier * * @return Section|null The child section or null when none found */ public function get($id) { foreach ($this->children as $child) { if ($id === $child->getId()) { return $child; } } } /** * Creates or re-opens a child section. * * @param string|null $id null to create a new section, the identifier to re-open an existing one. * * @return Section A child section */ public function open($id) { if (null === $session = $this->get($id)) { $session = $this->children[] = new self(microtime(true) * 1000); } return $session; } /** * @return string The identifier of the section */ public function getId() { return $this->id; } /** * Sets the session identifier. * * @param string $id The session identifier * * @return Section The current section */ public function setId($id) { $this->id = $id; return $this; } /** * Starts an event. * * @param string $name The event name * @param string $category The event category * * @return StopwatchEvent The event */ public function startEvent($name, $category) { if (!isset($this->events[$name])) { $this->events[$name] = new StopwatchEvent($this->origin ?: microtime(true) * 1000, $category); } return $this->events[$name]->start(); } /** * Checks if the event was started * * @param string $name The event name * * @return bool */ public function isEventStarted($name) { return isset($this->events[$name]) && $this->events[$name]->isStarted(); } /** * Stops an event. * * @param string $name The event name * * @return StopwatchEvent The event * * @throws \LogicException When the event has not been started */ public function stopEvent($name) { if (!isset($this->events[$name])) { throw new \LogicException(sprintf('Event "%s" is not started.', $name)); } return $this->events[$name]->stop(); } /** * Stops then restarts an event. * * @param string $name The event name * * @return StopwatchEvent The event * * @throws \LogicException When the event has not been started */ public function lap($name) { return $this->stopEvent($name)->start(); } /** * Returns a specific event by name * * @param string $name The event name * * @return StopwatchEvent The event * * @throws \LogicException When the event is not known */ public function getEvent($name) { if (!isset($this->events[$name])) { throw new \LogicException(sprintf('Event "%s" is not known.', $name)); } return $this->events[$name]; } /** * Returns the events from this section. * * @return StopwatchEvent[] An array of StopwatchEvent instances */ public function getEvents() { return $this->events; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config; /** * @author Fabien Potencier */ interface FileLocatorInterface { /** * Returns a full path for a given file name. * * @param string $name The file name to locate * @param string|null $currentPath The current path * @param bool $first Whether to return the first occurrence or an array of filenames * * @return string|array The full path to the file or an array of file paths * * @throws \InvalidArgumentException When file is not found */ public function locate($name, $currentPath = null, $first = true); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * This node represents a numeric value in the config tree. * * @author David Jeanmonod */ class NumericNode extends ScalarNode { protected $min; protected $max; public function __construct($name, NodeInterface $parent = null, $min = null, $max = null) { parent::__construct($name, $parent); $this->min = $min; $this->max = $max; } /** * {@inheritdoc} */ protected function finalizeValue($value) { $value = parent::finalizeValue($value); $errorMsg = null; if (isset($this->min) && $value < $this->min) { $errorMsg = sprintf('The value %s is too small for path "%s". Should be greater than or equal to %s', $value, $this->getPath(), $this->min); } if (isset($this->max) && $value > $this->max) { $errorMsg = sprintf('The value %s is too big for path "%s". Should be less than or equal to %s', $value, $this->getPath(), $this->max); } if (isset($errorMsg)) { $ex = new InvalidConfigurationException($errorMsg); $ex->setPath($this->getPath()); throw $ex; } return $value; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\Exception; use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * The base node class. * * @author Johannes M. Schmitt */ abstract class BaseNode implements NodeInterface { protected $name; protected $parent; protected $normalizationClosures = array(); protected $finalValidationClosures = array(); protected $allowOverwrite = true; protected $required = false; protected $equivalentValues = array(); protected $attributes = array(); /** * Constructor. * * @param string $name The name of the node * @param NodeInterface $parent The parent of this node * * @throws \InvalidArgumentException if the name contains a period. */ public function __construct($name, NodeInterface $parent = null) { if (false !== strpos($name, '.')) { throw new \InvalidArgumentException('The name must not contain ".".'); } $this->name = $name; $this->parent = $parent; } public function setAttribute($key, $value) { $this->attributes[$key] = $value; } public function getAttribute($key, $default = null) { return isset($this->attributes[$key]) ? $this->attributes[$key] : $default; } public function hasAttribute($key) { return isset($this->attributes[$key]); } public function getAttributes() { return $this->attributes; } public function setAttributes(array $attributes) { $this->attributes = $attributes; } public function removeAttribute($key) { unset($this->attributes[$key]); } /** * Sets an info message. * * @param string $info */ public function setInfo($info) { $this->setAttribute('info', $info); } /** * Returns info message. * * @return string The info text */ public function getInfo() { return $this->getAttribute('info'); } /** * Sets the example configuration for this node. * * @param string|array $example */ public function setExample($example) { $this->setAttribute('example', $example); } /** * Retrieves the example configuration for this node. * * @return string|array The example */ public function getExample() { return $this->getAttribute('example'); } /** * Adds an equivalent value. * * @param mixed $originalValue * @param mixed $equivalentValue */ public function addEquivalentValue($originalValue, $equivalentValue) { $this->equivalentValues[] = array($originalValue, $equivalentValue); } /** * Set this node as required. * * @param bool $boolean Required node */ public function setRequired($boolean) { $this->required = (bool) $boolean; } /** * Sets if this node can be overridden. * * @param bool $allow */ public function setAllowOverwrite($allow) { $this->allowOverwrite = (bool) $allow; } /** * Sets the closures used for normalization. * * @param \Closure[] $closures An array of Closures used for normalization */ public function setNormalizationClosures(array $closures) { $this->normalizationClosures = $closures; } /** * Sets the closures used for final validation. * * @param \Closure[] $closures An array of Closures used for final validation */ public function setFinalValidationClosures(array $closures) { $this->finalValidationClosures = $closures; } /** * Checks if this node is required. * * @return bool */ public function isRequired() { return $this->required; } /** * Returns the name of this node. * * @return string The Node's name. */ public function getName() { return $this->name; } /** * Retrieves the path of this node. * * @return string The Node's path */ public function getPath() { $path = $this->name; if (null !== $this->parent) { $path = $this->parent->getPath().'.'.$path; } return $path; } /** * Merges two values together. * * @param mixed $leftSide * @param mixed $rightSide * * @return mixed The merged value * * @throws ForbiddenOverwriteException */ final public function merge($leftSide, $rightSide) { if (!$this->allowOverwrite) { throw new ForbiddenOverwriteException(sprintf( 'Configuration path "%s" cannot be overwritten. You have to ' .'define all options for this path, and any of its sub-paths in ' .'one configuration section.', $this->getPath() )); } $this->validateType($leftSide); $this->validateType($rightSide); return $this->mergeValues($leftSide, $rightSide); } /** * Normalizes a value, applying all normalization closures. * * @param mixed $value Value to normalize. * * @return mixed The normalized value. */ final public function normalize($value) { $value = $this->preNormalize($value); // run custom normalization closures foreach ($this->normalizationClosures as $closure) { $value = $closure($value); } // replace value with their equivalent foreach ($this->equivalentValues as $data) { if ($data[0] === $value) { $value = $data[1]; } } // validate type $this->validateType($value); // normalize value return $this->normalizeValue($value); } /** * Normalizes the value before any other normalization is applied. * * @param $value * * @return $value The normalized array value */ protected function preNormalize($value) { return $value; } /** * Returns parent node for this node. * * @return NodeInterface|null */ public function getParent() { return $this->parent; } /** * Finalizes a value, applying all finalization closures. * * @param mixed $value The value to finalize * * @return mixed The finalized value * * @throws Exception * @throws InvalidConfigurationException */ final public function finalize($value) { $this->validateType($value); $value = $this->finalizeValue($value); // Perform validation on the final value if a closure has been set. // The closure is also allowed to return another value. foreach ($this->finalValidationClosures as $closure) { try { $value = $closure($value); } catch (Exception $e) { throw $e; } catch (\Exception $e) { throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": %s', $this->getPath(), $e->getMessage()), $e->getCode(), $e); } } return $value; } /** * Validates the type of a Node. * * @param mixed $value The value to validate * * @throws InvalidTypeException when the value is invalid */ abstract protected function validateType($value); /** * Normalizes the value. * * @param mixed $value The value to normalize. * * @return mixed The normalized value */ abstract protected function normalizeValue($value); /** * Merges two values together. * * @param mixed $leftSide * @param mixed $rightSide * * @return mixed The merged value */ abstract protected function mergeValues($leftSide, $rightSide); /** * Finalizes a value. * * @param mixed $value The value to finalize * * @return mixed The finalized value */ abstract protected function finalizeValue($value); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper; /** * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper instead. */ class ReferenceDumper extends YamlReferenceDumper { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * Node which only allows a finite set of values. * * @author Johannes M. Schmitt */ class EnumNode extends ScalarNode { private $values; public function __construct($name, NodeInterface $parent = null, array $values = array()) { $values = array_unique($values); if (count($values) <= 1) { throw new \InvalidArgumentException('$values must contain at least two distinct elements.'); } parent::__construct($name, $parent); $this->values = $values; } public function getValues() { return $this->values; } protected function finalizeValue($value) { $value = parent::finalizeValue($value); if (!in_array($value, $this->values, true)) { $ex = new InvalidConfigurationException(sprintf( 'The value %s is not allowed for path "%s". Permissible values: %s', json_encode($value), $this->getPath(), implode(', ', array_map('json_encode', $this->values)))); $ex->setPath($this->getPath()); throw $ex; } return $value; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; /** * This node represents a value of variable type in the config tree. * * This node is intended for values of arbitrary type. * Any PHP type is accepted as a value. * * @author Jeremy Mikola */ class VariableNode extends BaseNode implements PrototypeNodeInterface { protected $defaultValueSet = false; protected $defaultValue; protected $allowEmptyValue = true; /** * {@inheritdoc} */ public function setDefaultValue($value) { $this->defaultValueSet = true; $this->defaultValue = $value; } /** * {@inheritdoc} */ public function hasDefaultValue() { return $this->defaultValueSet; } /** * {@inheritdoc} */ public function getDefaultValue() { $v = $this->defaultValue; return $v instanceof \Closure ? $v() : $v; } /** * Sets if this node is allowed to have an empty value. * * @param bool $boolean True if this entity will accept empty values. */ public function setAllowEmptyValue($boolean) { $this->allowEmptyValue = (bool) $boolean; } /** * {@inheritdoc} */ public function setName($name) { $this->name = $name; } /** * {@inheritdoc} */ protected function validateType($value) { } /** * {@inheritdoc} */ protected function finalizeValue($value) { if (!$this->allowEmptyValue && empty($value)) { $ex = new InvalidConfigurationException(sprintf( 'The path "%s" cannot contain an empty value, but got %s.', $this->getPath(), json_encode($value) )); if ($hint = $this->getInfo()) { $ex->addHint($hint); } $ex->setPath($this->getPath()); throw $ex; } return $value; } /** * {@inheritdoc} */ protected function normalizeValue($value) { return $value; } /** * {@inheritdoc} */ protected function mergeValues($leftSide, $rightSide) { return $rightSide; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents an integer value in the config tree. * * @author Jeanmonod David */ class IntegerNode extends NumericNode { /** * {@inheritdoc} */ protected function validateType($value) { if (!is_int($value)) { $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected int, but got %s.', $this->getPath(), gettype($value))); if ($hint = $this->getInfo()) { $ex->addHint($hint); } $ex->setPath($this->getPath()); throw $ex; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * This class is the entry point for config normalization/merging/finalization. * * @author Johannes M. Schmitt */ class Processor { /** * Processes an array of configurations. * * @param NodeInterface $configTree The node tree describing the configuration * @param array $configs An array of configuration items to process * * @return array The processed configuration */ public function process(NodeInterface $configTree, array $configs) { $currentConfig = array(); foreach ($configs as $config) { $config = $configTree->normalize($config); $currentConfig = $configTree->merge($currentConfig, $config); } return $configTree->finalize($currentConfig); } /** * Processes an array of configurations. * * @param ConfigurationInterface $configuration The configuration class * @param array $configs An array of configuration items to process * * @return array The processed configuration */ public function processConfiguration(ConfigurationInterface $configuration, array $configs) { return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs); } /** * Normalizes a configuration entry. * * This method returns a normalize configuration array for a given key * to remove the differences due to the original format (YAML and XML mainly). * * Here is an example. * * The configuration in XML: * * twig.extension.foo * twig.extension.bar * * And the same configuration in YAML: * * extensions: ['twig.extension.foo', 'twig.extension.bar'] * * @param array $config A config array * @param string $key The key to normalize * @param string $plural The plural form of the key if it is irregular * * @return array */ public static function normalizeConfig($config, $key, $plural = null) { if (null === $plural) { $plural = $key.'s'; } if (isset($config[$plural])) { return $config[$plural]; } if (isset($config[$key])) { if (is_string($config[$key]) || !is_int(key($config[$key]))) { // only one return array($config[$key]); } return $config[$key]; } return array(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents a float value in the config tree. * * @author Jeanmonod David */ class FloatNode extends NumericNode { /** * {@inheritdoc} */ protected function validateType($value) { // Integers are also accepted, we just cast them if (is_int($value)) { $value = (float) $value; } if (!is_float($value)) { $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected float, but got %s.', $this->getPath(), gettype($value))); if ($hint = $this->getInfo()) { $ex->addHint($hint); } $ex->setPath($this->getPath()); throw $ex; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * An interface that must be implemented by all node parents. * * @author Victor Berchet */ interface NodeParentInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\IntegerNode; /** * This class provides a fluent interface for defining an integer node. * * @author Jeanmonod David */ class IntegerNodeDefinition extends NumericNodeDefinition { /** * Instantiates a Node. * * @return IntegerNode The node */ protected function instantiateNode() { return new IntegerNode($this->name, $this->parent, $this->min, $this->max); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class builds validation conditions. * * @author Christophe Coevoet */ class ValidationBuilder { protected $node; public $rules = array(); /** * Constructor. * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Registers a closure to run as normalization or an expression builder to build it if null is provided. * * @param \Closure $closure * * @return ExprBuilder|ValidationBuilder */ public function rule(\Closure $closure = null) { if (null !== $closure) { $this->rules[] = $closure; return $this; } return $this->rules[] = new ExprBuilder($this->node); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\BooleanNode; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ class BooleanNodeDefinition extends ScalarNodeDefinition { /** * {@inheritdoc} */ public function __construct($name, NodeParentInterface $parent = null) { parent::__construct($name, $parent); $this->nullEquivalent = true; } /** * Instantiate a Node. * * @return BooleanNode The node */ protected function instantiateNode() { return new BooleanNode($this->name, $this->parent); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\NodeInterface; /** * This is the entry class for building a config tree. * * @author Johannes M. Schmitt */ class TreeBuilder implements NodeParentInterface { protected $tree; protected $root; protected $builder; /** * Creates the root node. * * @param string $name The name of the root node * @param string $type The type of the root node * @param NodeBuilder $builder A custom node builder instance * * @return ArrayNodeDefinition|NodeDefinition The root node (as an ArrayNodeDefinition when the type is 'array') * * @throws \RuntimeException When the node type is not supported */ public function root($name, $type = 'array', NodeBuilder $builder = null) { $builder = $builder ?: new NodeBuilder(); return $this->root = $builder->node($name, $type)->setParent($this); } /** * Builds the tree. * * @return NodeInterface * * @throws \RuntimeException */ public function buildTree() { if (null === $this->root) { throw new \RuntimeException('The configuration tree has no root node.'); } if (null !== $this->tree) { return $this->tree; } return $this->tree = $this->root->getNode(true); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class builds normalization conditions. * * @author Johannes M. Schmitt */ class NormalizationBuilder { protected $node; public $before = array(); public $remappings = array(); /** * Constructor. * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Registers a key to remap to its plural form. * * @param string $key The key to remap * @param string $plural The plural of the key in case of irregular plural * * @return NormalizationBuilder */ public function remap($key, $plural = null) { $this->remappings[] = array($key, null === $plural ? $key.'s' : $plural); return $this; } /** * Registers a closure to run before the normalization or an expression builder to build it if null is provided. * * @param \Closure $closure * * @return ExprBuilder|NormalizationBuilder */ public function before(\Closure $closure = null) { if (null !== $closure) { $this->before[] = $closure; return $this; } return $this->before[] = new ExprBuilder($this->node); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\FloatNode; /** * This class provides a fluent interface for defining a float node. * * @author Jeanmonod David */ class FloatNodeDefinition extends NumericNodeDefinition { /** * Instantiates a Node. * * @return FloatNode The node */ protected function instantiateNode() { return new FloatNode($this->name, $this->parent, $this->min, $this->max); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\EnumNode; /** * Enum Node Definition. * * @author Johannes M. Schmitt */ class EnumNodeDefinition extends ScalarNodeDefinition { private $values; /** * @param array $values * * @return EnumNodeDefinition|$this */ public function values(array $values) { $values = array_unique($values); if (count($values) <= 1) { throw new \InvalidArgumentException('->values() must be called with at least two distinct values.'); } $this->values = $values; return $this; } /** * Instantiate a Node. * * @return EnumNode The node * * @throws \RuntimeException */ protected function instantiateNode() { if (null === $this->values) { throw new \RuntimeException('You must call ->values() on enum nodes.'); } return new EnumNode($this->name, $this->parent, $this->values); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\PrototypedArrayNode; use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; /** * This class provides a fluent interface for defining an array node. * * @author Johannes M. Schmitt */ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface { protected $performDeepMerging = true; protected $ignoreExtraKeys = false; protected $children = array(); protected $prototype; protected $atLeastOne = false; protected $allowNewKeys = true; protected $key; protected $removeKeyItem; protected $addDefaults = false; protected $addDefaultChildren = false; protected $nodeBuilder; protected $normalizeKeys = true; /** * {@inheritdoc} */ public function __construct($name, NodeParentInterface $parent = null) { parent::__construct($name, $parent); $this->nullEquivalent = array(); $this->trueEquivalent = array(); } /** * Sets a custom children builder. * * @param NodeBuilder $builder A custom NodeBuilder */ public function setBuilder(NodeBuilder $builder) { $this->nodeBuilder = $builder; } /** * Returns a builder to add children nodes. * * @return NodeBuilder */ public function children() { return $this->getNodeBuilder(); } /** * Sets a prototype for child nodes. * * @param string $type the type of node * * @return NodeDefinition */ public function prototype($type) { return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this); } /** * Adds the default value if the node is not set in the configuration. * * This method is applicable to concrete nodes only (not to prototype nodes). * If this function has been called and the node is not set during the finalization * phase, it's default value will be derived from its children default values. * * @return ArrayNodeDefinition */ public function addDefaultsIfNotSet() { $this->addDefaults = true; return $this; } /** * Adds children with a default value when none are defined. * * @param int|string|array|null $children The number of children|The child name|The children names to be added * * This method is applicable to prototype nodes only. * * @return ArrayNodeDefinition */ public function addDefaultChildrenIfNoneSet($children = null) { $this->addDefaultChildren = $children; return $this; } /** * Requires the node to have at least one element. * * This method is applicable to prototype nodes only. * * @return ArrayNodeDefinition */ public function requiresAtLeastOneElement() { $this->atLeastOne = true; return $this; } /** * Disallows adding news keys in a subsequent configuration. * * If used all keys have to be defined in the same configuration file. * * @return ArrayNodeDefinition */ public function disallowNewKeysInSubsequentConfigs() { $this->allowNewKeys = false; return $this; } /** * Sets a normalization rule for XML configurations. * * @param string $singular The key to remap * @param string $plural The plural of the key for irregular plurals * * @return ArrayNodeDefinition */ public function fixXmlConfig($singular, $plural = null) { $this->normalization()->remap($singular, $plural); return $this; } /** * Sets the attribute which value is to be used as key. * * This is useful when you have an indexed array that should be an * associative array. You can select an item from within the array * to be the key of the particular item. For example, if "id" is the * "key", then: * * array( * array('id' => 'my_name', 'foo' => 'bar'), * ); * * becomes * * array( * 'my_name' => array('foo' => 'bar'), * ); * * If you'd like "'id' => 'my_name'" to still be present in the resulting * array, then you can set the second argument of this method to false. * * This method is applicable to prototype nodes only. * * @param string $name The name of the key * @param bool $removeKeyItem Whether or not the key item should be removed. * * @return ArrayNodeDefinition */ public function useAttributeAsKey($name, $removeKeyItem = true) { $this->key = $name; $this->removeKeyItem = $removeKeyItem; return $this; } /** * Sets whether the node can be unset. * * @param bool $allow * * @return ArrayNodeDefinition */ public function canBeUnset($allow = true) { $this->merge()->allowUnset($allow); return $this; } /** * Adds an "enabled" boolean to enable the current section. * * By default, the section is disabled. If any configuration is specified then * the node will be automatically enabled: * * enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden * enableableArrayNode: ~ # The config is enabled & use the default values * enableableArrayNode: true # The config is enabled & use the default values * enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden * enableableArrayNode: {enabled: false, ...} # The config is disabled * enableableArrayNode: false # The config is disabled * * @return ArrayNodeDefinition */ public function canBeEnabled() { $this ->addDefaultsIfNotSet() ->treatFalseLike(array('enabled' => false)) ->treatTrueLike(array('enabled' => true)) ->treatNullLike(array('enabled' => true)) ->beforeNormalization() ->ifArray() ->then(function ($v) { $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true; return $v; }) ->end() ->children() ->booleanNode('enabled') ->defaultFalse() ; return $this; } /** * Adds an "enabled" boolean to enable the current section. * * By default, the section is enabled. * * @return ArrayNodeDefinition */ public function canBeDisabled() { $this ->addDefaultsIfNotSet() ->treatFalseLike(array('enabled' => false)) ->treatTrueLike(array('enabled' => true)) ->treatNullLike(array('enabled' => true)) ->children() ->booleanNode('enabled') ->defaultTrue() ; return $this; } /** * Disables the deep merging of the node. * * @return ArrayNodeDefinition */ public function performNoDeepMerging() { $this->performDeepMerging = false; return $this; } /** * Allows extra config keys to be specified under an array without * throwing an exception. * * Those config values are simply ignored and removed from the * resulting array. This should be used only in special cases where * you want to send an entire configuration array through a special * tree that processes only part of the array. * * @return ArrayNodeDefinition */ public function ignoreExtraKeys() { $this->ignoreExtraKeys = true; return $this; } /** * Sets key normalization. * * @param bool $bool Whether to enable key normalization * * @return ArrayNodeDefinition */ public function normalizeKeys($bool) { $this->normalizeKeys = (bool) $bool; return $this; } /** * Appends a node definition. * * $node = new ArrayNodeDefinition() * ->children() * ->scalarNode('foo')->end() * ->scalarNode('baz')->end() * ->end() * ->append($this->getBarNodeDefinition()) * ; * * @param NodeDefinition $node A NodeDefinition instance * * @return ArrayNodeDefinition This node */ public function append(NodeDefinition $node) { $this->children[$node->name] = $node->setParent($this); return $this; } /** * Returns a node builder to be used to add children and prototype. * * @return NodeBuilder The node builder */ protected function getNodeBuilder() { if (null === $this->nodeBuilder) { $this->nodeBuilder = new NodeBuilder(); } return $this->nodeBuilder->setParent($this); } /** * {@inheritdoc} */ protected function createNode() { if (null === $this->prototype) { $node = new ArrayNode($this->name, $this->parent); $this->validateConcreteNode($node); $node->setAddIfNotSet($this->addDefaults); foreach ($this->children as $child) { $child->parent = $node; $node->addChild($child->getNode()); } } else { $node = new PrototypedArrayNode($this->name, $this->parent); $this->validatePrototypeNode($node); if (null !== $this->key) { $node->setKeyAttribute($this->key, $this->removeKeyItem); } if (true === $this->atLeastOne) { $node->setMinNumberOfElements(1); } if ($this->default) { $node->setDefaultValue($this->defaultValue); } if (false !== $this->addDefaultChildren) { $node->setAddChildrenIfNoneSet($this->addDefaultChildren); if ($this->prototype instanceof static && null === $this->prototype->prototype) { $this->prototype->addDefaultsIfNotSet(); } } $this->prototype->parent = $node; $node->setPrototype($this->prototype->getNode()); } $node->setAllowNewKeys($this->allowNewKeys); $node->addEquivalentValue(null, $this->nullEquivalent); $node->addEquivalentValue(true, $this->trueEquivalent); $node->addEquivalentValue(false, $this->falseEquivalent); $node->setPerformDeepMerging($this->performDeepMerging); $node->setRequired($this->required); $node->setIgnoreExtraKeys($this->ignoreExtraKeys); $node->setNormalizeKeys($this->normalizeKeys); if (null !== $this->normalization) { $node->setNormalizationClosures($this->normalization->before); $node->setXmlRemappings($this->normalization->remappings); } if (null !== $this->merge) { $node->setAllowOverwrite($this->merge->allowOverwrite); $node->setAllowFalse($this->merge->allowFalse); } if (null !== $this->validation) { $node->setFinalValidationClosures($this->validation->rules); } return $node; } /** * Validate the configuration of a concrete node. * * @param ArrayNode $node The related node * * @throws InvalidDefinitionException */ protected function validateConcreteNode(ArrayNode $node) { $path = $node->getPath(); if (null !== $this->key) { throw new InvalidDefinitionException( sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path) ); } if (true === $this->atLeastOne) { throw new InvalidDefinitionException( sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path) ); } if ($this->default) { throw new InvalidDefinitionException( sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path) ); } if (false !== $this->addDefaultChildren) { throw new InvalidDefinitionException( sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path) ); } } /** * Validate the configuration of a prototype node. * * @param PrototypedArrayNode $node The related node * * @throws InvalidDefinitionException */ protected function validatePrototypeNode(PrototypedArrayNode $node) { $path = $node->getPath(); if ($this->addDefaults) { throw new InvalidDefinitionException( sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path) ); } if (false !== $this->addDefaultChildren) { if ($this->default) { throw new InvalidDefinitionException( sprintf('A default value and default children might not be used together at path "%s"', $path) ); } if (null !== $this->key && (null === $this->addDefaultChildren || is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) { throw new InvalidDefinitionException( sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path) ); } if (null === $this->key && (is_string($this->addDefaultChildren) || is_array($this->addDefaultChildren))) { throw new InvalidDefinitionException( sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path) ); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class builds merge conditions. * * @author Johannes M. Schmitt */ class MergeBuilder { protected $node; public $allowFalse = false; public $allowOverwrite = true; /** * Constructor. * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Sets whether the node can be unset. * * @param bool $allow * * @return MergeBuilder */ public function allowUnset($allow = true) { $this->allowFalse = $allow; return $this; } /** * Sets whether the node can be overwritten. * * @param bool $deny Whether the overwriting is forbidden or not * * @return MergeBuilder */ public function denyOverwrite($deny = true) { $this->allowOverwrite = !$deny; return $this; } /** * Returns the related node. * * @return NodeDefinition */ public function end() { return $this->node; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\VariableNode; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ class VariableNodeDefinition extends NodeDefinition { /** * Instantiate a Node. * * @return VariableNode The node */ protected function instantiateNode() { return new VariableNode($this->name, $this->parent); } /** * {@inheritdoc} */ protected function createNode() { $node = $this->instantiateNode(); if (null !== $this->normalization) { $node->setNormalizationClosures($this->normalization->before); } if (null !== $this->merge) { $node->setAllowOverwrite($this->merge->allowOverwrite); } if (true === $this->default) { $node->setDefaultValue($this->defaultValue); } $node->setAllowEmptyValue($this->allowEmptyValue); $node->addEquivalentValue(null, $this->nullEquivalent); $node->addEquivalentValue(true, $this->trueEquivalent); $node->addEquivalentValue(false, $this->falseEquivalent); $node->setRequired($this->required); if (null !== $this->validation) { $node->setFinalValidationClosures($this->validation->rules); } return $node; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\ScalarNode; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ class ScalarNodeDefinition extends VariableNodeDefinition { /** * Instantiate a Node. * * @return ScalarNode The node */ protected function instantiateNode() { return new ScalarNode($this->name, $this->parent); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; /** * This class provides a fluent interface for defining a node. * * @author Johannes M. Schmitt */ abstract class NodeDefinition implements NodeParentInterface { protected $name; protected $normalization; protected $validation; protected $defaultValue; protected $default = false; protected $required = false; protected $merge; protected $allowEmptyValue = true; protected $nullEquivalent; protected $trueEquivalent = true; protected $falseEquivalent = false; /** * @var NodeParentInterface|null */ protected $parent; protected $attributes = array(); /** * Constructor. * * @param string $name The name of the node * @param NodeParentInterface|null $parent The parent */ public function __construct($name, NodeParentInterface $parent = null) { $this->parent = $parent; $this->name = $name; } /** * Sets the parent node. * * @param NodeParentInterface $parent The parent * * @return NodeDefinition|$this */ public function setParent(NodeParentInterface $parent) { $this->parent = $parent; return $this; } /** * Sets info message. * * @param string $info The info text * * @return NodeDefinition|$this */ public function info($info) { return $this->attribute('info', $info); } /** * Sets example configuration. * * @param string|array $example * * @return NodeDefinition|$this */ public function example($example) { return $this->attribute('example', $example); } /** * Sets an attribute on the node. * * @param string $key * @param mixed $value * * @return NodeDefinition|$this */ public function attribute($key, $value) { $this->attributes[$key] = $value; return $this; } /** * Returns the parent node. * * @return NodeParentInterface|null The builder of the parent node */ public function end() { return $this->parent; } /** * Creates the node. * * @param bool $forceRootNode Whether to force this node as the root node * * @return NodeInterface */ public function getNode($forceRootNode = false) { if ($forceRootNode) { $this->parent = null; } if (null !== $this->normalization) { $this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before); } if (null !== $this->validation) { $this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules); } $node = $this->createNode(); $node->setAttributes($this->attributes); return $node; } /** * Sets the default value. * * @param mixed $value The default value * * @return NodeDefinition|$this */ public function defaultValue($value) { $this->default = true; $this->defaultValue = $value; return $this; } /** * Sets the node as required. * * @return NodeDefinition|$this */ public function isRequired() { $this->required = true; return $this; } /** * Sets the equivalent value used when the node contains null. * * @param mixed $value * * @return NodeDefinition|$this */ public function treatNullLike($value) { $this->nullEquivalent = $value; return $this; } /** * Sets the equivalent value used when the node contains true. * * @param mixed $value * * @return NodeDefinition|$this */ public function treatTrueLike($value) { $this->trueEquivalent = $value; return $this; } /** * Sets the equivalent value used when the node contains false. * * @param mixed $value * * @return NodeDefinition|$this */ public function treatFalseLike($value) { $this->falseEquivalent = $value; return $this; } /** * Sets null as the default value. * * @return NodeDefinition|$this */ public function defaultNull() { return $this->defaultValue(null); } /** * Sets true as the default value. * * @return NodeDefinition|$this */ public function defaultTrue() { return $this->defaultValue(true); } /** * Sets false as the default value. * * @return NodeDefinition|$this */ public function defaultFalse() { return $this->defaultValue(false); } /** * Sets an expression to run before the normalization. * * @return ExprBuilder */ public function beforeNormalization() { return $this->normalization()->before(); } /** * Denies the node value being empty. * * @return NodeDefinition|$this */ public function cannotBeEmpty() { $this->allowEmptyValue = false; return $this; } /** * Sets an expression to run for the validation. * * The expression receives the value of the node and must return it. It can * modify it. * An exception should be thrown when the node is not valid. * * @return ExprBuilder */ public function validate() { return $this->validation()->rule(); } /** * Sets whether the node can be overwritten. * * @param bool $deny Whether the overwriting is forbidden or not * * @return NodeDefinition|$this */ public function cannotBeOverwritten($deny = true) { $this->merge()->denyOverwrite($deny); return $this; } /** * Gets the builder for validation rules. * * @return ValidationBuilder */ protected function validation() { if (null === $this->validation) { $this->validation = new ValidationBuilder($this); } return $this->validation; } /** * Gets the builder for merging rules. * * @return MergeBuilder */ protected function merge() { if (null === $this->merge) { $this->merge = new MergeBuilder($this); } return $this->merge; } /** * Gets the builder for normalization rules. * * @return NormalizationBuilder */ protected function normalization() { if (null === $this->normalization) { $this->normalization = new NormalizationBuilder($this); } return $this->normalization; } /** * Instantiate and configure the node according to this definition. * * @return NodeInterface $node The node instance * * @throws InvalidDefinitionException When the definition is invalid */ abstract protected function createNode(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * An interface that must be implemented by nodes which can have children. * * @author Victor Berchet */ interface ParentNodeDefinitionInterface { public function children(); public function append(NodeDefinition $node); public function setBuilder(NodeBuilder $builder); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * This class provides a fluent interface for building a node. * * @author Johannes M. Schmitt */ class NodeBuilder implements NodeParentInterface { protected $parent; protected $nodeMapping; /** * Constructor. */ public function __construct() { $this->nodeMapping = array( 'variable' => __NAMESPACE__.'\\VariableNodeDefinition', 'scalar' => __NAMESPACE__.'\\ScalarNodeDefinition', 'boolean' => __NAMESPACE__.'\\BooleanNodeDefinition', 'integer' => __NAMESPACE__.'\\IntegerNodeDefinition', 'float' => __NAMESPACE__.'\\FloatNodeDefinition', 'array' => __NAMESPACE__.'\\ArrayNodeDefinition', 'enum' => __NAMESPACE__.'\\EnumNodeDefinition', ); } /** * Set the parent node. * * @param ParentNodeDefinitionInterface $parent The parent node * * @return NodeBuilder This node builder */ public function setParent(ParentNodeDefinitionInterface $parent = null) { $this->parent = $parent; return $this; } /** * Creates a child array node. * * @param string $name The name of the node * * @return ArrayNodeDefinition The child node */ public function arrayNode($name) { return $this->node($name, 'array'); } /** * Creates a child scalar node. * * @param string $name the name of the node * * @return ScalarNodeDefinition The child node */ public function scalarNode($name) { return $this->node($name, 'scalar'); } /** * Creates a child Boolean node. * * @param string $name The name of the node * * @return BooleanNodeDefinition The child node */ public function booleanNode($name) { return $this->node($name, 'boolean'); } /** * Creates a child integer node. * * @param string $name the name of the node * * @return IntegerNodeDefinition The child node */ public function integerNode($name) { return $this->node($name, 'integer'); } /** * Creates a child float node. * * @param string $name the name of the node * * @return FloatNodeDefinition The child node */ public function floatNode($name) { return $this->node($name, 'float'); } /** * Creates a child EnumNode. * * @param string $name * * @return EnumNodeDefinition */ public function enumNode($name) { return $this->node($name, 'enum'); } /** * Creates a child variable node. * * @param string $name The name of the node * * @return VariableNodeDefinition The builder of the child node */ public function variableNode($name) { return $this->node($name, 'variable'); } /** * Returns the parent node. * * @return ParentNodeDefinitionInterface The parent node */ public function end() { return $this->parent; } /** * Creates a child node. * * @param string $name The name of the node * @param string $type The type of the node * * @return NodeDefinition The child node * * @throws \RuntimeException When the node type is not registered * @throws \RuntimeException When the node class is not found */ public function node($name, $type) { $class = $this->getNodeClass($type); $node = new $class($name); $this->append($node); return $node; } /** * Appends a node definition. * * Usage: * * $node = new ArrayNodeDefinition('name') * ->children() * ->scalarNode('foo')->end() * ->scalarNode('baz')->end() * ->append($this->getBarNodeDefinition()) * ->end() * ; * * @param NodeDefinition $node * * @return NodeBuilder This node builder */ public function append(NodeDefinition $node) { if ($node instanceof ParentNodeDefinitionInterface) { $builder = clone $this; $builder->setParent(null); $node->setBuilder($builder); } if (null !== $this->parent) { $this->parent->append($node); // Make this builder the node parent to allow for a fluid interface $node->setParent($this); } return $this; } /** * Adds or overrides a node Type. * * @param string $type The name of the type * @param string $class The fully qualified name the node definition class * * @return NodeBuilder This node builder */ public function setNodeClass($type, $class) { $this->nodeMapping[strtolower($type)] = $class; return $this; } /** * Returns the class name of the node definition. * * @param string $type The node type * * @return string The node definition class name * * @throws \RuntimeException When the node type is not registered * @throws \RuntimeException When the node class is not found */ protected function getNodeClass($type) { $type = strtolower($type); if (!isset($this->nodeMapping[$type])) { throw new \RuntimeException(sprintf('The node type "%s" is not registered.', $type)); } $class = $this->nodeMapping[$type]; if (!class_exists($class)) { throw new \RuntimeException(sprintf('The node class "%s" does not exist.', $class)); } return $class; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; use Symfony\Component\Config\Definition\Exception\UnsetKeyException; /** * This class builds an if expression. * * @author Johannes M. Schmitt * @author Christophe Coevoet */ class ExprBuilder { protected $node; public $ifPart; public $thenPart; /** * Constructor. * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) { $this->node = $node; } /** * Marks the expression as being always used. * * @param \Closure $then * * @return ExprBuilder */ public function always(\Closure $then = null) { $this->ifPart = function ($v) { return true; }; if (null !== $then) { $this->thenPart = $then; } return $this; } /** * Sets a closure to use as tests. * * The default one tests if the value is true. * * @param \Closure $closure * * @return ExprBuilder */ public function ifTrue(\Closure $closure = null) { if (null === $closure) { $closure = function ($v) { return true === $v; }; } $this->ifPart = $closure; return $this; } /** * Tests if the value is a string. * * @return ExprBuilder */ public function ifString() { $this->ifPart = function ($v) { return is_string($v); }; return $this; } /** * Tests if the value is null. * * @return ExprBuilder */ public function ifNull() { $this->ifPart = function ($v) { return null === $v; }; return $this; } /** * Tests if the value is an array. * * @return ExprBuilder */ public function ifArray() { $this->ifPart = function ($v) { return is_array($v); }; return $this; } /** * Tests if the value is in an array. * * @param array $array * * @return ExprBuilder */ public function ifInArray(array $array) { $this->ifPart = function ($v) use ($array) { return in_array($v, $array, true); }; return $this; } /** * Tests if the value is not in an array. * * @param array $array * * @return ExprBuilder */ public function ifNotInArray(array $array) { $this->ifPart = function ($v) use ($array) { return !in_array($v, $array, true); }; return $this; } /** * Sets the closure to run if the test pass. * * @param \Closure $closure * * @return ExprBuilder */ public function then(\Closure $closure) { $this->thenPart = $closure; return $this; } /** * Sets a closure returning an empty array. * * @return ExprBuilder */ public function thenEmptyArray() { $this->thenPart = function ($v) { return array(); }; return $this; } /** * Sets a closure marking the value as invalid at validation time. * * if you want to add the value of the node in your message just use a %s placeholder. * * @param string $message * * @return ExprBuilder * * @throws \InvalidArgumentException */ public function thenInvalid($message) { $this->thenPart = function ($v) use ($message) {throw new \InvalidArgumentException(sprintf($message, json_encode($v))); }; return $this; } /** * Sets a closure unsetting this key of the array at validation time. * * @return ExprBuilder * * @throws UnsetKeyException */ public function thenUnset() { $this->thenPart = function ($v) { throw new UnsetKeyException('Unsetting key'); }; return $this; } /** * Returns the related node. * * @return NodeDefinition * * @throws \RuntimeException */ public function end() { if (null === $this->ifPart) { throw new \RuntimeException('You must specify an if part.'); } if (null === $this->thenPart) { throw new \RuntimeException('You must specify a then part.'); } return $this->node; } /** * Builds the expressions. * * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build * * @return array */ public static function buildExpressions(array $expressions) { foreach ($expressions as $k => $expr) { if ($expr instanceof self) { $if = $expr->ifPart; $then = $expr->thenPart; $expressions[$k] = function ($v) use ($if, $then) { return $if($v) ? $then($v) : $v; }; } } return $expressions; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Builder; /** * Abstract class that contains common code of integer and float node definitions. * * @author David Jeanmonod */ abstract class NumericNodeDefinition extends ScalarNodeDefinition { protected $min; protected $max; /** * Ensures that the value is smaller than the given reference. * * @param mixed $max * * @return NumericNodeDefinition * * @throws \InvalidArgumentException when the constraint is inconsistent */ public function max($max) { if (isset($this->min) && $this->min > $max) { throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s)', $max, $this->min)); } $this->max = $max; return $this; } /** * Ensures that the value is bigger than the given reference. * * @param mixed $min * * @return NumericNodeDefinition * * @throws \InvalidArgumentException when the constraint is inconsistent */ public function min($min) { if (isset($this->max) && $this->max < $min) { throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s)', $min, $this->max)); } $this->min = $min; return $this; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Dumper; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\EnumNode; use Symfony\Component\Config\Definition\PrototypedArrayNode; use Symfony\Component\Yaml\Inline; /** * Dumps a Yaml reference configuration for the given configuration/node instance. * * @author Kevin Bond */ class YamlReferenceDumper { private $reference; public function dump(ConfigurationInterface $configuration) { return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree()); } public function dumpNode(NodeInterface $node) { $this->reference = ''; $this->writeNode($node); $ref = $this->reference; $this->reference = null; return $ref; } /** * @param NodeInterface $node * @param int $depth */ private function writeNode(NodeInterface $node, $depth = 0) { $comments = array(); $default = ''; $defaultArray = null; $children = null; $example = $node->getExample(); // defaults if ($node instanceof ArrayNode) { $children = $node->getChildren(); if ($node instanceof PrototypedArrayNode) { $prototype = $node->getPrototype(); if ($prototype instanceof ArrayNode) { $children = $prototype->getChildren(); } // check for attribute as key if ($key = $node->getKeyAttribute()) { $keyNodeClass = 'Symfony\Component\Config\Definition\\'.($prototype instanceof ArrayNode ? 'ArrayNode' : 'ScalarNode'); $keyNode = new $keyNodeClass($key, $node); $keyNode->setInfo('Prototype'); // add children foreach ($children as $childNode) { $keyNode->addChild($childNode); } $children = array($key => $keyNode); } } if (!$children) { if ($node->hasDefaultValue() && count($defaultArray = $node->getDefaultValue())) { $default = ''; } elseif (!is_array($example)) { $default = '[]'; } } } elseif ($node instanceof EnumNode) { $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues())); $default = '~'; } else { $default = '~'; if ($node->hasDefaultValue()) { $default = $node->getDefaultValue(); if (is_array($default)) { if (count($defaultArray = $node->getDefaultValue())) { $default = ''; } elseif (!is_array($example)) { $default = '[]'; } } else { $default = Inline::dump($default); } } } // required? if ($node->isRequired()) { $comments[] = 'Required'; } // example if ($example && !is_array($example)) { $comments[] = 'Example: '.$example; } $default = (string) $default != '' ? ' '.$default : ''; $comments = count($comments) ? '# '.implode(', ', $comments) : ''; $text = rtrim(sprintf('%-20s %s %s', $node->getName().':', $default, $comments), ' '); if ($info = $node->getInfo()) { $this->writeLine(''); // indenting multi-line info $info = str_replace("\n", sprintf("\n%".($depth * 4)."s# ", ' '), $info); $this->writeLine('# '.$info, $depth * 4); } $this->writeLine($text, $depth * 4); // output defaults if ($defaultArray) { $this->writeLine(''); $message = count($defaultArray) > 1 ? 'Defaults' : 'Default'; $this->writeLine('# '.$message.':', $depth * 4 + 4); $this->writeArray($defaultArray, $depth + 1); } if (is_array($example)) { $this->writeLine(''); $message = count($example) > 1 ? 'Examples' : 'Example'; $this->writeLine('# '.$message.':', $depth * 4 + 4); $this->writeArray($example, $depth + 1); } if ($children) { foreach ($children as $childNode) { $this->writeNode($childNode, $depth + 1); } } } /** * Outputs a single config reference line * * @param string $text * @param int $indent */ private function writeLine($text, $indent = 0) { $indent = strlen($text) + $indent; $format = '%'.$indent.'s'; $this->reference .= sprintf($format, $text)."\n"; } private function writeArray(array $array, $depth) { $isIndexed = array_values($array) === $array; foreach ($array as $key => $value) { if (is_array($value)) { $val = ''; } else { $val = $value; } if ($isIndexed) { $this->writeLine('- '.$val, $depth * 4); } else { $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4); } if (is_array($value)) { $this->writeArray($value, $depth + 1); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Dumper; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\EnumNode; use Symfony\Component\Config\Definition\PrototypedArrayNode; /** * Dumps a XML reference configuration for the given configuration/node instance. * * @author Wouter J */ class XmlReferenceDumper { private $reference; public function dump(ConfigurationInterface $configuration, $namespace = null) { return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree(), $namespace); } public function dumpNode(NodeInterface $node, $namespace = null) { $this->reference = ''; $this->writeNode($node, 0, true, $namespace); $ref = $this->reference; $this->reference = null; return $ref; } /** * @param NodeInterface $node * @param int $depth * @param bool $root If the node is the root node * @param string $namespace The namespace of the node */ private function writeNode(NodeInterface $node, $depth = 0, $root = false, $namespace = null) { $rootName = ($root ? 'config' : $node->getName()); $rootNamespace = ($namespace ?: ($root ? 'http://example.org/schema/dic/'.$node->getName() : null)); // xml remapping if ($node->getParent()) { $remapping = array_filter($node->getParent()->getXmlRemappings(), function ($mapping) use ($rootName) { return $rootName === $mapping[1]; }); if (count($remapping)) { list($singular) = current($remapping); $rootName = $singular; } } $rootName = str_replace('_', '-', $rootName); $rootAttributes = array(); $rootAttributeComments = array(); $rootChildren = array(); $rootComments = array(); if ($node instanceof ArrayNode) { $children = $node->getChildren(); // comments about the root node if ($rootInfo = $node->getInfo()) { $rootComments[] = $rootInfo; } if ($rootNamespace) { $rootComments[] = 'Namespace: '.$rootNamespace; } // render prototyped nodes if ($node instanceof PrototypedArrayNode) { array_unshift($rootComments, 'prototype'); if ($key = $node->getKeyAttribute()) { $rootAttributes[$key] = str_replace('-', ' ', $rootName).' '.$key; } $prototype = $node->getPrototype(); if ($prototype instanceof ArrayNode) { $children = $prototype->getChildren(); } else { if ($prototype->hasDefaultValue()) { $prototypeValue = $prototype->getDefaultValue(); } else { switch (get_class($prototype)) { case 'Symfony\Component\Config\Definition\ScalarNode': $prototypeValue = 'scalar value'; break; case 'Symfony\Component\Config\Definition\FloatNode': case 'Symfony\Component\Config\Definition\IntegerNode': $prototypeValue = 'numeric value'; break; case 'Symfony\Component\Config\Definition\BooleanNode': $prototypeValue = 'true|false'; break; case 'Symfony\Component\Config\Definition\EnumNode': $prototypeValue = implode('|', array_map('json_encode', $prototype->getValues())); break; default: $prototypeValue = 'value'; } } } } // get attributes and elements foreach ($children as $child) { if (!$child instanceof ArrayNode) { // get attributes // metadata $name = str_replace('_', '-', $child->getName()); $value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world // comments $comments = array(); if ($info = $child->getInfo()) { $comments[] = $info; } if ($example = $child->getExample()) { $comments[] = 'Example: '.$example; } if ($child->isRequired()) { $comments[] = 'Required'; } if ($child instanceof EnumNode) { $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues())); } if (count($comments)) { $rootAttributeComments[$name] = implode(";\n", $comments); } // default values if ($child->hasDefaultValue()) { $value = $child->getDefaultValue(); } // append attribute $rootAttributes[$name] = $value; } else { // get elements $rootChildren[] = $child; } } } // render comments // root node comment if (count($rootComments)) { foreach ($rootComments as $comment) { $this->writeLine('', $depth); } } // attribute comments if (count($rootAttributeComments)) { foreach ($rootAttributeComments as $attrName => $comment) { $commentDepth = $depth + 4 + strlen($attrName) + 2; $commentLines = explode("\n", $comment); $multiline = (count($commentLines) > 1); $comment = implode(PHP_EOL.str_repeat(' ', $commentDepth), $commentLines); if ($multiline) { $this->writeLine('', $depth); } else { $this->writeLine('', $depth); } } } // render start tag + attributes $rootIsVariablePrototype = isset($prototypeValue); $rootIsEmptyTag = (0 === count($rootChildren) && !$rootIsVariablePrototype); $rootOpenTag = '<'.$rootName; if (1 >= ($attributesCount = count($rootAttributes))) { if (1 === $attributesCount) { $rootOpenTag .= sprintf(' %s="%s"', current(array_keys($rootAttributes)), $this->writeValue(current($rootAttributes))); } $rootOpenTag .= $rootIsEmptyTag ? ' />' : '>'; if ($rootIsVariablePrototype) { $rootOpenTag .= $prototypeValue.''; } $this->writeLine($rootOpenTag, $depth); } else { $this->writeLine($rootOpenTag, $depth); $i = 1; foreach ($rootAttributes as $attrName => $attrValue) { $attr = sprintf('%s="%s"', $attrName, $this->writeValue($attrValue)); $this->writeLine($attr, $depth + 4); if ($attributesCount === $i++) { $this->writeLine($rootIsEmptyTag ? '/>' : '>', $depth); if ($rootIsVariablePrototype) { $rootOpenTag .= $prototypeValue.''; } } } } // render children tags foreach ($rootChildren as $child) { $this->writeLine(''); $this->writeNode($child, $depth + 4); } // render end tag if (!$rootIsEmptyTag && !$rootIsVariablePrototype) { $this->writeLine(''); $rootEndTag = ''; $this->writeLine($rootEndTag, $depth); } } /** * Outputs a single config reference line * * @param string $text * @param int $indent */ private function writeLine($text, $indent = 0) { $indent = strlen($text) + $indent; $format = '%'.$indent.'s'; $this->reference .= sprintf($format, $text)."\n"; } /** * Renders the string conversion of the value. * * @param mixed $value * * @return string */ private function writeValue($value) { if ('%%%%not_defined%%%%' === $value) { return ''; } if (is_string($value) || is_numeric($value)) { return $value; } if (false === $value) { return 'false'; } if (true === $value) { return 'true'; } if (null === $value) { return 'null'; } if (empty($value)) { return ''; } if (is_array($value)) { return implode(',', $value); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; use Symfony\Component\Config\Definition\Exception\UnsetKeyException; /** * Represents an Array node in the config tree. * * @author Johannes M. Schmitt */ class ArrayNode extends BaseNode implements PrototypeNodeInterface { protected $xmlRemappings = array(); protected $children = array(); protected $allowFalse = false; protected $allowNewKeys = true; protected $addIfNotSet = false; protected $performDeepMerging = true; protected $ignoreExtraKeys = false; protected $normalizeKeys = true; public function setNormalizeKeys($normalizeKeys) { $this->normalizeKeys = (bool) $normalizeKeys; } /** * Normalizes keys between the different configuration formats. * * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML. * After running this method, all keys are normalized to foo_bar. * * If you have a mixed key like foo-bar_moo, it will not be altered. * The key will also not be altered if the target key already exists. * * @param mixed $value * * @return array The value with normalized keys */ protected function preNormalize($value) { if (!$this->normalizeKeys || !is_array($value)) { return $value; } foreach ($value as $k => $v) { if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) { $value[$normalizedKey] = $v; unset($value[$k]); } } return $value; } /** * Retrieves the children of this node. * * @return array The children */ public function getChildren() { return $this->children; } /** * Sets the xml remappings that should be performed. * * @param array $remappings an array of the form array(array(string, string)) */ public function setXmlRemappings(array $remappings) { $this->xmlRemappings = $remappings; } /** * Gets the xml remappings that should be performed. * * @return array $remappings an array of the form array(array(string, string)) */ public function getXmlRemappings() { return $this->xmlRemappings; } /** * Sets whether to add default values for this array if it has not been * defined in any of the configuration files. * * @param bool $boolean */ public function setAddIfNotSet($boolean) { $this->addIfNotSet = (bool) $boolean; } /** * Sets whether false is allowed as value indicating that the array should be unset. * * @param bool $allow */ public function setAllowFalse($allow) { $this->allowFalse = (bool) $allow; } /** * Sets whether new keys can be defined in subsequent configurations. * * @param bool $allow */ public function setAllowNewKeys($allow) { $this->allowNewKeys = (bool) $allow; } /** * Sets if deep merging should occur. * * @param bool $boolean */ public function setPerformDeepMerging($boolean) { $this->performDeepMerging = (bool) $boolean; } /** * Whether extra keys should just be ignore without an exception. * * @param bool $boolean To allow extra keys */ public function setIgnoreExtraKeys($boolean) { $this->ignoreExtraKeys = (bool) $boolean; } /** * Sets the node Name. * * @param string $name The node's name */ public function setName($name) { $this->name = $name; } /** * Checks if the node has a default value. * * @return bool */ public function hasDefaultValue() { return $this->addIfNotSet; } /** * Retrieves the default value. * * @return array The default value * * @throws \RuntimeException if the node has no default value */ public function getDefaultValue() { if (!$this->hasDefaultValue()) { throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath())); } $defaults = array(); foreach ($this->children as $name => $child) { if ($child->hasDefaultValue()) { $defaults[$name] = $child->getDefaultValue(); } } return $defaults; } /** * Adds a child node. * * @param NodeInterface $node The child node to add * * @throws \InvalidArgumentException when the child node has no name * @throws \InvalidArgumentException when the child node's name is not unique */ public function addChild(NodeInterface $node) { $name = $node->getName(); if (!strlen($name)) { throw new \InvalidArgumentException('Child nodes must be named.'); } if (isset($this->children[$name])) { throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name)); } $this->children[$name] = $node; } /** * Finalizes the value of this node. * * @param mixed $value * * @return mixed The finalised value * * @throws UnsetKeyException * @throws InvalidConfigurationException if the node doesn't have enough children */ protected function finalizeValue($value) { if (false === $value) { $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value)); throw new UnsetKeyException($msg); } foreach ($this->children as $name => $child) { if (!array_key_exists($name, $value)) { if ($child->isRequired()) { $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath()); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } if ($child->hasDefaultValue()) { $value[$name] = $child->getDefaultValue(); } continue; } try { $value[$name] = $child->finalize($value[$name]); } catch (UnsetKeyException $e) { unset($value[$name]); } } return $value; } /** * Validates the type of the value. * * @param mixed $value * * @throws InvalidTypeException */ protected function validateType($value) { if (!is_array($value) && (!$this->allowFalse || false !== $value)) { $ex = new InvalidTypeException(sprintf( 'Invalid type for path "%s". Expected array, but got %s', $this->getPath(), gettype($value) )); if ($hint = $this->getInfo()) { $ex->addHint($hint); } $ex->setPath($this->getPath()); throw $ex; } } /** * Normalizes the value. * * @param mixed $value The value to normalize * * @return mixed The normalized value * * @throws InvalidConfigurationException */ protected function normalizeValue($value) { if (false === $value) { return $value; } $value = $this->remapXml($value); $normalized = array(); foreach ($value as $name => $val) { if (isset($this->children[$name])) { $normalized[$name] = $this->children[$name]->normalize($val); unset($value[$name]); } } // if extra fields are present, throw exception if (count($value) && !$this->ignoreExtraKeys) { $msg = sprintf('Unrecognized option%s "%s" under "%s"', 1 === count($value) ? '' : 's', implode(', ', array_keys($value)), $this->getPath()); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } return $normalized; } /** * Remaps multiple singular values to a single plural value. * * @param array $value The source values * * @return array The remapped values */ protected function remapXml($value) { foreach ($this->xmlRemappings as $transformation) { list($singular, $plural) = $transformation; if (!isset($value[$singular])) { continue; } $value[$plural] = Processor::normalizeConfig($value, $singular, $plural); unset($value[$singular]); } return $value; } /** * Merges values together. * * @param mixed $leftSide The left side to merge. * @param mixed $rightSide The right side to merge. * * @return mixed The merged values * * @throws InvalidConfigurationException * @throws \RuntimeException */ protected function mergeValues($leftSide, $rightSide) { if (false === $rightSide) { // if this is still false after the last config has been merged the // finalization pass will take care of removing this key entirely return false; } if (false === $leftSide || !$this->performDeepMerging) { return $rightSide; } foreach ($rightSide as $k => $v) { // no conflict if (!array_key_exists($k, $leftSide)) { if (!$this->allowNewKeys) { $ex = new InvalidConfigurationException(sprintf( 'You are not allowed to define new elements for path "%s". ' .'Please define all elements for this path in one config file. ' .'If you are trying to overwrite an element, make sure you redefine it ' .'with the same name.', $this->getPath() )); $ex->setPath($this->getPath()); throw $ex; } $leftSide[$k] = $v; continue; } if (!isset($this->children[$k])) { throw new \RuntimeException('merge() expects a normalized config array.'); } $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v); } return $leftSide; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents a Boolean value in the config tree. * * @author Johannes M. Schmitt */ class BooleanNode extends ScalarNode { /** * {@inheritdoc} */ protected function validateType($value) { if (!is_bool($value)) { $ex = new InvalidTypeException(sprintf( 'Invalid type for path "%s". Expected boolean, but got %s.', $this->getPath(), gettype($value) )); if ($hint = $this->getInfo()) { $ex->addHint($hint); } $ex->setPath($this->getPath()); throw $ex; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * Base exception for all configuration exceptions. * * @author Johannes M. Schmitt */ class Exception extends \RuntimeException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is thrown whenever the key of an array is not unique. This can * only be the case if the configuration is coming from an XML file. * * @author Johannes M. Schmitt */ class DuplicateKeyException extends InvalidConfigurationException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * Thrown when an error is detected in a node Definition. * * @author Victor Berchet */ class InvalidDefinitionException extends Exception { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * A very general exception which can be thrown whenever non of the more specific * exceptions is suitable. * * @author Johannes M. Schmitt */ class InvalidConfigurationException extends Exception { private $path; private $containsHints = false; public function setPath($path) { $this->path = $path; } public function getPath() { return $this->path; } /** * Adds extra information that is suffixed to the original exception message. * * @param string $hint */ public function addHint($hint) { if (!$this->containsHints) { $this->message .= "\nHint: ".$hint; $this->containsHints = true; } else { $this->message .= ', '.$hint; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is usually not encountered by the end-user, but only used * internally to signal the parent scope to unset a key. * * @author Johannes M. Schmitt */ class UnsetKeyException extends Exception { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is thrown when a configuration path is overwritten from a * subsequent configuration file, but the entry node specifically forbids this. * * @author Johannes M. Schmitt */ class ForbiddenOverwriteException extends InvalidConfigurationException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition\Exception; /** * This exception is thrown if an invalid type is encountered. * * @author Johannes M. Schmitt */ class InvalidTypeException extends InvalidConfigurationException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidTypeException; /** * This node represents a scalar value in the config tree. * * The following values are considered scalars: * * booleans * * strings * * null * * integers * * floats * * @author Johannes M. Schmitt */ class ScalarNode extends VariableNode { /** * {@inheritdoc} */ protected function validateType($value) { if (!is_scalar($value) && null !== $value) { $ex = new InvalidTypeException(sprintf( 'Invalid type for path "%s". Expected scalar, but got %s.', $this->getPath(), gettype($value) )); if ($hint = $this->getInfo()) { $ex->addHint($hint); } $ex->setPath($this->getPath()); throw $ex; } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Exception\DuplicateKeyException; use Symfony\Component\Config\Definition\Exception\UnsetKeyException; use Symfony\Component\Config\Definition\Exception\Exception; /** * Represents a prototyped Array node in the config tree. * * @author Johannes M. Schmitt */ class PrototypedArrayNode extends ArrayNode { protected $prototype; protected $keyAttribute; protected $removeKeyAttribute = false; protected $minNumberOfElements = 0; protected $defaultValue = array(); protected $defaultChildren; /** * Sets the minimum number of elements that a prototype based node must * contain. By default this is zero, meaning no elements. * * @param int $number */ public function setMinNumberOfElements($number) { $this->minNumberOfElements = $number; } /** * Sets the attribute which value is to be used as key. * * This is useful when you have an indexed array that should be an * associative array. You can select an item from within the array * to be the key of the particular item. For example, if "id" is the * "key", then: * * array( * array('id' => 'my_name', 'foo' => 'bar'), * ); * * becomes * * array( * 'my_name' => array('foo' => 'bar'), * ); * * If you'd like "'id' => 'my_name'" to still be present in the resulting * array, then you can set the second argument of this method to false. * * @param string $attribute The name of the attribute which value is to be used as a key * @param bool $remove Whether or not to remove the key */ public function setKeyAttribute($attribute, $remove = true) { $this->keyAttribute = $attribute; $this->removeKeyAttribute = $remove; } /** * Retrieves the name of the attribute which value should be used as key. * * @return string The name of the attribute */ public function getKeyAttribute() { return $this->keyAttribute; } /** * Sets the default value of this node. * * @param string $value * * @throws \InvalidArgumentException if the default value is not an array */ public function setDefaultValue($value) { if (!is_array($value)) { throw new \InvalidArgumentException($this->getPath().': the default value of an array node has to be an array.'); } $this->defaultValue = $value; } /** * Checks if the node has a default value. * * @return bool */ public function hasDefaultValue() { return true; } /** * Adds default children when none are set. * * @param int|string|array|null $children The number of children|The child name|The children names to be added */ public function setAddChildrenIfNoneSet($children = array('defaults')) { if (null === $children) { $this->defaultChildren = array('defaults'); } else { $this->defaultChildren = is_int($children) && $children > 0 ? range(1, $children) : (array) $children; } } /** * Retrieves the default value. * * The default value could be either explicited or derived from the prototype * default value. * * @return array The default value */ public function getDefaultValue() { if (null !== $this->defaultChildren) { $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : array(); $defaults = array(); foreach (array_values($this->defaultChildren) as $i => $name) { $defaults[null === $this->keyAttribute ? $i : $name] = $default; } return $defaults; } return $this->defaultValue; } /** * Sets the node prototype. * * @param PrototypeNodeInterface $node */ public function setPrototype(PrototypeNodeInterface $node) { $this->prototype = $node; } /** * Retrieves the prototype. * * @return PrototypeNodeInterface The prototype */ public function getPrototype() { return $this->prototype; } /** * Disable adding concrete children for prototyped nodes. * * @param NodeInterface $node The child node to add * * @throws Exception */ public function addChild(NodeInterface $node) { throw new Exception('A prototyped array node can not have concrete children.'); } /** * Finalizes the value of this node. * * @param mixed $value * * @return mixed The finalized value * * @throws UnsetKeyException * @throws InvalidConfigurationException if the node doesn't have enough children */ protected function finalizeValue($value) { if (false === $value) { $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value)); throw new UnsetKeyException($msg); } foreach ($value as $k => $v) { $this->prototype->setName($k); try { $value[$k] = $this->prototype->finalize($v); } catch (UnsetKeyException $e) { unset($value[$k]); } } if (count($value) < $this->minNumberOfElements) { $msg = sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } return $value; } /** * Normalizes the value. * * @param mixed $value The value to normalize * * @return mixed The normalized value * * @throws InvalidConfigurationException * @throws DuplicateKeyException */ protected function normalizeValue($value) { if (false === $value) { return $value; } $value = $this->remapXml($value); $isAssoc = array_keys($value) !== range(0, count($value) - 1); $normalized = array(); foreach ($value as $k => $v) { if (null !== $this->keyAttribute && is_array($v)) { if (!isset($v[$this->keyAttribute]) && is_int($k) && !$isAssoc) { $msg = sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath()); $ex = new InvalidConfigurationException($msg); $ex->setPath($this->getPath()); throw $ex; } elseif (isset($v[$this->keyAttribute])) { $k = $v[$this->keyAttribute]; // remove the key attribute when required if ($this->removeKeyAttribute) { unset($v[$this->keyAttribute]); } // if only "value" is left if (1 == count($v) && isset($v['value'])) { $v = $v['value']; } } if (array_key_exists($k, $normalized)) { $msg = sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath()); $ex = new DuplicateKeyException($msg); $ex->setPath($this->getPath()); throw $ex; } } $this->prototype->setName($k); if (null !== $this->keyAttribute || $isAssoc) { $normalized[$k] = $this->prototype->normalize($v); } else { $normalized[] = $this->prototype->normalize($v); } } return $normalized; } /** * Merges values together. * * @param mixed $leftSide The left side to merge. * @param mixed $rightSide The right side to merge. * * @return mixed The merged values * * @throws InvalidConfigurationException * @throws \RuntimeException */ protected function mergeValues($leftSide, $rightSide) { if (false === $rightSide) { // if this is still false after the last config has been merged the // finalization pass will take care of removing this key entirely return false; } if (false === $leftSide || !$this->performDeepMerging) { return $rightSide; } foreach ($rightSide as $k => $v) { // prototype, and key is irrelevant, so simply append the element if (null === $this->keyAttribute) { $leftSide[] = $v; continue; } // no conflict if (!array_key_exists($k, $leftSide)) { if (!$this->allowNewKeys) { $ex = new InvalidConfigurationException(sprintf( 'You are not allowed to define new elements for path "%s". '. 'Please define all elements for this path in one config file.', $this->getPath() )); $ex->setPath($this->getPath()); throw $ex; } $leftSide[$k] = $v; continue; } $this->prototype->setName($k); $leftSide[$k] = $this->prototype->merge($leftSide[$k], $v); } return $leftSide; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * This interface must be implemented by nodes which can be used as prototypes. * * @author Johannes M. Schmitt */ interface PrototypeNodeInterface extends NodeInterface { /** * Sets the name of the node. * * @param string $name The name of the node */ public function setName($name); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * Configuration interface. * * @author Victor Berchet */ interface ConfigurationInterface { /** * Generates the configuration tree builder. * * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder */ public function getConfigTreeBuilder(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Definition; /** * Common Interface among all nodes. * * In most cases, it is better to inherit from BaseNode instead of implementing * this interface yourself. * * @author Johannes M. Schmitt */ interface NodeInterface { /** * Returns the name of the node. * * @return string The name of the node */ public function getName(); /** * Returns the path of the node. * * @return string The node path */ public function getPath(); /** * Returns true when the node is required. * * @return bool If the node is required */ public function isRequired(); /** * Returns true when the node has a default value. * * @return bool If the node has a default value */ public function hasDefaultValue(); /** * Returns the default value of the node. * * @return mixed The default value * * @throws \RuntimeException if the node has no default value */ public function getDefaultValue(); /** * Normalizes the supplied value. * * @param mixed $value The value to normalize * * @return mixed The normalized value */ public function normalize($value); /** * Merges two values together. * * @param mixed $leftSide * @param mixed $rightSide * * @return mixed The merged values */ public function merge($leftSide, $rightSide); /** * Finalizes a value. * * @param mixed $value The value to finalize * * @return mixed The finalized value */ public function finalize($value); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Util; /** * XMLUtils is a bunch of utility methods to XML operations. * * This class contains static methods only and is not meant to be instantiated. * * @author Fabien Potencier * @author Martin Hasoň */ class XmlUtils { /** * This class should not be instantiated. */ private function __construct() { } /** * Loads an XML file. * * @param string $file An XML file path * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation * * @return \DOMDocument * * @throws \InvalidArgumentException When loading of XML file returns error */ public static function loadFile($file, $schemaOrCallable = null) { $content = @file_get_contents($file); if ('' === trim($content)) { throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file)); } $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); libxml_clear_errors(); $dom = new \DOMDocument(); $dom->validateOnParse = true; if (!$dom->loadXML($content, LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) { libxml_disable_entity_loader($disableEntities); throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors))); } $dom->normalizeDocument(); libxml_use_internal_errors($internalErrors); libxml_disable_entity_loader($disableEntities); foreach ($dom->childNodes as $child) { if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { throw new \InvalidArgumentException('Document types are not allowed.'); } } if (null !== $schemaOrCallable) { $internalErrors = libxml_use_internal_errors(true); libxml_clear_errors(); $e = null; if (is_callable($schemaOrCallable)) { try { $valid = call_user_func($schemaOrCallable, $dom, $internalErrors); } catch (\Exception $e) { $valid = false; } } elseif (!is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) { $schemaSource = file_get_contents((string) $schemaOrCallable); $valid = @$dom->schemaValidateSource($schemaSource); } else { libxml_use_internal_errors($internalErrors); throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.'); } if (!$valid) { $messages = static::getXmlErrors($internalErrors); if (empty($messages)) { $messages = array(sprintf('The XML file "%s" is not valid.', $file)); } throw new \InvalidArgumentException(implode("\n", $messages), 0, $e); } } libxml_clear_errors(); libxml_use_internal_errors($internalErrors); return $dom; } /** * Converts a \DomElement object to a PHP array. * * The following rules applies during the conversion: * * * Each tag is converted to a key value or an array * if there is more than one "value" * * * The content of a tag is set under a "value" key (bar) * if the tag also has some nested tags * * * The attributes are converted to keys () * * * The nested-tags are converted to keys (bar) * * @param \DomElement $element A \DomElement instance * @param bool $checkPrefix Check prefix in an element or an attribute name * * @return array A PHP array */ public static function convertDomElementToArray(\DomElement $element, $checkPrefix = true) { $prefix = (string) $element->prefix; $empty = true; $config = array(); foreach ($element->attributes as $name => $node) { if ($checkPrefix && !in_array((string) $node->prefix, array('', $prefix), true)) { continue; } $config[$name] = static::phpize($node->value); $empty = false; } $nodeValue = false; foreach ($element->childNodes as $node) { if ($node instanceof \DOMText) { if ('' !== trim($node->nodeValue)) { $nodeValue = trim($node->nodeValue); $empty = false; } } elseif ($checkPrefix && $prefix != (string) $node->prefix) { continue; } elseif (!$node instanceof \DOMComment) { $value = static::convertDomElementToArray($node, $checkPrefix); $key = $node->localName; if (isset($config[$key])) { if (!is_array($config[$key]) || !is_int(key($config[$key]))) { $config[$key] = array($config[$key]); } $config[$key][] = $value; } else { $config[$key] = $value; } $empty = false; } } if (false !== $nodeValue) { $value = static::phpize($nodeValue); if (count($config)) { $config['value'] = $value; } else { $config = $value; } } return !$empty ? $config : null; } /** * Converts an xml value to a PHP type. * * @param mixed $value * * @return mixed */ public static function phpize($value) { $value = (string) $value; $lowercaseValue = strtolower($value); switch (true) { case 'null' === $lowercaseValue: return; case ctype_digit($value): $raw = $value; $cast = (int) $value; return '0' == $value[0] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw); case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)): $raw = $value; $cast = (int) $value; return '0' == $value[1] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw); case 'true' === $lowercaseValue: return true; case 'false' === $lowercaseValue: return false; case isset($value[1]) && '0b' == $value[0].$value[1]: return bindec($value); case is_numeric($value): return '0x' === $value[0].$value[1] ? hexdec($value) : (float) $value; case preg_match('/^0x[0-9a-f]++$/i', $value): return hexdec($value); case preg_match('/^(-|\+)?[0-9]+(\.[0-9]+)?$/', $value): return (float) $value; default: return $value; } } protected static function getXmlErrors($internalErrors) { $errors = array(); foreach (libxml_get_errors() as $error) { $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', $error->code, trim($error->message), $error->file ?: 'n/a', $error->line, $error->column ); } libxml_clear_errors(); libxml_use_internal_errors($internalErrors); return $errors; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config; /** * FileLocator uses an array of pre-defined paths to find files. * * @author Fabien Potencier */ class FileLocator implements FileLocatorInterface { protected $paths; /** * Constructor. * * @param string|array $paths A path or an array of paths where to look for resources */ public function __construct($paths = array()) { $this->paths = (array) $paths; } /** * {@inheritdoc} */ public function locate($name, $currentPath = null, $first = true) { if ('' == $name) { throw new \InvalidArgumentException('An empty file name is not valid to be located.'); } if ($this->isAbsolutePath($name)) { if (!file_exists($name)) { throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $name)); } return $name; } $paths = $this->paths; if (null !== $currentPath) { array_unshift($paths, $currentPath); } $paths = array_unique($paths); $filepaths = array(); foreach ($paths as $path) { if (file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) { if (true === $first) { return $file; } $filepaths[] = $file; } } if (!$filepaths) { throw new \InvalidArgumentException(sprintf('The file "%s" does not exist (in: %s).', $name, implode(', ', $paths))); } return $filepaths; } /** * Returns whether the file path is an absolute path. * * @param string $file A file path * * @return bool */ private function isAbsolutePath($file) { if ($file[0] === '/' || $file[0] === '\\' || (strlen($file) > 3 && ctype_alpha($file[0]) && $file[1] === ':' && ($file[2] === '\\' || $file[2] === '/') ) || null !== parse_url($file, PHP_URL_SCHEME) ) { return true; } return false; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Resource; /** * ResourceInterface is the interface that must be implemented by all Resource classes. * * @author Fabien Potencier */ interface ResourceInterface { /** * Returns a string representation of the Resource. * * @return string A string representation of the Resource */ public function __toString(); /** * Returns true if the resource has not been updated since the given timestamp. * * @param int $timestamp The last time the resource was loaded * * @return bool True if the resource has not been updated, false otherwise */ public function isFresh($timestamp); /** * Returns the tied resource. * * @return mixed The resource */ public function getResource(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Resource; /** * DirectoryResource represents a resources stored in a subdirectory tree. * * @author Fabien Potencier */ class DirectoryResource implements ResourceInterface, \Serializable { private $resource; private $pattern; /** * Constructor. * * @param string $resource The file path to the resource * @param string|null $pattern A pattern to restrict monitored files */ public function __construct($resource, $pattern = null) { $this->resource = $resource; $this->pattern = $pattern; } /** * {@inheritdoc} */ public function __toString() { return (string) $this->resource; } /** * {@inheritdoc} */ public function getResource() { return $this->resource; } /** * Returns the pattern to restrict monitored files. * * @return string|null */ public function getPattern() { return $this->pattern; } /** * {@inheritdoc} */ public function isFresh($timestamp) { if (!is_dir($this->resource)) { return false; } $newestMTime = filemtime($this->resource); foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) { // if regex filtering is enabled only check matching files if ($this->pattern && $file->isFile() && !preg_match($this->pattern, $file->getBasename())) { continue; } // always monitor directories for changes, except the .. entries // (otherwise deleted files wouldn't get detected) if ($file->isDir() && '/..' === substr($file, -3)) { continue; } $newestMTime = max($file->getMTime(), $newestMTime); } return $newestMTime < $timestamp; } public function serialize() { return serialize(array($this->resource, $this->pattern)); } public function unserialize($serialized) { list($this->resource, $this->pattern) = unserialize($serialized); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Resource; /** * FileResource represents a resource stored on the filesystem. * * The resource can be a file or a directory. * * @author Fabien Potencier */ class FileResource implements ResourceInterface, \Serializable { /** * @var string|false */ private $resource; /** * Constructor. * * @param string $resource The file path to the resource */ public function __construct($resource) { $this->resource = realpath($resource); } /** * {@inheritdoc} */ public function __toString() { return (string) $this->resource; } /** * {@inheritdoc} */ public function getResource() { return $this->resource; } /** * {@inheritdoc} */ public function isFresh($timestamp) { if (false === $this->resource || !file_exists($this->resource)) { return false; } return filemtime($this->resource) <= $timestamp; } public function serialize() { return serialize($this->resource); } public function unserialize($serialized) { $this->resource = unserialize($serialized); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Exception; /** * Exception class for when a resource cannot be loaded or imported. * * @author Ryan Weaver */ class FileLoaderLoadException extends \Exception { /** * @param string $resource The resource that could not be imported * @param string $sourceResource The original resource importing the new resource * @param int $code The error code * @param \Exception $previous A previous exception */ public function __construct($resource, $sourceResource = null, $code = null, $previous = null) { $message = ''; if ($previous) { // Include the previous exception, to help the user see what might be the underlying cause // Trim the trailing period of the previous message. We only want 1 period remove so no rtrim... if ('.' === substr($previous->getMessage(), -1)) { $trimmedMessage = substr($previous->getMessage(), 0, -1); $message .= sprintf('%s', $trimmedMessage).' in '; } else { $message .= sprintf('%s', $previous->getMessage()).' in '; } $message .= $resource.' '; // show tweaked trace to complete the human readable sentence if (null === $sourceResource) { $message .= sprintf('(which is loaded in resource "%s")', $this->varToString($resource)); } else { $message .= sprintf('(which is being imported from "%s")', $this->varToString($sourceResource)); } $message .= '.'; // if there's no previous message, present it the default way } elseif (null === $sourceResource) { $message .= sprintf('Cannot load resource "%s".', $this->varToString($resource)); } else { $message .= sprintf('Cannot import resource "%s" from "%s".', $this->varToString($resource), $this->varToString($sourceResource)); } // Is the resource located inside a bundle? if ('@' === $resource[0]) { $parts = explode(DIRECTORY_SEPARATOR, $resource); $bundle = substr($parts[0], 1); $message .= sprintf(' Make sure the "%s" bundle is correctly registered and loaded in the application kernel class.', $bundle); $message .= sprintf(' If the bundle is registered, make sure the bundle path "%s" is not empty.', $resource); } parent::__construct($message, $code, $previous); } protected function varToString($var) { if (is_object($var)) { return sprintf('Object(%s)', get_class($var)); } if (is_array($var)) { $a = array(); foreach ($var as $k => $v) { $a[] = sprintf('%s => %s', $k, $this->varToString($v)); } return sprintf('Array(%s)', implode(', ', $a)); } if (is_resource($var)) { return sprintf('Resource(%s)', get_resource_type($var)); } if (null === $var) { return 'null'; } if (false === $var) { return 'false'; } if (true === $var) { return 'true'; } return (string) $var; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Exception; /** * Exception class for when a circular reference is detected when importing resources. * * @author Fabien Potencier */ class FileLoaderImportCircularReferenceException extends FileLoaderLoadException { public function __construct(array $resources, $code = null, $previous = null) { $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]); \Exception::__construct($message, $code, $previous); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; /** * ConfigCache manages PHP cache files. * * When debug is enabled, it knows when to flush the cache * thanks to an array of ResourceInterface instances. * * @author Fabien Potencier */ class ConfigCache { private $debug; private $file; /** * Constructor. * * @param string $file The absolute cache path * @param bool $debug Whether debugging is enabled or not */ public function __construct($file, $debug) { $this->file = $file; $this->debug = (bool) $debug; } /** * Gets the cache file path. * * @return string The cache file path */ public function __toString() { return $this->file; } /** * Checks if the cache is still fresh. * * This method always returns true when debug is off and the * cache file exists. * * @return bool true if the cache is fresh, false otherwise */ public function isFresh() { if (!is_file($this->file)) { return false; } if (!$this->debug) { return true; } $metadata = $this->getMetaFile(); if (!is_file($metadata)) { return false; } $time = filemtime($this->file); $meta = unserialize(file_get_contents($metadata)); foreach ($meta as $resource) { if (!$resource->isFresh($time)) { return false; } } return true; } /** * Writes cache. * * @param string $content The content to write in the cache * @param ResourceInterface[] $metadata An array of ResourceInterface instances * * @throws \RuntimeException When cache file can't be written */ public function write($content, array $metadata = null) { $mode = 0666; $umask = umask(); $filesystem = new Filesystem(); $filesystem->dumpFile($this->file, $content, null); try { $filesystem->chmod($this->file, $mode, $umask); } catch (IOException $e) { // discard chmod failure (some filesystem may not support it) } if (null !== $metadata && true === $this->debug) { $filesystem->dumpFile($this->getMetaFile(), serialize($metadata), null); try { $filesystem->chmod($this->getMetaFile(), $mode, $umask); } catch (IOException $e) { // discard chmod failure (some filesystem may not support it) } } } /** * Gets the meta file path. * * @return string The meta file path */ private function getMetaFile() { return $this->file.'.meta'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; use Symfony\Component\Config\FileLocatorInterface; use Symfony\Component\Config\Exception\FileLoaderLoadException; use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException; /** * FileLoader is the abstract class used by all built-in loaders that are file based. * * @author Fabien Potencier */ abstract class FileLoader extends Loader { /** * @var array */ protected static $loading = array(); /** * @var FileLocatorInterface */ protected $locator; private $currentDir; /** * Constructor. * * @param FileLocatorInterface $locator A FileLocatorInterface instance */ public function __construct(FileLocatorInterface $locator) { $this->locator = $locator; } /** * Sets the current directory. * * @param string $dir */ public function setCurrentDir($dir) { $this->currentDir = $dir; } /** * Returns the file locator used by this loader. * * @return FileLocatorInterface */ public function getLocator() { return $this->locator; } /** * Imports a resource. * * @param mixed $resource A Resource * @param string|null $type The resource type or null if unknown * @param bool $ignoreErrors Whether to ignore import errors or not * @param string|null $sourceResource The original resource importing the new resource * * @return mixed * * @throws FileLoaderLoadException * @throws FileLoaderImportCircularReferenceException */ public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null) { try { $loader = $this->resolve($resource, $type); if ($loader instanceof self && null !== $this->currentDir) { // we fallback to the current locator to keep BC // as some some loaders do not call the parent __construct() // @deprecated should be removed in 3.0 $locator = $loader->getLocator() ?: $this->locator; $resource = $locator->locate($resource, $this->currentDir, false); } $resources = is_array($resource) ? $resource : array($resource); for ($i = 0; $i < $resourcesCount = count($resources); ++$i) { if (isset(self::$loading[$resources[$i]])) { if ($i == $resourcesCount - 1) { throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading)); } } else { $resource = $resources[$i]; break; } } self::$loading[$resource] = true; try { $ret = $loader->load($resource, $type); } catch (\Exception $e) { unset(self::$loading[$resource]); throw $e; } unset(self::$loading[$resource]); return $ret; } catch (FileLoaderImportCircularReferenceException $e) { throw $e; } catch (\Exception $e) { if (!$ignoreErrors) { // prevent embedded imports from nesting multiple exceptions if ($e instanceof FileLoaderLoadException) { throw $e; } throw new FileLoaderLoadException($resource, $sourceResource, null, $e); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; /** * LoaderInterface is the interface implemented by all loader classes. * * @author Fabien Potencier */ interface LoaderInterface { /** * Loads a resource. * * @param mixed $resource The resource * @param string|null $type The resource type or null if unknown * * @throws \Exception If something went wrong */ public function load($resource, $type = null); /** * Returns whether this class supports the given resource. * * @param mixed $resource A resource * @param string|null $type The resource type or null if unknown * * @return bool True if this class supports the given resource, false otherwise */ public function supports($resource, $type = null); /** * Gets the loader resolver. * * @return LoaderResolverInterface A LoaderResolverInterface instance */ public function getResolver(); /** * Sets the loader resolver. * * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance */ public function setResolver(LoaderResolverInterface $resolver); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; use Symfony\Component\Config\Exception\FileLoaderLoadException; /** * DelegatingLoader delegates loading to other loaders using a loader resolver. * * This loader acts as an array of LoaderInterface objects - each having * a chance to load a given resource (handled by the resolver) * * @author Fabien Potencier */ class DelegatingLoader extends Loader { /** * Constructor. * * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance */ public function __construct(LoaderResolverInterface $resolver) { $this->resolver = $resolver; } /** * {@inheritdoc} */ public function load($resource, $type = null) { if (false === $loader = $this->resolver->resolve($resource, $type)) { throw new FileLoaderLoadException($resource); } return $loader->load($resource, $type); } /** * {@inheritdoc} */ public function supports($resource, $type = null) { return false !== $this->resolver->resolve($resource, $type); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; /** * LoaderResolverInterface selects a loader for a given resource. * * @author Fabien Potencier */ interface LoaderResolverInterface { /** * Returns a loader able to load the resource. * * @param mixed $resource A resource * @param string|null $type The resource type or null if unknown * * @return LoaderInterface|false The loader or false if none is able to load the resource */ public function resolve($resource, $type = null); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; use Symfony\Component\Config\Exception\FileLoaderLoadException; /** * Loader is the abstract class used by all built-in loaders. * * @author Fabien Potencier */ abstract class Loader implements LoaderInterface { protected $resolver; /** * {@inheritdoc} */ public function getResolver() { return $this->resolver; } /** * {@inheritdoc} */ public function setResolver(LoaderResolverInterface $resolver) { $this->resolver = $resolver; } /** * Imports a resource. * * @param mixed $resource A resource * @param string|null $type The resource type or null if unknown * * @return mixed */ public function import($resource, $type = null) { return $this->resolve($resource, $type)->load($resource, $type); } /** * Finds a loader able to load an imported resource. * * @param mixed $resource A resource * @param string|null $type The resource type or null if unknown * * @return LoaderInterface A LoaderInterface instance * * @throws FileLoaderLoadException If no loader is found */ public function resolve($resource, $type = null) { if ($this->supports($resource, $type)) { return $this; } $loader = null === $this->resolver ? false : $this->resolver->resolve($resource, $type); if (false === $loader) { throw new FileLoaderLoadException($resource); } return $loader; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Config\Loader; /** * LoaderResolver selects a loader for a given resource. * * A resource can be anything (e.g. a full path to a config file or a Closure). * Each loader determines whether it can load a resource and how. * * @author Fabien Potencier */ class LoaderResolver implements LoaderResolverInterface { /** * @var LoaderInterface[] An array of LoaderInterface objects */ private $loaders = array(); /** * Constructor. * * @param LoaderInterface[] $loaders An array of loaders */ public function __construct(array $loaders = array()) { foreach ($loaders as $loader) { $this->addLoader($loader); } } /** * {@inheritdoc} */ public function resolve($resource, $type = null) { foreach ($this->loaders as $loader) { if ($loader->supports($resource, $type)) { return $loader; } } return false; } /** * Adds a loader. * * @param LoaderInterface $loader A LoaderInterface instance */ public function addLoader(LoaderInterface $loader) { $this->loaders[] = $loader; $loader->setResolver($this); } /** * Returns the registered loaders. * * @return LoaderInterface[] An array of LoaderInterface instances */ public function getLoaders() { return $this->loaders; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Context; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; /** * Creates new {@link ExecutionContext} instances. * * @since 2.5 * @author Bernhard Schussek * * @internal You should not instantiate or use this class. Code against * {@link ExecutionContextFactoryInterface} instead. */ class ExecutionContextFactory implements ExecutionContextFactoryInterface { /** * @var TranslatorInterface */ private $translator; /** * @var string|null */ private $translationDomain; /** * Creates a new context factory. * * @param TranslatorInterface $translator The translator * @param string|null $translationDomain The translation domain to * use for translating * violation messages */ public function __construct(TranslatorInterface $translator, $translationDomain = null) { $this->translator = $translator; $this->translationDomain = $translationDomain; } /** * {@inheritdoc} */ public function createContext(ValidatorInterface $validator, $root) { return new ExecutionContext( $validator, $root, $this->translator, $this->translationDomain ); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Context; use Symfony\Component\Validator\Validator\ValidatorInterface; /** * Creates instances of {@link ExecutionContextInterface}. * * You can use a custom factory if you want to customize the execution context * that is passed through the validation run. * * @since 2.5 * @author Bernhard Schussek */ interface ExecutionContextFactoryInterface { /** * Creates a new execution context. * * @param ValidatorInterface $validator The validator * @param mixed $root The root value of the validated * object graph * * @return ExecutionContextInterface The new execution context */ public function createContext(ValidatorInterface $validator, $root); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Context; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ExecutionContextInterface as LegacyExecutionContextInterface; use Symfony\Component\Validator\Mapping\MetadataInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface; /** * The context of a validation run. * * The context collects all violations generated during the validation. By * default, validators execute all validations in a new context: * * $violations = $validator->validate($object); * * When you make another call to the validator, while the validation is in * progress, the violations will be isolated from each other: * * public function validate($value, Constraint $constraint) * { * $validator = $this->context->getValidator(); * * // The violations are not added to $this->context * $violations = $validator->validate($value); * } * * However, if you want to add the violations to the current context, use the * {@link ValidatorInterface::inContext()} method: * * public function validate($value, Constraint $constraint) * { * $validator = $this->context->getValidator(); * * // The violations are added to $this->context * $validator * ->inContext($this->context) * ->validate($value) * ; * } * * Additionally, the context provides information about the current state of * the validator, such as the currently validated class, the name of the * currently validated property and more. These values change over time, so you * cannot store a context and expect that the methods still return the same * results later on. * * @since 2.5 * @author Bernhard Schussek */ interface ExecutionContextInterface extends LegacyExecutionContextInterface { /** * Returns a builder for adding a violation with extended information. * * Call {@link ConstraintViolationBuilderInterface::addViolation()} to * add the violation when you're done with the configuration: * * $context->buildViolation('Please enter a number between %min% and %max%.') * ->setParameter('%min%', 3) * ->setParameter('%max%', 10) * ->setTranslationDomain('number_validation') * ->addViolation(); * * @param string $message The error message * @param array $parameters The parameters substituted in the error message * * @return ConstraintViolationBuilderInterface The violation builder */ public function buildViolation($message, array $parameters = array()); /** * Returns the validator. * * Useful if you want to validate additional constraints: * * public function validate($value, Constraint $constraint) * { * $validator = $this->context->getValidator(); * * $violations = $validator->validateValue($value, new Length(array('min' => 3))); * * if (count($violations) > 0) { * // ... * } * } * * @return ValidatorInterface */ public function getValidator(); /** * Returns the currently validated object. * * If the validator is currently validating a class constraint, the * object of that class is returned. If it is a validating a property or * getter constraint, the object that the property/getter belongs to is * returned. * * In other cases, null is returned. * * @return object|null The currently validated object or null. */ public function getObject(); /** * Sets the currently validated value. * * @param mixed $value The validated value * @param object|null $object The currently validated object * @param MetadataInterface|null $metadata The validation metadata * @param string $propertyPath The property path to the current value * * @internal Used by the validator engine. Should not be called by user * code. */ public function setNode($value, $object, MetadataInterface $metadata = null, $propertyPath); /** * Sets the currently validated group. * * @param string|null $group The validated group * * @internal Used by the validator engine. Should not be called by user * code. */ public function setGroup($group); /** * Sets the currently validated constraint. * * @param Constraint $constraint The validated constraint * * @internal Used by the validator engine. Should not be called by user * code. */ public function setConstraint(Constraint $constraint); /** * Marks an object as validated in a specific validation group. * * @param string $cacheKey The hash of the object * @param string $groupHash The group's name or hash, if it is group * sequence * * @internal Used by the validator engine. Should not be called by user * code. */ public function markGroupAsValidated($cacheKey, $groupHash); /** * Returns whether an object was validated in a specific validation group. * * @param string $cacheKey The hash of the object * @param string $groupHash The group's name or hash, if it is group * sequence * * @return bool Whether the object was already validated for that * group * * @internal Used by the validator engine. Should not be called by user * code. */ public function isGroupValidated($cacheKey, $groupHash); /** * Marks a constraint as validated for an object. * * @param string $cacheKey The hash of the object * @param string $constraintHash The hash of the constraint * * @internal Used by the validator engine. Should not be called by user * code. */ public function markConstraintAsValidated($cacheKey, $constraintHash); /** * Returns whether a constraint was validated for an object. * * @param string $cacheKey The hash of the object * @param string $constraintHash The hash of the constraint * * @return bool Whether the constraint was already validated * * @internal Used by the validator engine. Should not be called by user * code. */ public function isConstraintValidated($cacheKey, $constraintHash); /** * Marks that an object was initialized. * * @param string $cacheKey The hash of the object * * @internal Used by the validator engine. Should not be called by user * code. * * @see ObjectInitializerInterface */ public function markObjectAsInitialized($cacheKey); /** * Returns whether an object was initialized. * * @param string $cacheKey The hash of the object * * @return bool Whether the object was already initialized * * @internal Used by the validator engine. Should not be called by user * code. * * @see ObjectInitializerInterface */ public function isObjectInitialized($cacheKey); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Context; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; /** * An execution context that is compatible with the legacy API (< 2.5). * * @since 2.5 * @author Bernhard Schussek * * @deprecated Implemented for backwards compatibility with Symfony < 2.5. * To be removed in Symfony 3.0. */ class LegacyExecutionContext extends ExecutionContext { /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * Creates a new context. * * @see ExecutionContext::__construct() * * @internal Called by {@link LegacyExecutionContextFactory}. Should not be used * in user code. */ public function __construct(ValidatorInterface $validator, $root, MetadataFactoryInterface $metadataFactory, TranslatorInterface $translator, $translationDomain = null) { parent::__construct( $validator, $root, $translator, $translationDomain ); $this->metadataFactory = $metadataFactory; } /** * {@inheritdoc} */ public function addViolation($message, array $parameters = array(), $invalidValue = null, $plural = null, $code = null) { if (func_num_args() > 2) { $this ->buildViolation($message, $parameters) ->setInvalidValue($invalidValue) ->setPlural($plural) ->setCode($code) ->addViolation() ; return; } parent::addViolation($message, $parameters); } /** * {@inheritdoc} */ public function addViolationAt($subPath, $message, array $parameters = array(), $invalidValue = null, $plural = null, $code = null) { if (func_num_args() > 2) { $this ->buildViolation($message, $parameters) ->atPath($subPath) ->setInvalidValue($invalidValue) ->setPlural($plural) ->setCode($code) ->addViolation() ; return; } $this ->buildViolation($message, $parameters) ->atPath($subPath) ->addViolation() ; } /** * {@inheritdoc} */ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false) { if (is_array($value)) { // The $traverse flag is ignored for arrays $constraint = new Valid(array('traverse' => true, 'deep' => $deep)); return $this ->getValidator() ->inContext($this) ->atPath($subPath) ->validate($value, $constraint, $groups) ; } if ($traverse && $value instanceof \Traversable) { $constraint = new Valid(array('traverse' => true, 'deep' => $deep)); return $this ->getValidator() ->inContext($this) ->atPath($subPath) ->validate($value, $constraint, $groups) ; } return $this ->getValidator() ->inContext($this) ->atPath($subPath) ->validate($value, null, $groups) ; } /** * {@inheritdoc} */ public function validateValue($value, $constraints, $subPath = '', $groups = null) { return $this ->getValidator() ->inContext($this) ->atPath($subPath) ->validate($value, $constraints, $groups) ; } /** * {@inheritdoc} */ public function getMetadataFactory() { return $this->metadataFactory; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Context; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; /** * Creates new {@link LegacyExecutionContext} instances. * * @since 2.5 * @author Bernhard Schussek * * @deprecated Implemented for backwards compatibility with Symfony < 2.5. * To be removed in Symfony 3.0. */ class LegacyExecutionContextFactory implements ExecutionContextFactoryInterface { /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * @var TranslatorInterface */ private $translator; /** * @var string|null */ private $translationDomain; /** * Creates a new context factory. * * @param MetadataFactoryInterface $metadataFactory The metadata factory * @param TranslatorInterface $translator The translator * @param string|null $translationDomain The translation domain * to use for translating * violation messages */ public function __construct(MetadataFactoryInterface $metadataFactory, TranslatorInterface $translator, $translationDomain = null) { $this->metadataFactory = $metadataFactory; $this->translator = $translator; $this->translationDomain = $translationDomain; } /** * {@inheritdoc} */ public function createContext(ValidatorInterface $validator, $root) { return new LegacyExecutionContext( $validator, $root, $this->metadataFactory, $this->translator, $this->translationDomain ); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Context; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\ClassBasedInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; use Symfony\Component\Validator\Exception\BadMethodCallException; use Symfony\Component\Validator\Mapping\MetadataInterface; use Symfony\Component\Validator\Mapping\PropertyMetadataInterface; use Symfony\Component\Validator\Util\PropertyPath; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Validator\Violation\ConstraintViolationBuilder; /** * The context used and created by {@link ExecutionContextFactory}. * * @since 2.5 * @author Bernhard Schussek * * @see ExecutionContextInterface * * @internal You should not instantiate or use this class. Code against * {@link ExecutionContextInterface} instead. */ class ExecutionContext implements ExecutionContextInterface { /** * @var ValidatorInterface */ private $validator; /** * The root value of the validated object graph. * * @var mixed */ private $root; /** * @var TranslatorInterface */ private $translator; /** * @var string */ private $translationDomain; /** * The violations generated in the current context. * * @var ConstraintViolationList */ private $violations; /** * The currently validated value. * * @var mixed */ private $value; /** * The currently validated object. * * @var object|null */ private $object; /** * The property path leading to the current value. * * @var string */ private $propertyPath = ''; /** * The current validation metadata. * * @var MetadataInterface|null */ private $metadata; /** * The currently validated group. * * @var string|null */ private $group; /** * The currently validated constraint. * * @var Constraint|null */ private $constraint; /** * Stores which objects have been validated in which group. * * @var array */ private $validatedObjects = array(); /** * Stores which class constraint has been validated for which object. * * @var array */ private $validatedConstraints = array(); /** * Stores which objects have been initialized. * * @var array */ private $initializedObjects; /** * Creates a new execution context. * * @param ValidatorInterface $validator The validator * @param mixed $root The root value of the * validated object graph * @param TranslatorInterface $translator The translator * @param string|null $translationDomain The translation domain to * use for translating * violation messages * * @internal Called by {@link ExecutionContextFactory}. Should not be used * in user code. */ public function __construct(ValidatorInterface $validator, $root, TranslatorInterface $translator, $translationDomain = null) { $this->validator = $validator; $this->root = $root; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->violations = new ConstraintViolationList(); } /** * {@inheritdoc} */ public function setNode($value, $object, MetadataInterface $metadata = null, $propertyPath) { $this->value = $value; $this->object = $object; $this->metadata = $metadata; $this->propertyPath = (string) $propertyPath; } /** * {@inheritdoc} */ public function setGroup($group) { $this->group = $group; } /** * {@inheritdoc} */ public function setConstraint(Constraint $constraint) { $this->constraint = $constraint; } /** * {@inheritdoc} */ public function addViolation($message, array $parameters = array(), $invalidValue = null, $plural = null, $code = null) { // The parameters $invalidValue and following are ignored by the new // API, as they are not present in the new interface anymore. // You should use buildViolation() instead. if (func_num_args() > 2) { throw new BadMethodCallException( 'The parameters $invalidValue, $pluralization and $code are '. 'not supported anymore as of Symfony 2.5. Please use '. 'buildViolation() instead or enable the legacy mode.' ); } $this->violations->add(new ConstraintViolation( $this->translator->trans($message, $parameters, $this->translationDomain), $message, $parameters, $this->root, $this->propertyPath, $this->value, null, null, $this->constraint )); } /** * {@inheritdoc} */ public function buildViolation($message, array $parameters = array()) { return new ConstraintViolationBuilder( $this->violations, $this->constraint, $message, $parameters, $this->root, $this->propertyPath, $this->value, $this->translator, $this->translationDomain ); } /** * {@inheritdoc} */ public function getViolations() { return $this->violations; } /** * {@inheritdoc} */ public function getValidator() { return $this->validator; } /** * {@inheritdoc} */ public function getRoot() { return $this->root; } /** * {@inheritdoc} */ public function getValue() { return $this->value; } /** * {@inheritdoc} */ public function getObject() { return $this->object; } /** * {@inheritdoc} */ public function getMetadata() { return $this->metadata; } /** * {@inheritdoc} */ public function getGroup() { return $this->group; } /** * {@inheritdoc} */ public function getClassName() { return $this->metadata instanceof ClassBasedInterface ? $this->metadata->getClassName() : null; } /** * {@inheritdoc} */ public function getPropertyName() { return $this->metadata instanceof PropertyMetadataInterface ? $this->metadata->getPropertyName() : null; } /** * {@inheritdoc} */ public function getPropertyPath($subPath = '') { return PropertyPath::append($this->propertyPath, $subPath); } /** * {@inheritdoc} */ public function addViolationAt($subPath, $message, array $parameters = array(), $invalidValue = null, $plural = null, $code = null) { throw new BadMethodCallException( 'addViolationAt() is not supported anymore as of Symfony 2.5. '. 'Please use buildViolation() instead or enable the legacy mode.' ); } /** * {@inheritdoc} */ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false) { throw new BadMethodCallException( 'validate() is not supported anymore as of Symfony 2.5. '. 'Please use getValidator() instead or enable the legacy mode.' ); } /** * {@inheritdoc} */ public function validateValue($value, $constraints, $subPath = '', $groups = null) { throw new BadMethodCallException( 'validateValue() is not supported anymore as of Symfony 2.5. '. 'Please use getValidator() instead or enable the legacy mode.' ); } /** * {@inheritdoc} */ public function getMetadataFactory() { throw new BadMethodCallException( 'getMetadataFactory() is not supported anymore as of Symfony 2.5. '. 'Please use getValidator() in combination with getMetadataFor() '. 'or hasMetadataFor() instead or enable the legacy mode.' ); } /** * {@inheritdoc} */ public function markGroupAsValidated($cacheKey, $groupHash) { if (!isset($this->validatedObjects[$cacheKey])) { $this->validatedObjects[$cacheKey] = array(); } $this->validatedObjects[$cacheKey][$groupHash] = true; } /** * {@inheritdoc} */ public function isGroupValidated($cacheKey, $groupHash) { return isset($this->validatedObjects[$cacheKey][$groupHash]); } /** * {@inheritdoc} */ public function markConstraintAsValidated($cacheKey, $constraintHash) { $this->validatedConstraints[$cacheKey.':'.$constraintHash] = true; } /** * {@inheritdoc} */ public function isConstraintValidated($cacheKey, $constraintHash) { return isset($this->validatedConstraints[$cacheKey.':'.$constraintHash]); } /** * {@inheritdoc} */ public function markObjectAsInitialized($cacheKey) { $this->initializedObjects[$cacheKey] = true; } /** * {@inheritdoc} */ public function isObjectInitialized($cacheKey) { return isset($this->initializedObjects[$cacheKey]); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A container for validation metadata. * * The container contains constraints that may belong to different validation * groups. Constraints for a specific group can be fetched by calling * {@link findConstraints}. * * Implement this interface to add validation metadata to your own metadata * layer. Each metadata may have named properties. Each property can be * represented by one or more {@link PropertyMetadataInterface} instances that * are returned by {@link getPropertyMetadata}. Since * PropertyMetadataInterface inherits from MetadataInterface, * each property may be divided into further properties. * * The {@link accept} method of each metadata implements the Visitor pattern. * The method should forward the call to the visitor's * {@link ValidationVisitorInterface::visit} method and additionally call * accept() on all structurally related metadata instances. * * For example, to store constraints for PHP classes and their properties, * create a class ClassMetadata (implementing MetadataInterface) * and a class PropertyMetadata (implementing PropertyMetadataInterface). * ClassMetadata::getPropertyMetadata($property) returns all * PropertyMetadata instances for a property of that class. Its * accept()-method simply forwards to ValidationVisitorInterface::visit() * and calls accept() on all contained PropertyMetadata * instances, which themselves call ValidationVisitorInterface::visit() * again. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Mapping\MetadataInterface} instead. */ interface MetadataInterface { /** * Implementation of the Visitor design pattern. * * Calls {@link ValidationVisitorInterface::visit} and then forwards the * accept()-call to all property metadata instances. * * @param ValidationVisitorInterface $visitor The visitor implementing the validation logic * @param mixed $value The value to validate * @param string|string[] $group The validation group to validate in * @param string $propertyPath The current property path in the validation graph * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. */ public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath); /** * Returns all constraints for a given validation group. * * @param string $group The validation group * * @return Constraint[] A list of constraint instances */ public function findConstraints($group); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Validates values and graphs of objects and arrays. * * @author Bernhard Schussek * * @api * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link \Symfony\Component\Validator\Validator\ValidatorInterface} instead. */ interface ValidatorInterface { /** * Validates a value. * * The accepted values depend on the {@link MetadataFactoryInterface} * implementation. * * The signature changed with Symfony 2.5 (see * {@link Validator\ValidatorInterface::validate()}. This signature will be * disabled in Symfony 3.0. * * @param mixed $value The value to validate * @param array|null $groups The validation groups to validate. * @param bool $traverse Whether to traverse the value if it is traversable. * @param bool $deep Whether to traverse nested traversable values recursively. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validate($value, $groups = null, $traverse = false, $deep = false); /** * Validates a property of a value against its current value. * * The accepted values depend on the {@link MetadataFactoryInterface} * implementation. * * @param mixed $containingValue The value containing the property. * @param string $property The name of the property to validate. * @param array|null $groups The validation groups to validate. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validateProperty($containingValue, $property, $groups = null); /** * Validate a property of a value against a potential value. * * The accepted values depend on the {@link MetadataFactoryInterface} * implementation. * * @param mixed $containingValue The value containing the property. * @param string $property The name of the property to validate * @param string $value The value to validate against the * constraints of the property. * @param array|null $groups The validation groups to validate. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api */ public function validatePropertyValue($containingValue, $property, $value, $groups = null); /** * Validates a value against a constraint or a list of constraints. * * @param mixed $value The value to validate. * @param Constraint|Constraint[] $constraints The constraint(s) to validate against. * @param array|null $groups The validation groups to validate. * * @return ConstraintViolationListInterface A list of constraint violations. If the * list is empty, validation succeeded. * * @api * * @deprecated Renamed to {@link Validator\ValidatorInterface::validate()} * in Symfony 2.5. Will be removed in Symfony 3.0. */ public function validateValue($value, $constraints, $groups = null); /** * Returns the factory for metadata instances. * * @return MetadataFactoryInterface The metadata factory. * * @api * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Validator\ValidatorInterface::getMetadataFor()} or * {@link Validator\ValidatorInterface::hasMetadataFor()} * instead. */ public function getMetadataFactory(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\CachedReader; use Doctrine\Common\Annotations\Reader; use Doctrine\Common\Cache\ArrayCache; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Context\ExecutionContextFactory; use Symfony\Component\Validator\Context\LegacyExecutionContextFactory; use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Validator\Mapping\Cache\CacheInterface; use Symfony\Component\Validator\Mapping\ClassMetadataFactory; use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; use Symfony\Component\Validator\Mapping\Loader\LoaderChain; use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader; use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; use Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader; use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; use Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader; use Symfony\Component\Validator\Validator\LegacyValidator; use Symfony\Component\Validator\Validator\RecursiveValidator; use Symfony\Component\Validator\Validator as ValidatorV24; /** * The default implementation of {@link ValidatorBuilderInterface}. * * @author Bernhard Schussek */ class ValidatorBuilder implements ValidatorBuilderInterface { /** * @var array */ private $initializers = array(); /** * @var array */ private $xmlMappings = array(); /** * @var array */ private $yamlMappings = array(); /** * @var array */ private $methodMappings = array(); /** * @var Reader|null */ private $annotationReader; /** * @var MetadataFactoryInterface|null */ private $metadataFactory; /** * @var ConstraintValidatorFactoryInterface|null */ private $validatorFactory; /** * @var CacheInterface|null */ private $metadataCache; /** * @var TranslatorInterface|null */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var PropertyAccessorInterface|null */ private $propertyAccessor; /** * @var int|null */ private $apiVersion; /** * {@inheritdoc} */ public function addObjectInitializer(ObjectInitializerInterface $initializer) { $this->initializers[] = $initializer; return $this; } /** * {@inheritdoc} */ public function addObjectInitializers(array $initializers) { $this->initializers = array_merge($this->initializers, $initializers); return $this; } /** * {@inheritdoc} */ public function addXmlMapping($path) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->xmlMappings[] = $path; return $this; } /** * {@inheritdoc} */ public function addXmlMappings(array $paths) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->xmlMappings = array_merge($this->xmlMappings, $paths); return $this; } /** * {@inheritdoc} */ public function addYamlMapping($path) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->yamlMappings[] = $path; return $this; } /** * {@inheritdoc} */ public function addYamlMappings(array $paths) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->yamlMappings = array_merge($this->yamlMappings, $paths); return $this; } /** * {@inheritdoc} */ public function addMethodMapping($methodName) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->methodMappings[] = $methodName; return $this; } /** * {@inheritdoc} */ public function addMethodMappings(array $methodNames) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->methodMappings = array_merge($this->methodMappings, $methodNames); return $this; } /** * {@inheritdoc} */ public function enableAnnotationMapping(Reader $annotationReader = null) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot enable annotation mapping after setting a custom metadata factory. Configure your metadata factory instead.'); } if (null === $annotationReader) { if (!class_exists('Doctrine\Common\Annotations\AnnotationReader') || !class_exists('Doctrine\Common\Cache\ArrayCache')) { throw new \RuntimeException('Enabling annotation based constraint mapping requires the packages doctrine/annotations and doctrine/cache to be installed.'); } $annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache()); } $this->annotationReader = $annotationReader; return $this; } /** * {@inheritdoc} */ public function disableAnnotationMapping() { $this->annotationReader = null; return $this; } /** * {@inheritdoc} */ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory) { if (count($this->xmlMappings) > 0 || count($this->yamlMappings) > 0 || count($this->methodMappings) > 0 || null !== $this->annotationReader) { throw new ValidatorException('You cannot set a custom metadata factory after adding custom mappings. You should do either of both.'); } $this->metadataFactory = $metadataFactory; return $this; } /** * {@inheritdoc} */ public function setMetadataCache(CacheInterface $cache) { if (null !== $this->metadataFactory) { throw new ValidatorException('You cannot set a custom metadata cache after setting a custom metadata factory. Configure your metadata factory instead.'); } $this->metadataCache = $cache; return $this; } /** * {@inheritdoc} */ public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory) { if (null !== $this->propertyAccessor) { throw new ValidatorException('You cannot set a validator factory after setting a custom property accessor. Remove the call to setPropertyAccessor() if you want to call setConstraintValidatorFactory().'); } $this->validatorFactory = $validatorFactory; return $this; } /** * {@inheritdoc} */ public function setTranslator(TranslatorInterface $translator) { $this->translator = $translator; return $this; } /** * {@inheritdoc} */ public function setTranslationDomain($translationDomain) { $this->translationDomain = $translationDomain; return $this; } /** * {@inheritdoc} */ public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor) { if (null !== $this->validatorFactory) { throw new ValidatorException('You cannot set a property accessor after setting a custom validator factory. Configure your validator factory instead.'); } $this->propertyAccessor = $propertyAccessor; return $this; } /** * {@inheritdoc} */ public function setApiVersion($apiVersion) { if (!in_array($apiVersion, array(Validation::API_VERSION_2_4, Validation::API_VERSION_2_5, Validation::API_VERSION_2_5_BC))) { throw new InvalidArgumentException(sprintf( 'The requested API version is invalid: "%s"', $apiVersion )); } if (PHP_VERSION_ID < 50309 && $apiVersion === Validation::API_VERSION_2_5_BC) { throw new InvalidArgumentException(sprintf( 'The Validator API that is compatible with both Symfony 2.4 '. 'and Symfony 2.5 can only be used on PHP 5.3.9 and higher. '. 'Your current PHP version is %s.', PHP_VERSION )); } $this->apiVersion = $apiVersion; return $this; } /** * {@inheritdoc} */ public function getValidator() { $metadataFactory = $this->metadataFactory; $apiVersion = $this->apiVersion; if (null === $apiVersion) { $apiVersion = PHP_VERSION_ID < 50309 ? Validation::API_VERSION_2_4 : Validation::API_VERSION_2_5_BC; } if (!$metadataFactory) { $loaders = array(); if (count($this->xmlMappings) > 1) { $loaders[] = new XmlFilesLoader($this->xmlMappings); } elseif (1 === count($this->xmlMappings)) { $loaders[] = new XmlFileLoader($this->xmlMappings[0]); } if (count($this->yamlMappings) > 1) { $loaders[] = new YamlFilesLoader($this->yamlMappings); } elseif (1 === count($this->yamlMappings)) { $loaders[] = new YamlFileLoader($this->yamlMappings[0]); } foreach ($this->methodMappings as $methodName) { $loaders[] = new StaticMethodLoader($methodName); } if ($this->annotationReader) { $loaders[] = new AnnotationLoader($this->annotationReader); } $loader = null; if (count($loaders) > 1) { $loader = new LoaderChain($loaders); } elseif (1 === count($loaders)) { $loader = $loaders[0]; } if (Validation::API_VERSION_2_5 === $apiVersion) { $metadataFactory = new LazyLoadingMetadataFactory($loader, $this->metadataCache); } else { $metadataFactory = new ClassMetadataFactory($loader, $this->metadataCache); } } $validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory($this->propertyAccessor); $translator = $this->translator ?: new DefaultTranslator(); if (Validation::API_VERSION_2_4 === $apiVersion) { return new ValidatorV24($metadataFactory, $validatorFactory, $translator, $this->translationDomain, $this->initializers); } if (Validation::API_VERSION_2_5 === $apiVersion) { $contextFactory = new ExecutionContextFactory($translator, $this->translationDomain); return new RecursiveValidator($contextFactory, $metadataFactory, $validatorFactory, $this->initializers); } $contextFactory = new LegacyExecutionContextFactory($metadataFactory, $translator, $this->translationDomain); return new LegacyValidator($contextFactory, $metadataFactory, $validatorFactory, $this->initializers); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A violation of a constraint that happened during validation. * * For each constraint that fails during validation one or more violations are * created. The violations store the violation message, the path to the failing * element in the validation graph and the root element that was originally * passed to the validator. For example, take the following graph: * *
 * (Person)---(firstName: string)
 *      \
 *   (address: Address)---(street: string)
 * 
* * If the Person object is validated and validation fails for the * "firstName" property, the generated violation has the Person * instance as root and the property path "firstName". If validation fails * for the "street" property of the related Address instance, the root * element is still the person, but the property path is "address.street". * * @author Bernhard Schussek * * @api */ interface ConstraintViolationInterface { /** * Returns the violation message. * * @return string The violation message. * * @api */ public function getMessage(); /** * Returns the raw violation message. * * The raw violation message contains placeholders for the parameters * returned by {@link getMessageParameters}. Typically you'll pass the * message template and parameters to a translation engine. * * @return string The raw violation message. * * @api */ public function getMessageTemplate(); /** * Returns the parameters to be inserted into the raw violation message. * * @return array A possibly empty list of parameters indexed by the names * that appear in the message template. * * @see getMessageTemplate() * * @api */ public function getMessageParameters(); /** * Returns a number for pluralizing the violation message. * * For example, the message template could have different translation based * on a parameter "choices": * *
    *
  • Please select exactly one entry. (choices=1)
  • *
  • Please select two entries. (choices=2)
  • *
* * This method returns the value of the parameter for choosing the right * pluralization form (in this case "choices"). * * @return int|null The number to use to pluralize of the message. */ public function getMessagePluralization(); /** * Returns the root element of the validation. * * @return mixed The value that was passed originally to the validator when * the validation was started. Because the validator traverses * the object graph, the value at which the violation occurs * is not necessarily the value that was originally validated. * * @api */ public function getRoot(); /** * Returns the property path from the root element to the violation. * * @return string The property path indicates how the validator reached * the invalid value from the root element. If the root * element is a Person instance with a property * "address" that contains an Address instance * with an invalid property "street", the generated property * path is "address.street". Property access is denoted by * dots, while array access is denoted by square brackets, * for example "addresses[1].street". * * @api */ public function getPropertyPath(); /** * Returns the value that caused the violation. * * @return mixed The invalid value that caused the validated constraint to * fail. * * @api */ public function getInvalidValue(); /** * Returns a machine-digestible error code for the violation. * * @return mixed The error code. */ public function getCode(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Violation; use Symfony\Component\Validator\ExecutionContextInterface; /** * Backwards-compatible implementation of {@link ConstraintViolationBuilderInterface}. * * @author Bernhard Schussek * * @internal You should not instantiate or use this class. Code against * {@link ConstraintViolationBuilderInterface} instead. * * @deprecated This class will be removed in Symfony 3.0. */ class LegacyConstraintViolationBuilder implements ConstraintViolationBuilderInterface { /** * @var ExecutionContextInterface */ private $context; /** * @var string */ private $message; /** * @var array */ private $parameters; /** * @var mixed */ private $invalidValue; /** * @var string */ private $propertyPath; /** * @var int|null */ private $plural; /** * @var mixed */ private $code; public function __construct(ExecutionContextInterface $context, $message, array $parameters) { $this->context = $context; $this->message = $message; $this->parameters = $parameters; $this->invalidValue = $context->getValue(); } /** * {@inheritdoc} */ public function atPath($path) { $this->propertyPath = $path; return $this; } /** * {@inheritdoc} */ public function setParameter($key, $value) { $this->parameters[$key] = $value; return $this; } /** * {@inheritdoc} */ public function setParameters(array $parameters) { $this->parameters = $parameters; return $this; } /** * {@inheritdoc} */ public function setTranslationDomain($translationDomain) { // can't be set in the old API return $this; } /** * {@inheritdoc} */ public function setInvalidValue($invalidValue) { $this->invalidValue = $invalidValue; return $this; } /** * {@inheritdoc} */ public function setPlural($number) { $this->plural = $number; return $this; } /** * {@inheritdoc} */ public function setCode($code) { $this->code = $code; return $this; } /** * {@inheritdoc} */ public function setCause($cause) { // do nothing - we can't save the cause through the old API return $this; } /** * {@inheritdoc} */ public function addViolation() { if ($this->propertyPath) { $this->context->addViolationAt($this->propertyPath, $this->message, $this->parameters, $this->invalidValue, $this->plural, $this->code); return; } $this->context->addViolation($this->message, $this->parameters, $this->invalidValue, $this->plural, $this->code); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Violation; /** * Builds {@link \Symfony\Component\Validator\ConstraintViolationInterface} * objects. * * Use the various methods on this interface to configure the built violation. * Finally, call {@link addViolation()} to add the violation to the current * execution context. * * @since 2.5 * @author Bernhard Schussek */ interface ConstraintViolationBuilderInterface { /** * Stores the property path at which the violation should be generated. * * The passed path will be appended to the current property path of the * execution context. * * @param string $path The property path * * @return ConstraintViolationBuilderInterface This builder */ public function atPath($path); /** * Sets a parameter to be inserted into the violation message. * * @param string $key The name of the parameter * @param string $value The value to be inserted in the parameter's place * * @return ConstraintViolationBuilderInterface This builder */ public function setParameter($key, $value); /** * Sets all parameters to be inserted into the violation message. * * @param array $parameters An array with the parameter names as keys and * the values to be inserted in their place as * values * * @return ConstraintViolationBuilderInterface This builder */ public function setParameters(array $parameters); /** * Sets the translation domain which should be used for translating the * violation message. * * @param string $translationDomain The translation domain * * @return ConstraintViolationBuilderInterface This builder * * @see \Symfony\Component\Translation\TranslatorInterface */ public function setTranslationDomain($translationDomain); /** * Sets the invalid value that caused this violation. * * @param mixed $invalidValue The invalid value * * @return ConstraintViolationBuilderInterface This builder */ public function setInvalidValue($invalidValue); /** * Sets the number which determines how the plural form of the violation * message is chosen when it is translated. * * @param int $number The number for determining the plural form * * @return ConstraintViolationBuilderInterface This builder * * @see \Symfony\Component\Translation\TranslatorInterface::transChoice() */ public function setPlural($number); /** * Sets the violation code. * * @param int $code The violation code * * @return ConstraintViolationBuilderInterface This builder */ public function setCode($code); /** * Sets the cause of the violation. * * @param mixed $cause The cause of the violation * * @return ConstraintViolationBuilderInterface This builder */ public function setCause($cause); /** * Adds the violation to the current execution context. */ public function addViolation(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Violation; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; use Symfony\Component\Validator\Util\PropertyPath; /** * Default implementation of {@link ConstraintViolationBuilderInterface}. * * @since 2.5 * @author Bernhard Schussek * * @internal You should not instantiate or use this class. Code against * {@link ConstraintViolationBuilderInterface} instead. */ class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface { /** * @var ConstraintViolationList */ private $violations; /** * @var string */ private $message; /** * @var array */ private $parameters; /** * @var mixed */ private $root; /** * @var mixed */ private $invalidValue; /** * @var string */ private $propertyPath; /** * @var TranslatorInterface */ private $translator; /** * @var string|null */ private $translationDomain; /** * @var int|null */ private $plural; /** * @var Constraint */ private $constraint; /** * @var mixed */ private $code; /** * @var mixed */ private $cause; public function __construct(ConstraintViolationList $violations, Constraint $constraint, $message, array $parameters, $root, $propertyPath, $invalidValue, TranslatorInterface $translator, $translationDomain = null) { $this->violations = $violations; $this->message = $message; $this->parameters = $parameters; $this->root = $root; $this->propertyPath = $propertyPath; $this->invalidValue = $invalidValue; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->constraint = $constraint; } /** * {@inheritdoc} */ public function atPath($path) { $this->propertyPath = PropertyPath::append($this->propertyPath, $path); return $this; } /** * {@inheritdoc} */ public function setParameter($key, $value) { $this->parameters[$key] = $value; return $this; } /** * {@inheritdoc} */ public function setParameters(array $parameters) { $this->parameters = $parameters; return $this; } /** * {@inheritdoc} */ public function setTranslationDomain($translationDomain) { $this->translationDomain = $translationDomain; return $this; } /** * {@inheritdoc} */ public function setInvalidValue($invalidValue) { $this->invalidValue = $invalidValue; return $this; } /** * {@inheritdoc} */ public function setPlural($number) { $this->plural = $number; return $this; } /** * {@inheritdoc} */ public function setCode($code) { $this->code = $code; return $this; } /** * {@inheritdoc} */ public function setCause($cause) { $this->cause = $cause; return $this; } /** * {@inheritdoc} */ public function addViolation() { if (null === $this->plural) { $translatedMessage = $this->translator->trans( $this->message, $this->parameters, $this->translationDomain ); } else { try { $translatedMessage = $this->translator->transChoice( $this->message, $this->plural, $this->parameters, $this->translationDomain# ); } catch (\InvalidArgumentException $e) { $translatedMessage = $this->translator->trans( $this->message, $this->parameters, $this->translationDomain ); } } $this->violations->add(new ConstraintViolation( $translatedMessage, $this->message, $this->parameters, $this->root, $this->propertyPath, $this->invalidValue, $this->plural, $this->code, $this->constraint, $this->cause )); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Util; /** * Contains utility methods for dealing with property paths. * * For more extensive functionality, use Symfony's PropertyAccess component. * * @since 2.5 * * @author Bernhard Schussek */ class PropertyPath { /** * Appends a path to a given property path. * * If the base path is empty, the appended path will be returned unchanged. * If the base path is not empty, and the appended path starts with a * squared opening bracket ("["), the concatenation of the two paths is * returned. Otherwise, the concatenation of the two paths is returned, * separated by a dot ("."). * * @param string $basePath The base path * @param string $subPath The path to append * * @return string The concatenation of the two property paths */ public static function append($basePath, $subPath) { if ('' !== (string) $subPath) { if ('[' === $subPath{0}) { return $basePath.$subPath; } return '' !== (string) $basePath ? $basePath.'.'.$subPath : $subPath; } return $basePath; } /** * Not instantiable. */ private function __construct() { } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Default implementation of {@ConstraintViolationInterface}. * * @author Bernhard Schussek */ class ConstraintViolation implements ConstraintViolationInterface { /** * @var string */ private $message; /** * @var string */ private $messageTemplate; /** * @var array */ private $parameters; /** * @var int|null */ private $plural; /** * @var mixed */ private $root; /** * @var string */ private $propertyPath; /** * @var mixed */ private $invalidValue; /** * @var Constraint|null */ private $constraint; /** * @var mixed */ private $code; /** * @var mixed */ private $cause; /** * Creates a new constraint violation. * * @param string $message The violation message * @param string $messageTemplate The raw violation message * @param array $parameters The parameters to substitute in the * raw violation message * @param mixed $root The value originally passed to the * validator * @param string $propertyPath The property path from the root * value to the invalid value * @param mixed $invalidValue The invalid value that caused this * violation * @param int|null $plural The number for determining the plural * form when translating the message * @param mixed $code The error code of the violation * @param Constraint|null $constraint The constraint whose validation * caused the violation * @param mixed $cause The cause of the violation */ public function __construct($message, $messageTemplate, array $parameters, $root, $propertyPath, $invalidValue, $plural = null, $code = null, Constraint $constraint = null, $cause = null) { $this->message = $message; $this->messageTemplate = $messageTemplate; $this->parameters = $parameters; $this->plural = $plural; $this->root = $root; $this->propertyPath = $propertyPath; $this->invalidValue = $invalidValue; $this->constraint = $constraint; $this->code = $code; $this->cause = $cause; } /** * Converts the violation into a string for debugging purposes. * * @return string The violation as string. */ public function __toString() { if (is_object($this->root)) { $class = 'Object('.get_class($this->root).')'; } elseif (is_array($this->root)) { $class = 'Array'; } else { $class = (string) $this->root; } $propertyPath = (string) $this->propertyPath; $code = $this->code; if ('' !== $propertyPath && '[' !== $propertyPath[0] && '' !== $class) { $class .= '.'; } if (!empty($code)) { $code = ' (code '.$code.')'; } return $class.$propertyPath.":\n ".$this->getMessage().$code; } /** * {@inheritdoc} */ public function getMessageTemplate() { return $this->messageTemplate; } /** * {@inheritdoc} */ public function getMessageParameters() { return $this->parameters; } /** * Alias of {@link getMessageParameters()}. */ public function getParameters() { return $this->parameters; } /** * {@inheritdoc} */ public function getMessagePluralization() { return $this->plural; } /** * Alias of {@link getMessagePluralization()}. */ public function getPlural() { return $this->plural; } /** * {@inheritdoc} */ public function getMessage() { return $this->message; } /** * {@inheritdoc} */ public function getRoot() { return $this->root; } /** * {@inheritdoc} */ public function getPropertyPath() { return $this->propertyPath; } /** * {@inheritdoc} */ public function getInvalidValue() { return $this->invalidValue; } /** * Returns the constraint whose validation caused the violation. * * @return Constraint|null The constraint or null if it is not known */ public function getConstraint() { return $this->constraint; } /** * Returns the cause of the violation. * * @return mixed */ public function getCause() { return $this->cause; } /** * {@inheritdoc} */ public function getCode() { return $this->code; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A container for {@link PropertyMetadataInterface} instances. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Mapping\ClassMetadataInterface} instead. */ interface PropertyMetadataContainerInterface { /** * Check if there's any metadata attached to the given named property. * * @param string $property The property name. * * @return bool */ public function hasPropertyMetadata($property); /** * Returns all metadata instances for the given named property. * * If your implementation does not support properties, simply throw an * exception in this method (for example a BadMethodCallException). * * @param string $property The property name. * * @return PropertyMetadataInterface[] A list of metadata instances. Empty if * no metadata exists for the property. */ public function getPropertyMetadata($property); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Exception\NoSuchMetadataException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Default implementation of {@link ValidationVisitorInterface} and * {@link GlobalExecutionContextInterface}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. */ class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionContextInterface { /** * @var mixed */ private $root; /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * @var ConstraintValidatorFactoryInterface */ private $validatorFactory; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var array */ private $objectInitializers; /** * @var ConstraintViolationList */ private $violations; /** * @var array */ private $validatedObjects = array(); /** * Creates a new validation visitor. * * @param mixed $root The value passed to the validator. * @param MetadataFactoryInterface $metadataFactory The factory for obtaining metadata instances. * @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating constraint validators. * @param TranslatorInterface $translator The translator for translating violation messages. * @param string|null $translationDomain The domain of the translation messages. * @param ObjectInitializerInterface[] $objectInitializers The initializers for preparing objects before validation. * * @throws UnexpectedTypeException If any of the object initializers is not an instance of ObjectInitializerInterface */ public function __construct($root, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = null, array $objectInitializers = array()) { foreach ($objectInitializers as $initializer) { if (!$initializer instanceof ObjectInitializerInterface) { throw new UnexpectedTypeException($initializer, 'Symfony\Component\Validator\ObjectInitializerInterface'); } } $this->root = $root; $this->metadataFactory = $metadataFactory; $this->validatorFactory = $validatorFactory; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->objectInitializers = $objectInitializers; $this->violations = new ConstraintViolationList(); } /** * {@inheritdoc} */ public function visit(MetadataInterface $metadata, $value, $group, $propertyPath) { $context = new ExecutionContext( $this, $this->translator, $this->translationDomain, $metadata, $value, $group, $propertyPath ); $context->validateValue($value, $metadata->findConstraints($group)); } /** * {@inheritdoc} */ public function validate($value, $group, $propertyPath, $traverse = false, $deep = false) { if (null === $value) { return; } if (is_object($value)) { $hash = spl_object_hash($value); // Exit, if the object is already validated for the current group if (isset($this->validatedObjects[$hash][$group])) { return; } // Initialize if the object wasn't initialized before if (!isset($this->validatedObjects[$hash])) { foreach ($this->objectInitializers as $initializer) { if (!$initializer instanceof ObjectInitializerInterface) { throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.'); } $initializer->initialize($value); } } // Remember validating this object before starting and possibly // traversing the object graph $this->validatedObjects[$hash][$group] = true; } // Validate arrays recursively by default, otherwise every driver needs // to implement special handling for arrays. // https://github.com/symfony/symfony/issues/6246 if (is_array($value) || ($traverse && $value instanceof \Traversable)) { foreach ($value as $key => $element) { // Ignore any scalar values in the collection if (is_object($element) || is_array($element)) { // Only repeat the traversal if $deep is set $this->validate($element, $group, $propertyPath.'['.$key.']', $deep, $deep); } } try { $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath); } catch (NoSuchMetadataException $e) { // Metadata doesn't necessarily have to exist for // traversable objects, because we know how to validate // them anyway. Optionally, additional metadata is supported. } } else { $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath); } } /** * {@inheritdoc} */ public function getViolations() { return $this->violations; } /** * {@inheritdoc} */ public function getRoot() { return $this->root; } /** * {@inheritdoc} */ public function getVisitor() { return $this; } /** * {@inheritdoc} */ public function getValidatorFactory() { return $this->validatorFactory; } /** * {@inheritdoc} */ public function getMetadataFactory() { return $this->metadataFactory; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Context\ExecutionContextInterface as ExecutionContextInterface2Dot5; use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface; use Symfony\Component\Validator\Violation\LegacyConstraintViolationBuilder; /** * Base class for constraint validators. * * @author Bernhard Schussek * * @api */ abstract class ConstraintValidator implements ConstraintValidatorInterface { /** * Whether to format {@link \DateTime} objects as RFC-3339 dates * ("Y-m-d H:i:s"). * * @var int */ const PRETTY_DATE = 1; /** * Whether to cast objects with a "__toString()" method to strings. * * @var int */ const OBJECT_TO_STRING = 2; /** * @var ExecutionContextInterface */ protected $context; /** * {@inheritdoc} */ public function initialize(ExecutionContextInterface $context) { $this->context = $context; } /** * Wrapper for {@link ExecutionContextInterface::buildViolation} that * supports the 2.4 context API. * * @param string $message The violation message * @param array $parameters The message parameters * * @return ConstraintViolationBuilderInterface The violation builder * * @deprecated This method will be removed in Symfony 3.0. */ protected function buildViolation($message, array $parameters = array()) { if ($this->context instanceof ExecutionContextInterface2Dot5) { return $this->context->buildViolation($message, $parameters); } return new LegacyConstraintViolationBuilder($this->context, $message, $parameters); } /** * Wrapper for {@link ExecutionContextInterface::buildViolation} that * supports the 2.4 context API. * * @param ExecutionContextInterface $context The context to use * @param string $message The violation message * @param array $parameters The message parameters * * @return ConstraintViolationBuilderInterface The violation builder * * @deprecated This method will be removed in Symfony 3.0. */ protected function buildViolationInContext(ExecutionContextInterface $context, $message, array $parameters = array()) { if ($context instanceof ExecutionContextInterface2Dot5) { return $context->buildViolation($message, $parameters); } return new LegacyConstraintViolationBuilder($context, $message, $parameters); } /** * Returns a string representation of the type of the value. * * This method should be used if you pass the type of a value as * message parameter to a constraint violation. Note that such * parameters should usually not be included in messages aimed at * non-technical people. * * @param mixed $value The value to return the type of * * @return string The type of the value */ protected function formatTypeOf($value) { return is_object($value) ? get_class($value) : gettype($value); } /** * Returns a string representation of the value. * * This method returns the equivalent PHP tokens for most scalar types * (i.e. "false" for false, "1" for 1 etc.). Strings are always wrapped * in double quotes ("). Objects, arrays and resources are formatted as * "object", "array" and "resource". If the parameter $prettyDateTime * is set to true, {@link \DateTime} objects will be formatted as * RFC-3339 dates ("Y-m-d H:i:s"). * * Be careful when passing message parameters to a constraint violation * that (may) contain objects, arrays or resources. These parameters * should only be displayed for technical users. Non-technical users * won't know what an "object", "array" or "resource" is and will be * confused by the violation message. * * @param mixed $value The value to format as string * @param int $format A bitwise combination of the format * constants in this class * * @return string The string representation of the passed value */ protected function formatValue($value, $format = 0) { $isDateTime = $value instanceof \DateTime || $value instanceof \DateTimeInterface; if (($format & self::PRETTY_DATE) && $isDateTime) { if (class_exists('IntlDateFormatter')) { $locale = \Locale::getDefault(); $formatter = new \IntlDateFormatter($locale, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT); // neither the native nor the stub IntlDateFormatter support // DateTimeImmutable as of yet if (!$value instanceof \DateTime) { $value = new \DateTime( $value->format('Y-m-d H:i:s.u e'), $value->getTimezone() ); } return $formatter->format($value); } return $value->format('Y-m-d H:i:s'); } if (is_object($value)) { if ($format & self::OBJECT_TO_STRING && method_exists($value, '__toString')) { return $value->__toString(); } return 'object'; } if (is_array($value)) { return 'array'; } if (is_string($value)) { return '"'.$value.'"'; } if (is_resource($value)) { return 'resource'; } if (null === $value) { return 'null'; } if (false === $value) { return 'false'; } if (true === $value) { return 'true'; } return (string) $value; } /** * Returns a string representation of a list of values. * * Each of the values is converted to a string using * {@link formatValue()}. The values are then concatenated with commas. * * @param array $values A list of values * @param int $format A bitwise combination of the format * constants in this class * * @return string The string representation of the value list * * @see formatValue() */ protected function formatValues(array $values, $format = 0) { foreach ($values as $key => $value) { $values[$key] = $this->formatValue($value, $format); } return implode(', ', $values); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Defines the interface for a group sequence provider. */ interface GroupSequenceProviderInterface { /** * Returns which validation groups should be used for a certain state * of the object. * * @return array An array of validation groups */ public function getGroupSequence(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Exception\BadMethodCallException; use Symfony\Component\Validator\Exception\InvalidArgumentException; /** * Simple translator implementation that simply replaces the parameters in * the message IDs. * * Example usage: * * $translator = new DefaultTranslator(); * * echo $translator->trans( * 'This is a {{ var }}.', * array('{{ var }}' => 'donkey') * ); * * // -> This is a donkey. * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 3, * array('{{ count }}' => 'three') * ); * * // -> These are three donkeys. * * This translator does not support message catalogs, translation domains or * locales. Instead, it implements a subset of the capabilities of * {@link \Symfony\Component\Translation\Translator} and can be used in places * where translation is not required by default but should be optional. * * @author Bernhard Schussek */ class DefaultTranslator implements TranslatorInterface { /** * Interpolates the given message. * * Parameters are replaced in the message in the same manner that * {@link strtr()} uses. * * Example usage: * * $translator = new DefaultTranslator(); * * echo $translator->trans( * 'This is a {{ var }}.', * array('{{ var }}' => 'donkey') * ); * * // -> This is a donkey. * * @param string $id The message id * @param array $parameters An array of parameters for the message * @param string $domain Ignored * @param string $locale Ignored * * @return string The interpolated string */ public function trans($id, array $parameters = array(), $domain = null, $locale = null) { return strtr($id, $parameters); } /** * Interpolates the given choice message by choosing a variant according to a number. * * The variants are passed in the message ID using the format * "|". "" is chosen if the passed $number is * exactly 1. "" is chosen otherwise. * * This format is consistent with the format supported by * {@link \Symfony\Component\Translation\Translator}, but it does not * have the same expressiveness. While Translator supports intervals in * message translations, which are needed for languages other than English, * this translator does not. You should use Translator or a custom * implementation of {@link \Symfony\Component\Translation\TranslatorInterface} if you need this or similar * functionality. * * Example usage: * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 0, * array('{{ count }}' => 0) * ); * * // -> These are 0 donkeys. * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 1, * array('{{ count }}' => 1) * ); * * // -> This is 1 donkey. * * echo $translator->transChoice( * 'This is {{ count }} donkey.|These are {{ count }} donkeys.', * 3, * array('{{ count }}' => 3) * ); * * // -> These are 3 donkeys. * * @param string $id The message id * @param int $number The number to use to find the index of the message * @param array $parameters An array of parameters for the message * @param string $domain Ignored * @param string $locale Ignored * * @return string The translated string * * @throws InvalidArgumentException If the message id does not have the format * "singular|plural". */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) { $ids = explode('|', $id); if (1 == $number) { return strtr($ids[0], $parameters); } if (!isset($ids[1])) { throw new InvalidArgumentException(sprintf('The message "%s" cannot be pluralized, because it is missing a plural (e.g. "There is one apple|There are %%count%% apples").', $id)); } return strtr($ids[1], $parameters); } /** * Not supported. * * @param string $locale The locale * * @throws BadMethodCallException */ public function setLocale($locale) { throw new BadMethodCallException('Unsupported method.'); } /** * Returns the locale of the translator. * * @return string Always returns 'en' */ public function getLocale() { return 'en'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Specifies an object able to return the correct ConstraintValidatorInterface * instance given a Constraint object. */ interface ConstraintValidatorFactoryInterface { /** * Given a Constraint, this returns the ConstraintValidatorInterface * object that should be used to verify its validity. * * @param Constraint $constraint The source constraint * * @return ConstraintValidatorInterface */ public function getInstance(Constraint $constraint); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Returns {@link MetadataInterface} instances for values. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Mapping\Factory\MetadataFactoryInterface} instead. */ interface MetadataFactoryInterface { /** * Returns the metadata for the given value. * * @param mixed $value Some value * * @return MetadataInterface The metadata for the value * * @throws Exception\NoSuchMetadataException If no metadata exists for the given value */ public function getMetadataFor($value); /** * Returns whether the class is able to return metadata for the given value. * * @param mixed $value Some value * * @return bool Whether metadata can be returned for that value */ public function hasMetadataFor($value); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"ANNOTATION"}) * * @author Bernhard Schussek */ class Required extends Existence { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Date extends Constraint { const INVALID_FORMAT_ERROR = 1; const INVALID_DATE_ERROR = 2; protected static $errorNames = array( self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR', self::INVALID_DATE_ERROR => 'INVALID_DATE_ERROR', ); public $message = 'This value is not a valid date.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Daniel Holmes */ class LessThanOrEqual extends AbstractComparison { public $message = 'This value should be less than or equal to {{ compared_value }}.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Exception\RuntimeException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Fabien Potencier * @author Bernhard Schussek */ class ExpressionValidator extends ConstraintValidator { /** * @var PropertyAccessorInterface */ private $propertyAccessor; /** * @var ExpressionLanguage */ private $expressionLanguage; /** * @param PropertyAccessorInterface|null $propertyAccessor Optional as of Symfony 2.5 * * @throws UnexpectedTypeException If the property accessor is invalid */ public function __construct($propertyAccessor = null) { if (null !== $propertyAccessor && !$propertyAccessor instanceof PropertyAccessorInterface) { throw new UnexpectedTypeException($propertyAccessor, 'null or \Symfony\Component\PropertyAccess\PropertyAccessorInterface'); } $this->propertyAccessor = $propertyAccessor; } /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Expression) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Expression'); } $variables = array(); // Symfony 2.5+ if ($this->context instanceof ExecutionContextInterface) { $variables['value'] = $value; $variables['this'] = $this->context->getObject(); } elseif (null === $this->context->getPropertyName()) { $variables['value'] = $value; $variables['this'] = $value; } else { $root = $this->context->getRoot(); $variables['value'] = $value; if (is_object($root)) { // Extract the object that the property belongs to from the object // graph $path = new PropertyPath($this->context->getPropertyPath()); $parentPath = $path->getParent(); $variables['this'] = $parentPath ? $this->getPropertyAccessor()->getValue($root, $parentPath) : $root; } else { $variables['this'] = null; } } if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } private function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(); } return $this->expressionLanguage; } private function getPropertyAccessor() { if (null === $this->propertyAccessor) { if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) { throw new RuntimeException('Unable to use expressions as the Symfony PropertyAccess component is not installed.'); } $this->propertyAccessor = PropertyAccess::createPropertyAccessor(); } return $this->propertyAccessor; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class DateTimeValidator extends DateValidator { const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/'; /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof DateTime) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\DateTime'); } if (null === $value || '' === $value || $value instanceof \DateTime) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if (!preg_match(static::PATTERN, $value, $matches)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(DateTime::INVALID_FORMAT_ERROR) ->addViolation(); return; } if (!DateValidator::checkDate($matches[1], $matches[2], $matches[3])) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(DateTime::INVALID_DATE_ERROR) ->addViolation(); } if (!TimeValidator::checkTime($matches[4], $matches[5], $matches[6])) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(DateTime::INVALID_TIME_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid language code. * * @author Bernhard Schussek * * @api */ class LanguageValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Language) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Language'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $languages = Intl::getLanguageBundle()->getLanguageNames(); if (!isset($languages[$value])) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Manuel Reinhard * @author Michael Schummel * @author Bernhard Schussek */ class Iban extends Constraint { const TOO_SHORT_ERROR = 1; const INVALID_COUNTRY_CODE_ERROR = 2; const INVALID_CHARACTERS_ERROR = 3; const INVALID_CASE_ERROR = 4; const CHECKSUM_FAILED_ERROR = 5; protected static $errorNames = array( self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR', self::INVALID_COUNTRY_CODE_ERROR => 'INVALID_COUNTRY_CODE_ERROR', self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR', self::INVALID_CASE_ERROR => 'INVALID_CASE_ERROR', self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR', ); public $message = 'This is not a valid International Bank Account Number (IBAN).'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"CLASS", "PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Callback extends Constraint { /** * @var string|callable * * @since 2.4 */ public $callback; /** * @var array * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. */ public $methods; /** * {@inheritdoc} */ public function __construct($options = null) { // Invocation through annotations with an array parameter only if (is_array($options) && 1 === count($options) && isset($options['value'])) { $options = $options['value']; } if (is_array($options) && !isset($options['callback']) && !isset($options['methods']) && !isset($options['groups'])) { if (is_callable($options)) { $options = array('callback' => $options); } else { // BC with Symfony < 2.4 $options = array('methods' => $options); } } parent::__construct($options); } /** * {@inheritdoc} */ public function getDefaultOption() { return 'callback'; } /** * {@inheritdoc} */ public function getTargets() { return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class BlankValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Blank) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Blank'); } if ('' !== $value && null !== $value) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class IsFalse extends Constraint { public $message = 'This value should be false.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\RuntimeException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class EmailValidator extends ConstraintValidator { /** * @var bool */ private $isStrict; public function __construct($strict = false) { $this->isStrict = $strict; } /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Email) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Email'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if (null === $constraint->strict) { $constraint->strict = $this->isStrict; } if ($constraint->strict) { if (!class_exists('\Egulias\EmailValidator\EmailValidator')) { throw new RuntimeException('Strict email validation requires egulias/email-validator'); } $strictValidator = new \Egulias\EmailValidator\EmailValidator(); if (!$strictValidator->isValid($value, false, true)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Email::INVALID_FORMAT_ERROR) ->addViolation(); return; } } elseif (!preg_match('/^.+\@\S+\.\S+$/', $value)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Email::INVALID_FORMAT_ERROR) ->addViolation(); return; } $host = substr($value, strpos($value, '@') + 1); // Check for host DNS resource records if ($constraint->checkMX) { if (!$this->checkMX($host)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Email::MX_CHECK_FAILED_ERROR) ->addViolation(); } return; } if ($constraint->checkHost && !$this->checkHost($host)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Email::HOST_CHECK_FAILED_ERROR) ->addViolation(); } } /** * Check DNS Records for MX type. * * @param string $host Host * * @return bool */ private function checkMX($host) { return checkdnsrr($host, 'MX'); } /** * Check if one of MX, A or AAAA DNS RR exists. * * @param string $host Host * * @return bool */ private function checkHost($host) { return $this->checkMX($host) || (checkdnsrr($host, 'A') || checkdnsrr($host, 'AAAA')); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @author Bernhard Schussek * * @api */ class FalseValidator extends IsFalseValidator { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid image file and is valid * against minWidth, maxWidth, minHeight and maxHeight constraints. * * @author Benjamin Dulau * @author Bernhard Schussek */ class ImageValidator extends FileValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Image) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Image'); } $violations = count($this->context->getViolations()); parent::validate($value, $constraint); $failed = count($this->context->getViolations()) !== $violations; if ($failed || null === $value || '' === $value) { return; } if (null === $constraint->minWidth && null === $constraint->maxWidth && null === $constraint->minHeight && null === $constraint->maxHeight && null === $constraint->minRatio && null === $constraint->maxRatio && $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait) { return; } $size = @getimagesize($value); if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) { $this->buildViolation($constraint->sizeNotDetectedMessage) ->setCode(Image::SIZE_NOT_DETECTED_ERROR) ->addViolation(); return; } $width = $size[0]; $height = $size[1]; if ($constraint->minWidth) { if (!ctype_digit((string) $constraint->minWidth)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width', $constraint->minWidth)); } if ($width < $constraint->minWidth) { $this->buildViolation($constraint->minWidthMessage) ->setParameter('{{ width }}', $width) ->setParameter('{{ min_width }}', $constraint->minWidth) ->setCode(Image::TOO_NARROW_ERROR) ->addViolation(); return; } } if ($constraint->maxWidth) { if (!ctype_digit((string) $constraint->maxWidth)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width', $constraint->maxWidth)); } if ($width > $constraint->maxWidth) { $this->buildViolation($constraint->maxWidthMessage) ->setParameter('{{ width }}', $width) ->setParameter('{{ max_width }}', $constraint->maxWidth) ->setCode(Image::TOO_WIDE_ERROR) ->addViolation(); return; } } if ($constraint->minHeight) { if (!ctype_digit((string) $constraint->minHeight)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum height', $constraint->minHeight)); } if ($height < $constraint->minHeight) { $this->buildViolation($constraint->minHeightMessage) ->setParameter('{{ height }}', $height) ->setParameter('{{ min_height }}', $constraint->minHeight) ->setCode(Image::TOO_LOW_ERROR) ->addViolation(); return; } } if ($constraint->maxHeight) { if (!ctype_digit((string) $constraint->maxHeight)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum height', $constraint->maxHeight)); } if ($height > $constraint->maxHeight) { $this->buildViolation($constraint->maxHeightMessage) ->setParameter('{{ height }}', $height) ->setParameter('{{ max_height }}', $constraint->maxHeight) ->setCode(Image::TOO_HIGH_ERROR) ->addViolation(); } } $ratio = round($width / $height, 2); if (null !== $constraint->minRatio) { if (!is_numeric((string) $constraint->minRatio)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum ratio', $constraint->minRatio)); } if ($ratio < $constraint->minRatio) { $this->buildViolation($constraint->minRatioMessage) ->setParameter('{{ ratio }}', $ratio) ->setParameter('{{ min_ratio }}', $constraint->minRatio) ->setCode(Image::RATIO_TOO_SMALL_ERROR) ->addViolation(); } } if (null !== $constraint->maxRatio) { if (!is_numeric((string) $constraint->maxRatio)) { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum ratio', $constraint->maxRatio)); } if ($ratio > $constraint->maxRatio) { $this->buildViolation($constraint->maxRatioMessage) ->setParameter('{{ ratio }}', $ratio) ->setParameter('{{ max_ratio }}', $constraint->maxRatio) ->setCode(Image::RATIO_TOO_BIG_ERROR) ->addViolation(); } } if (!$constraint->allowSquare && $width == $height) { $this->buildViolation($constraint->allowSquareMessage) ->setParameter('{{ width }}', $width) ->setParameter('{{ height }}', $height) ->setCode(Image::SQUARE_NOT_ALLOWED_ERROR) ->addViolation(); } if (!$constraint->allowLandscape && $width > $height) { $this->buildViolation($constraint->allowLandscapeMessage) ->setParameter('{{ width }}', $width) ->setParameter('{{ height }}', $height) ->setCode(Image::LANDSCAPE_NOT_ALLOWED_ERROR) ->addViolation(); } if (!$constraint->allowPortrait && $width < $height) { $this->buildViolation($constraint->allowPortraitMessage) ->setParameter('{{ width }}', $width) ->setParameter('{{ height }}', $height) ->setCode(Image::PORTRAIT_NOT_ALLOWED_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether the value is a valid ISBN-10 or ISBN-13 * * @author The Whole Life To Learn * @author Manuel Reinhard * @author Bernhard Schussek * * @see https://en.wikipedia.org/wiki/Isbn */ class IsbnValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Isbn) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Isbn'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $canonical = str_replace('-', '', $value); if (null === $constraint->type) { if ($constraint->isbn10 && !$constraint->isbn13) { $constraint->type = 'isbn10'; } elseif ($constraint->isbn13 && !$constraint->isbn10) { $constraint->type = 'isbn13'; } } // Explicitly validate against ISBN-10 if ('isbn10' === $constraint->type) { if (true !== ($code = $this->validateIsbn10($canonical))) { $this->buildViolation($this->getMessage($constraint, $constraint->type)) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode($code) ->addViolation(); } return; } // Explicitly validate against ISBN-13 if ('isbn13' === $constraint->type) { if (true !== ($code = $this->validateIsbn13($canonical))) { $this->buildViolation($this->getMessage($constraint, $constraint->type)) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode($code) ->addViolation(); } return; } // Try both ISBNs // First, try ISBN-10 $code = $this->validateIsbn10($canonical); // The ISBN can only be an ISBN-13 if the value was too long for ISBN-10 if (Isbn::TOO_LONG_ERROR === $code) { // Try ISBN-13 now $code = $this->validateIsbn13($canonical); // If too short, this means we have 11 or 12 digits if (Isbn::TOO_SHORT_ERROR === $code) { $code = Isbn::TYPE_NOT_RECOGNIZED_ERROR; } } if (true !== $code) { $this->buildViolation($this->getMessage($constraint)) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode($code) ->addViolation(); } } protected function validateIsbn10($isbn) { // Choose an algorithm so that ERROR_INVALID_CHARACTERS is preferred // over ERROR_TOO_SHORT/ERROR_TOO_LONG // Otherwise "0-45122-5244" passes, but "0-45122_5244" reports // "too long" // Error priority: // 1. ERROR_INVALID_CHARACTERS // 2. ERROR_TOO_SHORT/ERROR_TOO_LONG // 3. ERROR_CHECKSUM_FAILED $checkSum = 0; for ($i = 0; $i < 10; ++$i) { // If we test the length before the loop, we get an ERROR_TOO_SHORT // when actually an ERROR_INVALID_CHARACTERS is wanted, e.g. for // "0-45122_5244" (typo) if (!isset($isbn{$i})) { return Isbn::TOO_SHORT_ERROR; } if ('X' === $isbn{$i}) { $digit = 10; } elseif (ctype_digit($isbn{$i})) { $digit = $isbn{$i}; } else { return Isbn::INVALID_CHARACTERS_ERROR; } $checkSum += $digit * (10 - $i); } if (isset($isbn{$i})) { return Isbn::TOO_LONG_ERROR; } return 0 === $checkSum % 11 ? true : Isbn::CHECKSUM_FAILED_ERROR; } protected function validateIsbn13($isbn) { // Error priority: // 1. ERROR_INVALID_CHARACTERS // 2. ERROR_TOO_SHORT/ERROR_TOO_LONG // 3. ERROR_CHECKSUM_FAILED if (!ctype_digit($isbn)) { return Isbn::INVALID_CHARACTERS_ERROR; } $length = strlen($isbn); if ($length < 13) { return Isbn::TOO_SHORT_ERROR; } if ($length > 13) { return Isbn::TOO_LONG_ERROR; } $checkSum = 0; for ($i = 0; $i < 13; $i += 2) { $checkSum += $isbn{$i}; } for ($i = 1; $i < 12; $i += 2) { $checkSum += $isbn{$i} * 3; } return 0 === $checkSum % 10 ? true : Isbn::CHECKSUM_FAILED_ERROR; } protected function getMessage($constraint, $type = null) { if (null !== $constraint->message) { return $constraint->message; } elseif ('isbn10' === $type) { return $constraint->isbn10Message; } elseif ('isbn13' === $type) { return $constraint->isbn13Message; } return $constraint->bothIsbnMessage; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates a PAN using the LUHN Algorithm. * * For a list of example card numbers that are used to test this * class, please see the LuhnValidatorTest class. * * @see http://en.wikipedia.org/wiki/Luhn_algorithm * * @author Tim Nagel * @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/ * @author Bernhard Schussek */ class LuhnValidator extends ConstraintValidator { /** * Validates a credit card number with the Luhn algorithm. * * @param mixed $value * @param Constraint $constraint * * @throws UnexpectedTypeException when the given credit card number is no string */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Luhn) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Luhn'); } if (null === $value || '' === $value) { return; } // Work with strings only, because long numbers are represented as floats // internally and don't work with strlen() if (!is_string($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if (!ctype_digit($value)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Luhn::INVALID_CHARACTERS_ERROR) ->addViolation(); return; } $checkSum = 0; $length = strlen($value); // Starting with the last digit and walking left, add every second // digit to the check sum // e.g. 7 9 9 2 7 3 9 8 7 1 3 // ^ ^ ^ ^ ^ ^ // = 7 + 9 + 7 + 9 + 7 + 3 for ($i = $length - 1; $i >= 0; $i -= 2) { $checkSum += $value{$i}; } // Starting with the second last digit and walking left, double every // second digit and add it to the check sum // For doubles greater than 9, sum the individual digits // e.g. 7 9 9 2 7 3 9 8 7 1 3 // ^ ^ ^ ^ ^ // = 1+8 + 4 + 6 + 1+6 + 2 for ($i = $length - 2; $i >= 0; $i -= 2) { $checkSum += array_sum(str_split($value{$i} * 2)); } if (0 === $checkSum || 0 !== $checkSum % 10) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Luhn::CHECKSUM_FAILED_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class TypeValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Type) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Type'); } if (null === $value) { return; } $type = strtolower($constraint->type); $type = $type == 'boolean' ? 'bool' : $constraint->type; $isFunction = 'is_'.$type; $ctypeFunction = 'ctype_'.$type; if (function_exists($isFunction) && $isFunction($value)) { return; } elseif (function_exists($ctypeFunction) && $ctypeFunction($value)) { return; } elseif ($value instanceof $constraint->type) { return; } $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setParameter('{{ type }}', $constraint->type) ->addViolation(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class CollectionValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Collection) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Collection'); } if (null === $value) { return; } if (!is_array($value) && !($value instanceof \Traversable && $value instanceof \ArrayAccess)) { throw new UnexpectedTypeException($value, 'array or Traversable and ArrayAccess'); } // We need to keep the initialized context when CollectionValidator // calls itself recursively (Collection constraints can be nested). // Since the context of the validator is overwritten when initialize() // is called for the nested constraint, the outer validator is // acting on the wrong context when the nested validation terminates. // // A better solution - which should be approached in Symfony 3.0 - is to // remove the initialize() method and pass the context as last argument // to validate() instead. $context = $this->context; foreach ($constraint->fields as $field => $fieldConstraint) { // bug fix issue #2779 $existsInArray = is_array($value) && array_key_exists($field, $value); $existsInArrayAccess = $value instanceof \ArrayAccess && $value->offsetExists($field); if ($existsInArray || $existsInArrayAccess) { if (count($fieldConstraint->constraints) > 0) { if ($context instanceof ExecutionContextInterface) { $context->getValidator() ->inContext($context) ->atPath('['.$field.']') ->validate($value[$field], $fieldConstraint->constraints); } else { // 2.4 API $context->validateValue($value[$field], $fieldConstraint->constraints, '['.$field.']'); } } } elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) { $this->buildViolationInContext($context, $constraint->missingFieldsMessage) ->atPath('['.$field.']') ->setParameter('{{ field }}', $this->formatValue($field)) ->setInvalidValue(null) ->setCode(Collection::MISSING_FIELD_ERROR) ->addViolation(); } } if (!$constraint->allowExtraFields) { foreach ($value as $field => $fieldValue) { if (!isset($constraint->fields[$field])) { $this->buildViolationInContext($context, $constraint->extraFieldsMessage) ->atPath('['.$field.']') ->setParameter('{{ field }}', $this->formatValue($field)) ->setInvalidValue($fieldValue) ->setCode(Collection::NO_SUCH_FIELD_ERROR) ->addViolation(); } } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class UrlValidator extends ConstraintValidator { const PATTERN = '~^ (%s):// # protocol (([\pL\pN-]+:)?([\pL\pN-]+)@)? # basic auth ( ([\pL\pN\pS-\.])+(\.?([\pL]|xn\-\-[\pL\pN-]+)+\.?) # a domain name | # or \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # a IP address | # or \[ (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::)))) \] # a IPv6 address ) (:[0-9]+)? # a port (optional) (/?|/\S+) # a /, nothing or a / with something $~ixu'; /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Url) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Url'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $pattern = sprintf(static::PATTERN, implode('|', $constraint->protocols)); if (!preg_match($pattern, $value)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are less than the previous (<). * * @author Daniel Holmes */ class LessThanValidator extends AbstractComparisonValidator { /** * {@inheritdoc} */ protected function compareValues($value1, $value2) { return $value1 < $value2; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Time extends Constraint { const INVALID_FORMAT_ERROR = 1; const INVALID_TIME_ERROR = 2; protected static $errorNames = array( self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR', self::INVALID_TIME_ERROR => 'INVALID_TIME_ERROR', ); public $message = 'This value is not a valid time.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * A constraint that is composed of other constraints. * * You should never use the nested constraint instances anywhere else, because * their groups are adapted when passed to the constructor of this class. * * If you want to create your own composite constraint, extend this class and * let {@link getCompositeOption()} return the name of the property which * contains the nested constraints. * * @since 2.6 * @author Bernhard Schussek */ abstract class Composite extends Constraint { /** * {@inheritdoc} * * The groups of the composite and its nested constraints are made * consistent using the following strategy: * * - If groups are passed explicitly to the composite constraint, but * not to the nested constraints, the options of the composite * constraint are copied to the nested constraints; * * - If groups are passed explicitly to the nested constraints, but not * to the composite constraint, the groups of all nested constraints * are merged and used as groups for the composite constraint; * * - If groups are passed explicitly to both the composite and its nested * constraints, the groups of the nested constraints must be a subset * of the groups of the composite constraint. If not, a * {@link ConstraintDefinitionException} is thrown. * * All this is done in the constructor, because constraints can then be * cached. When constraints are loaded from the cache, no more group * checks need to be done. */ public function __construct($options = null) { parent::__construct($options); $this->initializeNestedConstraints(); /** @var Constraint[] $nestedConstraints */ $compositeOption = $this->getCompositeOption(); $nestedConstraints = $this->$compositeOption; if (!is_array($nestedConstraints)) { $nestedConstraints = array($nestedConstraints); } foreach ($nestedConstraints as $constraint) { if (!$constraint instanceof Constraint) { throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, get_class($this))); } if ($constraint instanceof Valid) { throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', get_class($this))); } } if (!property_exists($this, 'groups')) { $mergedGroups = array(); foreach ($nestedConstraints as $constraint) { foreach ($constraint->groups as $group) { $mergedGroups[$group] = true; } } $this->groups = array_keys($mergedGroups); $this->$compositeOption = $nestedConstraints; return; } foreach ($nestedConstraints as $constraint) { if (property_exists($constraint, 'groups')) { $excessGroups = array_diff($constraint->groups, $this->groups); if (count($excessGroups) > 0) { throw new ConstraintDefinitionException(sprintf( 'The group(s) "%s" passed to the constraint %s '. 'should also be passed to its containing constraint %s', implode('", "', $excessGroups), get_class($constraint), get_class($this) )); } } else { $constraint->groups = $this->groups; } } $this->$compositeOption = $nestedConstraints; } /** * {@inheritdoc} * * Implicit group names are forwarded to nested constraints. * * @param string $group */ public function addImplicitGroupName($group) { parent::addImplicitGroupName($group); /** @var Constraint[] $nestedConstraints */ $nestedConstraints = $this->{$this->getCompositeOption()}; foreach ($nestedConstraints as $constraint) { $constraint->addImplicitGroupName($group); } } /** * Returns the name of the property that contains the nested constraints. * * @return string The property name */ abstract protected function getCompositeOption(); /** * Initializes the nested constraints. * * This method can be overwritten in subclasses to clean up the nested * constraints passed to the constructor. * * @see Collection::initializeNestedConstraints() */ protected function initializeNestedConstraints() { } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class IsTrue extends Constraint { public $message = 'This value should be true.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are greater than or equal to the previous (>=). * * @author Daniel Holmes */ class GreaterThanOrEqualValidator extends AbstractComparisonValidator { /** * {@inheritdoc} */ protected function compareValues($value1, $value2) { return $value1 >= $value2; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class IsNullValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof IsNull) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\IsNull'); } if (null !== $value) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Choice extends Constraint { const NO_SUCH_CHOICE_ERROR = 1; const TOO_FEW_ERROR = 2; const TOO_MANY_ERROR = 3; protected static $errorNames = array( self::NO_SUCH_CHOICE_ERROR => 'NO_SUCH_CHOICE_ERROR', self::TOO_FEW_ERROR => 'TOO_FEW_ERROR', self::TOO_MANY_ERROR => 'TOO_MANY_ERROR', ); public $choices; public $callback; public $multiple = false; public $strict = false; public $min; public $max; public $message = 'The value you selected is not a valid choice.'; public $multipleMessage = 'One or more of the given values is invalid.'; public $minMessage = 'You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.'; public $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.'; /** * {@inheritdoc} */ public function getDefaultOption() { return 'choices'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ class LengthValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Length) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Length'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $stringValue = (string) $value; $invalidCharset = false; if ('UTF8' === $charset = strtoupper($constraint->charset)) { $charset = 'UTF-8'; } if (function_exists('iconv_strlen')) { $length = @iconv_strlen($stringValue, $constraint->charset); $invalidCharset = false === $length; } elseif (function_exists('mb_strlen')) { if (mb_check_encoding($stringValue, $constraint->charset)) { $length = mb_strlen($stringValue, $constraint->charset); } else { $invalidCharset = true; } } elseif ('UTF-8' !== $charset) { $length = strlen($stringValue); } elseif (!preg_match('//u', $stringValue)) { $invalidCharset = true; } elseif (function_exists('utf8_decode')) { $length = strlen(utf8_decode($stringValue)); } else { preg_replace('/./u', '', $stringValue, -1, $length); } if ($invalidCharset) { $this->buildViolation($constraint->charsetMessage) ->setParameter('{{ value }}', $this->formatValue($stringValue)) ->setParameter('{{ charset }}', $constraint->charset) ->setInvalidValue($value) ->addViolation(); return; } if (null !== $constraint->max && $length > $constraint->max) { $this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage) ->setParameter('{{ value }}', $this->formatValue($stringValue)) ->setParameter('{{ limit }}', $constraint->max) ->setInvalidValue($value) ->setPlural((int) $constraint->max) ->setCode(Length::TOO_LONG_ERROR) ->addViolation(); return; } if (null !== $constraint->min && $length < $constraint->min) { $this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage) ->setParameter('{{ value }}', $this->formatValue($stringValue)) ->setParameter('{{ limit }}', $constraint->min) ->setInvalidValue($value) ->setPlural((int) $constraint->min) ->setCode(Length::TOO_SHORT_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class NotBlank extends Constraint { public $message = 'This value should not be blank.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ class CountValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (null === $value) { return; } if (!is_array($value) && !$value instanceof \Countable) { throw new UnexpectedTypeException($value, 'array or \Countable'); } $count = count($value); if (null !== $constraint->max && $count > $constraint->max) { $this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->maxMessage) ->setParameter('{{ count }}', $count) ->setParameter('{{ limit }}', $constraint->max) ->setInvalidValue($value) ->setPlural((int) $constraint->max) ->setCode(Count::TOO_MANY_ERROR) ->addViolation(); return; } if (null !== $constraint->min && $count < $constraint->min) { $this->buildViolation($constraint->min == $constraint->max ? $constraint->exactMessage : $constraint->minMessage) ->setParameter('{{ count }}', $count) ->setParameter('{{ limit }}', $constraint->min) ->setInvalidValue($value) ->setPlural((int) $constraint->min) ->setCode(Count::TOO_FEW_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Exception\OutOfBoundsException; /** * A sequence of validation groups. * * When validating a group sequence, each group will only be validated if all * of the previous groups in the sequence succeeded. For example: * * $validator->validate($address, null, new GroupSequence('Basic', 'Strict')); * * In the first step, all constraints that belong to the group "Basic" will be * validated. If none of the constraints fail, the validator will then validate * the constraints in group "Strict". This is useful, for example, if "Strict" * contains expensive checks that require a lot of CPU or slow, external * services. You usually don't want to run expensive checks if any of the cheap * checks fail. * * When adding metadata to a class, you can override the "Default" group of * that class with a group sequence: * * /** * * @GroupSequence({"Address", "Strict"}) * *\/ * class Address * { * // ... * } * * Whenever you validate that object in the "Default" group, the group sequence * will be validated: * * $validator->validate($address); * * If you want to execute the constraints of the "Default" group for a class * with an overridden default group, pass the class name as group name instead: * * $validator->validate($address, null, "Address") * * @Annotation * @Target({"CLASS", "ANNOTATION"}) * * @author Bernhard Schussek * * @api * * Implementing \ArrayAccess, \IteratorAggregate and \Countable is @deprecated since 2.5 and will be removed in 3.0. */ class GroupSequence implements \ArrayAccess, \IteratorAggregate, \Countable { /** * The groups in the sequence. * * @var string[]|GroupSequence[] */ public $groups; /** * The group in which cascaded objects are validated when validating * this sequence. * * By default, cascaded objects are validated in each of the groups of * the sequence. * * If a class has a group sequence attached, that sequence replaces the * "Default" group. When validating that class in the "Default" group, the * group sequence is used instead, but still the "Default" group should be * cascaded to other objects. * * @var string|GroupSequence */ public $cascadedGroup; /** * Creates a new group sequence. * * @param string[] $groups The groups in the sequence */ public function __construct(array $groups) { // Support for Doctrine annotations $this->groups = isset($groups['value']) ? $groups['value'] : $groups; } /** * Returns an iterator for this group. * * @return \Traversable The iterator * * @see \IteratorAggregate::getIterator() * * @deprecated Implemented for backwards compatibility with Symfony < 2.5. * To be removed in Symfony 3.0. */ public function getIterator() { return new \ArrayIterator($this->groups); } /** * Returns whether the given offset exists in the sequence. * * @param int $offset The offset * * @return bool Whether the offset exists * * @deprecated Implemented for backwards compatibility with Symfony < 2.5. * To be removed in Symfony 3.0. */ public function offsetExists($offset) { return isset($this->groups[$offset]); } /** * Returns the group at the given offset. * * @param int $offset The offset * * @return string The group a the given offset * * @throws OutOfBoundsException If the object does not exist * * @deprecated Implemented for backwards compatibility with Symfony < 2.5. * To be removed in Symfony 3.0. */ public function offsetGet($offset) { if (!isset($this->groups[$offset])) { throw new OutOfBoundsException(sprintf( 'The offset "%s" does not exist.', $offset )); } return $this->groups[$offset]; } /** * Sets the group at the given offset. * * @param int $offset The offset * @param string $value The group name * * @deprecated Implemented for backwards compatibility with Symfony < 2.5. * To be removed in Symfony 3.0. */ public function offsetSet($offset, $value) { if (null !== $offset) { $this->groups[$offset] = $value; return; } $this->groups[] = $value; } /** * Removes the group at the given offset. * * @param int $offset The offset * * @deprecated Implemented for backwards compatibility with Symfony < 2.5. * To be removed in Symfony 3.0. */ public function offsetUnset($offset) { unset($this->groups[$offset]); } /** * Returns the number of groups in the sequence. * * @return int The number of groups * * @deprecated Implemented for backwards compatibility with Symfony < 2.5. * To be removed in Symfony 3.0. */ public function count() { return count($this->groups); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid currency. * * @author Miha Vrhovnik * * @api */ class CurrencyValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Currency) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Currency'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $currencies = Intl::getCurrencyBundle()->getCurrencyNames(); if (!isset($currencies[$value])) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Required as BaseRequired; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Validator\Constraints\Required} instead. */ class Required extends BaseRequired { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Optional as BaseOptional; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @deprecated Deprecated in 2.3, to be removed in 3.0. Use * {@link \Symfony\Component\Validator\Constraints\Optional} instead. */ class Optional extends BaseOptional { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Locale extends Constraint { public $message = 'This value is not a valid locale.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values aren't identical (!==). * * @author Daniel Holmes */ class NotIdenticalToValidator extends AbstractComparisonValidator { /** * {@inheritdoc} */ protected function compareValues($value1, $value2) { return $value1 !== $value2; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Daniel Holmes */ class GreaterThanOrEqual extends AbstractComparison { public $message = 'This value should be greater than or equal to {{ compared_value }}.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @author Bernhard Schussek * * @api */ class TrueValidator extends IsTrueValidator { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class All extends Composite { public $constraints = array(); public function getDefaultOption() { return 'constraints'; } public function getRequiredOptions() { return array('constraints'); } protected function getCompositeOption() { return 'constraints'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class NotBlankValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof NotBlank) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\NotBlank'); } if (false === $value || (empty($value) && '0' != $value)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Annotation to define a group sequence provider. * * @Annotation * @Target({"CLASS", "ANNOTATION"}) */ class GroupSequenceProvider { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Length extends Constraint { const TOO_SHORT_ERROR = 1; const TOO_LONG_ERROR = 2; protected static $errorNames = array( self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR', self::TOO_LONG_ERROR => 'TOO_LONG_ERROR', ); public $maxMessage = 'This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.'; public $minMessage = 'This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.'; public $exactMessage = 'This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.'; public $charsetMessage = 'This value does not match the expected {{ charset }} charset.'; public $max; public $min; public $charset = 'UTF-8'; public function __construct($options = null) { if (null !== $options && !is_array($options)) { $options = array( 'min' => $options, 'max' => $options, ); } parent::__construct($options); if (null === $this->min && null === $this->max) { throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max')); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Country extends Constraint { public $message = 'This value is not a valid country.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Valid extends Constraint { public $traverse = true; /** * @deprecated Deprecated as of version 2.5, to be removed in Symfony 3.0. */ public $deep = true; public function __construct($options = null) { if (is_array($options) && array_key_exists('groups', $options)) { throw new ConstraintDefinitionException(sprintf( 'The option "groups" is not supported by the constraint %s', __CLASS__ )); } parent::__construct($options); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Type extends Constraint { public $message = 'This value should be of type {{ type }}.'; public $type; /** * {@inheritdoc} */ public function getDefaultOption() { return 'type'; } /** * {@inheritdoc} */ public function getRequiredOptions() { return array('type'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value match or not given regexp pattern. * * @author Bernhard Schussek * @author Joseph Bielawski * * @api */ class RegexValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Regex) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Regex'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if ($constraint->match xor preg_match($constraint->pattern, $value)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Antonio J. García Lagar * @author Bernhard Schussek */ class Issn extends Constraint { const TOO_SHORT_ERROR = 1; const TOO_LONG_ERROR = 2; const MISSING_HYPHEN_ERROR = 3; const INVALID_CHARACTERS_ERROR = 4; const INVALID_CASE_ERROR = 5; const CHECKSUM_FAILED_ERROR = 6; protected static $errorNames = array( self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR', self::TOO_LONG_ERROR => 'TOO_LONG_ERROR', self::MISSING_HYPHEN_ERROR => 'MISSING_HYPHEN_ERROR', self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR', self::INVALID_CASE_ERROR => 'INVALID_CASE_ERROR', self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR', ); public $message = 'This value is not a valid ISSN.'; public $caseSensitive = false; public $requireHyphen = false; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Daniel Holmes */ class EqualTo extends AbstractComparison { public $message = 'This value should be equal to {{ compared_value }}.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether the value is a valid UUID per RFC 4122. * * @author Colin O'Dell * @author Bernhard Schussek * * @see http://tools.ietf.org/html/rfc4122 * @see https://en.wikipedia.org/wiki/Universally_unique_identifier */ class UuidValidator extends ConstraintValidator { // The strict pattern matches UUIDs like this: // xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx // Roughly speaking: // x = any hexadecimal character // M = any allowed version {1..5} // N = any allowed variant {8, 9, a, b} const STRICT_LENGTH = 36; const STRICT_FIRST_HYPHEN_POSITION = 8; const STRICT_LAST_HYPHEN_POSITION = 23; const STRICT_VERSION_POSITION = 14; const STRICT_VARIANT_POSITION = 19; // The loose pattern validates similar yet non-compliant UUIDs. // Hyphens are completely optional. If present, they should only appear // between every fourth character: // xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx // xxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxx // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // The value can also be wrapped with characters like []{}: // {xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx} // Neither the version nor the variant is validated by this pattern. const LOOSE_MAX_LENGTH = 39; const LOOSE_FIRST_HYPHEN_POSITION = 4; /** * @deprecated Deprecated since Symfony 2.6, to be removed in 3.0 */ const STRICT_PATTERN = '/^[a-f0-9]{8}-[a-f0-9]{4}-[%s][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i'; /** * @deprecated Deprecated since Symfony 2.6, to be removed in 3.0 */ const LOOSE_PATTERN = '/^[a-f0-9]{4}(?:-?[a-f0-9]{4}){7}$/i'; /** * @deprecated Deprecated since Symfony 2.6, to be removed in 3.0 */ const STRICT_UUID_LENGTH = self::STRICT_LENGTH; /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if ($constraint->strict) { $this->validateStrict($value, $constraint); return; } $this->validateLoose($value, $constraint); } private function validateLoose($value, Uuid $constraint) { // Error priority: // 1. ERROR_INVALID_CHARACTERS // 2. ERROR_INVALID_HYPHEN_PLACEMENT // 3. ERROR_TOO_SHORT/ERROR_TOO_LONG // Trim any wrapping characters like [] or {} used by some legacy systems $trimmed = trim($value, '[]{}'); // Position of the next expected hyphen $h = self::LOOSE_FIRST_HYPHEN_POSITION; // Expected length $l = self::LOOSE_MAX_LENGTH; for ($i = 0; $i < $l; ++$i) { // Check length if (!isset($trimmed{$i})) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Uuid::TOO_SHORT_ERROR) ->addViolation(); return; } // Hyphens must occur every fifth position // xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx // ^ ^ ^ ^ ^ ^ ^ if ('-' === $trimmed{$i}) { if ($i !== $h) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR) ->addViolation(); return; } $h += 5; continue; } // Missing hyphens are ignored if ($i === $h) { $h += 4; --$l; } // Check characters if (!ctype_xdigit($trimmed{$i})) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Uuid::INVALID_CHARACTERS_ERROR) ->addViolation(); return; } } // Check length again if (isset($trimmed{$i})) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Uuid::TOO_LONG_ERROR) ->addViolation(); } } private function validateStrict($value, Uuid $constraint) { // Error priority: // 1. ERROR_INVALID_CHARACTERS // 2. ERROR_INVALID_HYPHEN_PLACEMENT // 3. ERROR_TOO_SHORT/ERROR_TOO_LONG // 4. ERROR_INVALID_VERSION // 5. ERROR_INVALID_VARIANT // Position of the next expected hyphen $h = self::STRICT_FIRST_HYPHEN_POSITION; for ($i = 0; $i < self::STRICT_LENGTH; ++$i) { // Check length if (!isset($value{$i})) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Uuid::TOO_SHORT_ERROR) ->addViolation(); return; } // Check hyphen placement // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx // ^ ^ ^ ^ if ('-' === $value{$i}) { if ($i !== $h) { $this->buildViolation($constraint->message) ->setParameter( '{{ value }}', $this->formatValue($value) ) ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR) ->addViolation(); return; } // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx // ^ if ($h < self::STRICT_LAST_HYPHEN_POSITION) { $h += 5; } continue; } // Check characters if (!ctype_xdigit($value{$i})) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Uuid::INVALID_CHARACTERS_ERROR) ->addViolation(); return; } // Missing hyphen if ($i === $h) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Uuid::INVALID_HYPHEN_PLACEMENT_ERROR) ->addViolation(); return; } } // Check length again if (isset($value{$i})) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Uuid::TOO_LONG_ERROR) ->addViolation(); } // Check version if (!in_array($value{self::STRICT_VERSION_POSITION}, $constraint->versions)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Uuid::INVALID_VERSION_ERROR) ->addViolation(); } // Check variant - first two bits must equal "10" // 0b10xx // & 0b1100 (12) // = 0b1000 (8) if ((hexdec($value{self::STRICT_VARIANT_POSITION}) & 12) !== 8) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Uuid::INVALID_VARIANT_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Provides a base class for the validation of property comparisons. * * @author Daniel Holmes * @author Bernhard Schussek */ abstract class AbstractComparisonValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof AbstractComparison) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\AbstractComparison'); } if (null === $value) { return; } $comparedValue = $constraint->value; // Convert strings to DateTimes if comparing another DateTime // This allows to compare with any date/time value supported by // the DateTime constructor: // http://php.net/manual/en/datetime.formats.php if (is_string($comparedValue)) { if ($value instanceof \DatetimeImmutable) { // If $value is immutable, convert the compared value to a // DateTimeImmutable too $comparedValue = new \DatetimeImmutable($comparedValue); } elseif ($value instanceof \DateTime || $value instanceof \DateTimeInterface) { // Otherwise use DateTime $comparedValue = new \DateTime($comparedValue); } } if (!$this->compareValues($value, $comparedValue)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value, self::OBJECT_TO_STRING | self::PRETTY_DATE)) ->setParameter('{{ compared_value }}', $this->formatValue($comparedValue, self::OBJECT_TO_STRING | self::PRETTY_DATE)) ->setParameter('{{ compared_value_type }}', $this->formatTypeOf($comparedValue)) ->addViolation(); } } /** * Compares the two given values to find if their relationship is valid. * * @param mixed $value1 The first value to compare * @param mixed $value2 The second value to compare * * @return bool true if the relationship is valid, false otherwise */ abstract protected function compareValues($value1, $value2); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Range extends Constraint { const INVALID_VALUE_ERROR = 1; const BEYOND_RANGE_ERROR = 2; const BELOW_RANGE_ERROR = 3; protected static $errorNames = array( self::INVALID_VALUE_ERROR => 'INVALID_VALUE_ERROR', self::BEYOND_RANGE_ERROR => 'BEYOND_RANGE_ERROR', self::BELOW_RANGE_ERROR => 'BELOW_RANGE_ERROR', ); public $minMessage = 'This value should be {{ limit }} or more.'; public $maxMessage = 'This value should be {{ limit }} or less.'; public $invalidMessage = 'This value should be a valid number.'; public $min; public $max; public function __construct($options = null) { parent::__construct($options); if (null === $this->min && null === $this->max) { throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max')); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are less than or equal to the previous (<=). * * @author Daniel Holmes */ class LessThanOrEqualValidator extends AbstractComparisonValidator { /** * {@inheritdoc} */ protected function compareValues($value1, $value2) { return $value1 <= $value2; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class IsTrueValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof IsTrue) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\IsTrue'); } if (null === $value) { return; } if (true !== $value && 1 !== $value && '1' !== $value) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Benjamin Dulau * @author Bernhard Schussek * * @api */ class Image extends File { // Don't reuse values used in File const SIZE_NOT_DETECTED_ERROR = 10; const TOO_WIDE_ERROR = 11; const TOO_NARROW_ERROR = 12; const TOO_HIGH_ERROR = 13; const TOO_LOW_ERROR = 14; const RATIO_TOO_BIG_ERROR = 15; const RATIO_TOO_SMALL_ERROR = 16; const SQUARE_NOT_ALLOWED_ERROR = 17; const LANDSCAPE_NOT_ALLOWED_ERROR = 18; const PORTRAIT_NOT_ALLOWED_ERROR = 19; // Include the mapping from the base class protected static $errorNames = array( self::NOT_FOUND_ERROR => 'NOT_FOUND_ERROR', self::NOT_READABLE_ERROR => 'NOT_READABLE_ERROR', self::EMPTY_ERROR => 'EMPTY_ERROR', self::TOO_LARGE_ERROR => 'TOO_LARGE_ERROR', self::INVALID_MIME_TYPE_ERROR => 'INVALID_MIME_TYPE_ERROR', self::SIZE_NOT_DETECTED_ERROR => 'SIZE_NOT_DETECTED_ERROR', self::TOO_WIDE_ERROR => 'TOO_WIDE_ERROR', self::TOO_NARROW_ERROR => 'TOO_NARROW_ERROR', self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR', self::TOO_LOW_ERROR => 'TOO_LOW_ERROR', self::RATIO_TOO_BIG_ERROR => 'RATIO_TOO_BIG_ERROR', self::RATIO_TOO_SMALL_ERROR => 'RATIO_TOO_SMALL_ERROR', self::SQUARE_NOT_ALLOWED_ERROR => 'SQUARE_NOT_ALLOWED_ERROR', self::LANDSCAPE_NOT_ALLOWED_ERROR => 'LANDSCAPE_NOT_ALLOWED_ERROR', self::PORTRAIT_NOT_ALLOWED_ERROR => 'PORTRAIT_NOT_ALLOWED_ERROR', ); public $mimeTypes = 'image/*'; public $minWidth; public $maxWidth; public $maxHeight; public $minHeight; public $maxRatio; public $minRatio; public $allowSquare = true; public $allowLandscape = true; public $allowPortrait = true; // The constant for a wrong MIME type is taken from the parent class. public $mimeTypesMessage = 'This file is not a valid image.'; public $sizeNotDetectedMessage = 'The size of the image could not be detected.'; public $maxWidthMessage = 'The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.'; public $minWidthMessage = 'The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.'; public $maxHeightMessage = 'The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.'; public $minHeightMessage = 'The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.'; public $maxRatioMessage = 'The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.'; public $minRatioMessage = 'The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.'; public $allowSquareMessage = 'The image is square ({{ width }}x{{ height }}px). Square images are not allowed.'; public $allowLandscapeMessage = 'The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.'; public $allowPortraitMessage = 'The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Url extends Constraint { public $message = 'This value is not a valid URL.'; public $protocols = array('http', 'https'); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Daniel Holmes */ class GreaterThan extends AbstractComparison { public $message = 'This value should be greater than {{ compared_value }}.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class False extends IsFalse { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Used for the comparison of values. * * @author Daniel Holmes */ abstract class AbstractComparison extends Constraint { public $message; public $value; /** * {@inheritdoc} */ public function __construct($options = null) { if (is_array($options) && !isset($options['value'])) { throw new ConstraintDefinitionException(sprintf( 'The %s constraint requires the "value" option to be set.', get_class($this) )); } parent::__construct($options); } /** * {@inheritdoc} */ public function getDefaultOption() { return 'value'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are greater than the previous (>). * * @author Daniel Holmes */ class GreaterThanValidator extends AbstractComparisonValidator { /** * {@inheritdoc} */ protected function compareValues($value1, $value2) { return $value1 > $value2; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are all unequal (!=). * * @author Daniel Holmes */ class NotEqualToValidator extends AbstractComparisonValidator { /** * {@inheritdoc} */ protected function compareValues($value1, $value2) { return $value1 != $value2; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Daniel Holmes */ class IdenticalTo extends AbstractComparison { public $message = 'This value should be identical to {{ compared_value_type }} {{ compared_value }}.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class File extends Constraint { // Check the Image constraint for clashes if adding new constants here const NOT_FOUND_ERROR = 1; const NOT_READABLE_ERROR = 2; const EMPTY_ERROR = 3; const TOO_LARGE_ERROR = 4; const INVALID_MIME_TYPE_ERROR = 5; protected static $errorNames = array( self::NOT_FOUND_ERROR => 'NOT_FOUND_ERROR', self::NOT_READABLE_ERROR => 'NOT_READABLE_ERROR', self::EMPTY_ERROR => 'EMPTY_ERROR', self::TOO_LARGE_ERROR => 'TOO_LARGE_ERROR', self::INVALID_MIME_TYPE_ERROR => 'INVALID_MIME_TYPE_ERROR', ); public $binaryFormat; public $mimeTypes = array(); public $notFoundMessage = 'The file could not be found.'; public $notReadableMessage = 'The file is not readable.'; public $maxSizeMessage = 'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.'; public $mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.'; public $disallowEmptyMessage = 'An empty file is not allowed.'; public $uploadIniSizeErrorMessage = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.'; public $uploadFormSizeErrorMessage = 'The file is too large.'; public $uploadPartialErrorMessage = 'The file was only partially uploaded.'; public $uploadNoFileErrorMessage = 'No file was uploaded.'; public $uploadNoTmpDirErrorMessage = 'No temporary folder was configured in php.ini.'; public $uploadCantWriteErrorMessage = 'Cannot write temporary file to disk.'; public $uploadExtensionErrorMessage = 'A PHP extension caused the upload to fail.'; public $uploadErrorMessage = 'The file could not be uploaded.'; protected $maxSize; public function __construct($options = null) { parent::__construct($options); if (null !== $this->maxSize) { $this->normalizeBinaryFormat($this->maxSize); } } public function __set($option, $value) { if ('maxSize' === $option) { $this->normalizeBinaryFormat($value); return; } parent::__set($option, $value); } public function __get($option) { if ('maxSize' === $option) { return $this->maxSize; } return parent::__get($option); } private function normalizeBinaryFormat($maxSize) { if (ctype_digit((string) $maxSize)) { $this->maxSize = (int) $maxSize; $this->binaryFormat = null === $this->binaryFormat ? false : $this->binaryFormat; } elseif (preg_match('/^\d++k$/i', $maxSize)) { $this->maxSize = $maxSize * 1000; $this->binaryFormat = null === $this->binaryFormat ? false : $this->binaryFormat; } elseif (preg_match('/^\d++M$/i', $maxSize)) { $this->maxSize = $maxSize * 1000000; $this->binaryFormat = null === $this->binaryFormat ? false : $this->binaryFormat; } elseif (preg_match('/^\d++Ki$/i', $maxSize)) { $this->maxSize = $maxSize << 10; $this->binaryFormat = null === $this->binaryFormat ? true : $this->binaryFormat; } elseif (preg_match('/^\d++Mi$/i', $maxSize)) { $this->maxSize = $maxSize << 20; $this->binaryFormat = null === $this->binaryFormat ? true : $this->binaryFormat; } else { throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $this->maxSize)); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * * @author Colin O'Dell * @author Bernhard Schussek */ class Uuid extends Constraint { const TOO_SHORT_ERROR = 1; const TOO_LONG_ERROR = 2; const INVALID_CHARACTERS_ERROR = 3; const INVALID_HYPHEN_PLACEMENT_ERROR = 4; const INVALID_VERSION_ERROR = 5; const INVALID_VARIANT_ERROR = 6; protected static $errorNames = array( self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR', self::TOO_LONG_ERROR => 'TOO_LONG_ERROR', self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR', self::INVALID_HYPHEN_PLACEMENT_ERROR => 'INVALID_HYPHEN_PLACEMENT_ERROR', self::INVALID_VERSION_ERROR => 'INVALID_VERSION_ERROR', self::INVALID_VARIANT_ERROR => 'INVALID_VARIANT_ERROR', ); // Possible versions defined by RFC 4122 const V1_MAC = 1; const V2_DCE = 2; const V3_MD5 = 3; const V4_RANDOM = 4; const V5_SHA1 = 5; /** * Message to display when validation fails * * @var string */ public $message = 'This is not a valid UUID.'; /** * Strict mode only allows UUIDs that meet the formal definition and formatting per RFC 4122 * * Set this to `false` to allow legacy formats with different dash positioning or wrapping characters * * @var bool */ public $strict = true; /** * Array of allowed versions (see version constants above) * * All UUID versions are allowed by default * * @var int[] */ public $versions = array( self::V1_MAC, self::V2_DCE, self::V3_MD5, self::V4_RANDOM, self::V5_SHA1, ); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @author Bernhard Schussek */ abstract class Existence extends Composite { public $constraints = array(); public function getDefaultOption() { return 'constraints'; } protected function getCompositeOption() { return 'constraints'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class IsFalseValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof IsFalse) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\IsFalse'); } if (null === $value || false === $value || 0 === $value || '0' === $value) { return; } $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are identical (===). * * @author Daniel Holmes */ class IdenticalToValidator extends AbstractComparisonValidator { /** * {@inheritdoc} */ protected function compareValues($value1, $value2) { return $value1 === $value2; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * Validates that a value is a valid IP address. * * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * @author Joseph Bielawski * * @api */ class Ip extends Constraint { const V4 = '4'; const V6 = '6'; const ALL = 'all'; // adds FILTER_FLAG_NO_PRIV_RANGE flag (skip private ranges) const V4_NO_PRIV = '4_no_priv'; const V6_NO_PRIV = '6_no_priv'; const ALL_NO_PRIV = 'all_no_priv'; // adds FILTER_FLAG_NO_RES_RANGE flag (skip reserved ranges) const V4_NO_RES = '4_no_res'; const V6_NO_RES = '6_no_res'; const ALL_NO_RES = 'all_no_res'; // adds FILTER_FLAG_NO_PRIV_RANGE and FILTER_FLAG_NO_RES_RANGE flags (skip both) const V4_ONLY_PUBLIC = '4_public'; const V6_ONLY_PUBLIC = '6_public'; const ALL_ONLY_PUBLIC = 'all_public'; protected static $versions = array( self::V4, self::V6, self::ALL, self::V4_NO_PRIV, self::V6_NO_PRIV, self::ALL_NO_PRIV, self::V4_NO_RES, self::V6_NO_RES, self::ALL_NO_RES, self::V4_ONLY_PUBLIC, self::V6_ONLY_PUBLIC, self::ALL_ONLY_PUBLIC, ); public $version = self::V4; public $message = 'This is not a valid IP address.'; /** * {@inheritdoc} */ public function __construct($options = null) { parent::__construct($options); if (!in_array($this->version, self::$versions)) { throw new ConstraintDefinitionException(sprintf('The option "version" must be one of "%s"', implode('", "', self::$versions))); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * Validates values are equal (==). * * @author Daniel Holmes */ class EqualToValidator extends AbstractComparisonValidator { /** * {@inheritdoc} */ protected function compareValues($value1, $value2) { return $value1 == $value2; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class NotNull extends Constraint { public $message = 'This value should not be null.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Null extends IsNull { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Daniel Holmes */ class NotIdenticalTo extends AbstractComparison { public $message = 'This value should not be identical to {{ compared_value_type }} {{ compared_value }}.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class AllValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof All) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\All'); } if (null === $value) { return; } if (!is_array($value) && !$value instanceof \Traversable) { throw new UnexpectedTypeException($value, 'array or Traversable'); } $context = $this->context; if ($context instanceof ExecutionContextInterface) { $validator = $context->getValidator()->inContext($context); foreach ($value as $key => $element) { $validator->atPath('['.$key.']')->validate($element, $constraint->constraints); } } else { // 2.4 API foreach ($value as $key => $element) { $context->validateValue($element, $constraint->constraints, '['.$key.']'); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validator for Callback constraint. * * @author Bernhard Schussek * * @api */ class CallbackValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($object, Constraint $constraint) { if (!$constraint instanceof Callback) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Callback'); } if (null !== $constraint->callback && null !== $constraint->methods) { throw new ConstraintDefinitionException( 'The Callback constraint supports either the option "callback" '. 'or "methods", but not both at the same time.' ); } // has to be an array so that we can differentiate between callables // and method names if (null !== $constraint->methods && !is_array($constraint->methods)) { throw new UnexpectedTypeException($constraint->methods, 'array'); } $methods = $constraint->methods ?: array($constraint->callback); foreach ($methods as $method) { if ($method instanceof \Closure) { $method($object, $this->context); } elseif (is_array($method)) { if (!is_callable($method)) { throw new ConstraintDefinitionException(sprintf('"%s::%s" targeted by Callback constraint is not a valid callable', $method[0], $method[1])); } call_user_func($method, $object, $this->context); } elseif (null !== $object) { if (!method_exists($object, $method)) { throw new ConstraintDefinitionException(sprintf('Method "%s" targeted by Callback constraint does not exist', $method)); } $reflMethod = new \ReflectionMethod($object, $method); if ($reflMethod->isStatic()) { $reflMethod->invoke(null, $object, $this->context); } else { $reflMethod->invoke($object, $this->context); } } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid country code. * * @author Bernhard Schussek * * @api */ class CountryValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Country) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Country'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $countries = Intl::getRegionBundle()->getCountryNames(); if (!isset($countries[$value])) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Daniel Holmes */ class LessThan extends AbstractComparison { public $message = 'This value should be less than {{ compared_value }}.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether the value is a valid ISSN. * * @author Antonio J. García Lagar * @author Bernhard Schussek * * @see https://en.wikipedia.org/wiki/Issn */ class IssnValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Issn) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Issn'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $canonical = $value; // 1234-567X // ^ if (isset($canonical{4}) && '-' === $canonical{4}) { // remove hyphen $canonical = substr($canonical, 0, 4).substr($canonical, 5); } elseif ($constraint->requireHyphen) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Issn::MISSING_HYPHEN_ERROR) ->addViolation(); return; } $length = strlen($canonical); if ($length < 8) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Issn::TOO_SHORT_ERROR) ->addViolation(); return; } if ($length > 8) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Issn::TOO_LONG_ERROR) ->addViolation(); return; } // 1234567X // ^^^^^^^ digits only if (!ctype_digit(substr($canonical, 0, 7))) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Issn::INVALID_CHARACTERS_ERROR) ->addViolation(); return; } // 1234567X // ^ digit, x or X if (!ctype_digit($canonical{7}) && 'x' !== $canonical{7} && 'X' !== $canonical{7}) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Issn::INVALID_CHARACTERS_ERROR) ->addViolation(); return; } // 1234567X // ^ case-sensitive? if ($constraint->caseSensitive && 'x' === $canonical{7}) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Issn::INVALID_CASE_ERROR) ->addViolation(); return; } // Calculate a checksum. "X" equals 10. $checkSum = 'X' === $canonical{7} || 'x' === $canonical{7} ? 10 : $canonical{7}; for ($i = 0; $i < 7; ++$i) { // Multiply the first digit by 8, the second by 7, etc. $checkSum += (8 - $i) * $canonical{$i}; } if (0 !== $checkSum % 11) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Issn::CHECKSUM_FAILED_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Count extends Constraint { const TOO_FEW_ERROR = 1; const TOO_MANY_ERROR = 2; protected static $errorNames = array( self::TOO_FEW_ERROR => 'TOO_FEW_ERROR', self::TOO_MANY_ERROR => 'TOO_MANY_ERROR', ); public $minMessage = 'This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.'; public $maxMessage = 'This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.'; public $exactMessage = 'This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.'; public $min; public $max; public function __construct($options = null) { if (null !== $options && !is_array($options)) { $options = array( 'min' => $options, 'max' => $options, ); } parent::__construct($options); if (null === $this->min && null === $this->max) { throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max')); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\HttpFoundation\File\File as FileObject; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class FileValidator extends ConstraintValidator { const KB_BYTES = 1000; const MB_BYTES = 1000000; const KIB_BYTES = 1024; const MIB_BYTES = 1048576; private static $suffices = array( 1 => 'bytes', self::KB_BYTES => 'kB', self::MB_BYTES => 'MB', self::KIB_BYTES => 'KiB', self::MIB_BYTES => 'MiB', ); /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof File) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\File'); } if (null === $value || '' === $value) { return; } if ($value instanceof UploadedFile && !$value->isValid()) { switch ($value->getError()) { case UPLOAD_ERR_INI_SIZE: $iniLimitSize = UploadedFile::getMaxFilesize(); if ($constraint->maxSize && $constraint->maxSize < $iniLimitSize) { $limitInBytes = $constraint->maxSize; $binaryFormat = $constraint->binaryFormat; } else { $limitInBytes = $iniLimitSize; $binaryFormat = true; } list($sizeAsString, $limitAsString, $suffix) = $this->factorizeSizes(0, $limitInBytes, $binaryFormat); $this->buildViolation($constraint->uploadIniSizeErrorMessage) ->setParameter('{{ limit }}', $limitAsString) ->setParameter('{{ suffix }}', $suffix) ->setCode(UPLOAD_ERR_INI_SIZE) ->addViolation(); return; case UPLOAD_ERR_FORM_SIZE: $this->buildViolation($constraint->uploadFormSizeErrorMessage) ->setCode(UPLOAD_ERR_FORM_SIZE) ->addViolation(); return; case UPLOAD_ERR_PARTIAL: $this->buildViolation($constraint->uploadPartialErrorMessage) ->setCode(UPLOAD_ERR_PARTIAL) ->addViolation(); return; case UPLOAD_ERR_NO_FILE: $this->buildViolation($constraint->uploadNoFileErrorMessage) ->setCode(UPLOAD_ERR_NO_FILE) ->addViolation(); return; case UPLOAD_ERR_NO_TMP_DIR: $this->buildViolation($constraint->uploadNoTmpDirErrorMessage) ->setCode(UPLOAD_ERR_NO_TMP_DIR) ->addViolation(); return; case UPLOAD_ERR_CANT_WRITE: $this->buildViolation($constraint->uploadCantWriteErrorMessage) ->setCode(UPLOAD_ERR_CANT_WRITE) ->addViolation(); return; case UPLOAD_ERR_EXTENSION: $this->buildViolation($constraint->uploadExtensionErrorMessage) ->setCode(UPLOAD_ERR_EXTENSION) ->addViolation(); return; default: $this->buildViolation($constraint->uploadErrorMessage) ->setCode($value->getError()) ->addViolation(); return; } } if (!is_scalar($value) && !$value instanceof FileObject && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $path = $value instanceof FileObject ? $value->getPathname() : (string) $value; if (!is_file($path)) { $this->buildViolation($constraint->notFoundMessage) ->setParameter('{{ file }}', $this->formatValue($path)) ->setCode(File::NOT_FOUND_ERROR) ->addViolation(); return; } if (!is_readable($path)) { $this->buildViolation($constraint->notReadableMessage) ->setParameter('{{ file }}', $this->formatValue($path)) ->setCode(File::NOT_READABLE_ERROR) ->addViolation(); return; } $sizeInBytes = filesize($path); if (0 === $sizeInBytes) { $this->buildViolation($constraint->disallowEmptyMessage) ->setParameter('{{ file }}', $this->formatValue($path)) ->setCode(File::EMPTY_ERROR) ->addViolation(); return; } if ($constraint->maxSize) { $limitInBytes = $constraint->maxSize; if ($sizeInBytes > $limitInBytes) { list($sizeAsString, $limitAsString, $suffix) = $this->factorizeSizes($sizeInBytes, $limitInBytes, $constraint->binaryFormat); $this->buildViolation($constraint->maxSizeMessage) ->setParameter('{{ file }}', $this->formatValue($path)) ->setParameter('{{ size }}', $sizeAsString) ->setParameter('{{ limit }}', $limitAsString) ->setParameter('{{ suffix }}', $suffix) ->setCode(File::TOO_LARGE_ERROR) ->addViolation(); return; } } if ($constraint->mimeTypes) { if (!$value instanceof FileObject) { $value = new FileObject($value); } $mimeTypes = (array) $constraint->mimeTypes; $mime = $value->getMimeType(); foreach ($mimeTypes as $mimeType) { if ($mimeType === $mime) { return; } if ($discrete = strstr($mimeType, '/*', true)) { if (strstr($mime, '/', true) === $discrete) { return; } } } $this->buildViolation($constraint->mimeTypesMessage) ->setParameter('{{ file }}', $this->formatValue($path)) ->setParameter('{{ type }}', $this->formatValue($mime)) ->setParameter('{{ types }}', $this->formatValues($mimeTypes)) ->setCode(File::INVALID_MIME_TYPE_ERROR) ->addViolation(); } } private static function moreDecimalsThan($double, $numberOfDecimals) { return strlen((string) $double) > strlen(round($double, $numberOfDecimals)); } /** * Convert the limit to the smallest possible number * (i.e. try "MB", then "kB", then "bytes") */ private function factorizeSizes($size, $limit, $binaryFormat) { if ($binaryFormat) { $coef = self::MIB_BYTES; $coefFactor = self::KIB_BYTES; } else { $coef = self::MB_BYTES; $coefFactor = self::KB_BYTES; } $limitAsString = (string) ($limit / $coef); // Restrict the limit to 2 decimals (without rounding! we // need the precise value) while (self::moreDecimalsThan($limitAsString, 2)) { $coef /= $coefFactor; $limitAsString = (string) ($limit / $coef); } // Convert size to the same measure, but round to 2 decimals $sizeAsString = (string) round($size / $coef, 2); // If the size and limit produce the same string output // (due to rounding), reduce the coefficient while ($sizeAsString === $limitAsString) { $coef /= $coefFactor; $limitAsString = (string) ($limit / $coef); $sizeAsString = (string) round($size / $coef, 2); } return array($sizeAsString, $limitAsString, self::$suffices[$coef]); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class NotNullValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof NotNull) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\NotNull'); } if (null === $value) { $this->context->addViolation($constraint->message); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class IsNull extends Constraint { public $message = 'This value should be null.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Language extends Constraint { public $message = 'This value is not a valid language.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Blank extends Constraint { public $message = 'This value should be blank.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class TimeValidator extends ConstraintValidator { const PATTERN = '/^(\d{2}):(\d{2}):(\d{2})$/'; /** * Checks whether a time is valid. * * @param int $hour The hour * @param int $minute The minute * @param int $second The second * * @return bool Whether the time is valid * * @internal */ public static function checkTime($hour, $minute, $second) { return $hour >= 0 && $hour < 24 && $minute >= 0 && $minute < 60 && $second >= 0 && $second < 60; } /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Time) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Time'); } if (null === $value || '' === $value || $value instanceof \DateTime) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if (!preg_match(static::PATTERN, $value, $matches)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Time::INVALID_FORMAT_ERROR) ->addViolation(); return; } if (!self::checkTime($matches[1], $matches[2], $matches[3])) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Time::INVALID_TIME_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Collection extends Composite { const MISSING_FIELD_ERROR = 1; const NO_SUCH_FIELD_ERROR = 2; protected static $errorNames = array( self::MISSING_FIELD_ERROR => 'MISSING_FIELD_ERROR', self::NO_SUCH_FIELD_ERROR => 'NO_SUCH_FIELD_ERROR', ); public $fields = array(); public $allowExtraFields = false; public $allowMissingFields = false; public $extraFieldsMessage = 'This field was not expected.'; public $missingFieldsMessage = 'This field is missing.'; /** * {@inheritdoc} */ public function __construct($options = null) { // no known options set? $options is the fields array if (is_array($options) && !array_intersect(array_keys($options), array('groups', 'fields', 'allowExtraFields', 'allowMissingFields', 'extraFieldsMessage', 'missingFieldsMessage'))) { $options = array('fields' => $options); } parent::__construct($options); } /** * {@inheritdoc} */ protected function initializeNestedConstraints() { parent::initializeNestedConstraints(); if (!is_array($this->fields)) { throw new ConstraintDefinitionException(sprintf('The option "fields" is expected to be an array in constraint %s', __CLASS__)); } foreach ($this->fields as $fieldName => $field) { // the XmlFileLoader and YamlFileLoader pass the field Optional // and Required constraint as an array with exactly one element if (is_array($field) && count($field) == 1) { $this->fields[$fieldName] = $field = $field[0]; } if (!$field instanceof Optional && !$field instanceof Required) { $this->fields[$fieldName] = $field = new Required($field); } } } public function getRequiredOptions() { return array('fields'); } protected function getCompositeOption() { return 'fields'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Miha Vrhovnik * * @api */ class Currency extends Constraint { public $message = 'This value is not a valid currency.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek */ class RangeValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Range) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Range'); } if (null === $value) { return; } if (!is_numeric($value) && !$value instanceof \DateTime && !$value instanceof \DateTimeInterface) { $this->buildViolation($constraint->invalidMessage) ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE)) ->setCode(Range::INVALID_VALUE_ERROR) ->addViolation(); return; } $min = $constraint->min; $max = $constraint->max; // Convert strings to DateTimes if comparing another DateTime // This allows to compare with any date/time value supported by // the DateTime constructor: // http://php.net/manual/en/datetime.formats.php if ($value instanceof \DateTime || $value instanceof \DateTimeInterface) { if (is_string($min)) { $min = new \DateTime($min); } if (is_string($max)) { $max = new \DateTime($max); } } if (null !== $constraint->max && $value > $max) { $this->buildViolation($constraint->maxMessage) ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE)) ->setParameter('{{ limit }}', $this->formatValue($max, self::PRETTY_DATE)) ->setCode(Range::BEYOND_RANGE_ERROR) ->addViolation(); return; } if (null !== $constraint->min && $value < $min) { $this->buildViolation($constraint->minMessage) ->setParameter('{{ value }}', $this->formatValue($value, self::PRETTY_DATE)) ->setParameter('{{ limit }}', $this->formatValue($min, self::PRETTY_DATE)) ->setCode(Range::BELOW_RANGE_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates that a card number belongs to a specified scheme. * * @author Tim Nagel * @author Bernhard Schussek * * @see http://en.wikipedia.org/wiki/Bank_card_number * @see http://www.regular-expressions.info/creditcard.html * @see http://www.barclaycard.co.uk/business/files/Ranges_and_Rules_September_2014.pdf */ class CardSchemeValidator extends ConstraintValidator { protected $schemes = array( // American Express card numbers start with 34 or 37 and have 15 digits. 'AMEX' => array( '/^3[47][0-9]{13}$/', ), // China UnionPay cards start with 62 and have between 16 and 19 digits. // Please note that these cards do not follow Luhn Algorithm as a checksum. 'CHINA_UNIONPAY' => array( '/^62[0-9]{14,17}$/', ), // Diners Club card numbers begin with 300 through 305, 36 or 38. All have 14 digits. // There are Diners Club cards that begin with 5 and have 16 digits. // These are a joint venture between Diners Club and MasterCard, and should be processed like a MasterCard. 'DINERS' => array( '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/', ), // Discover card numbers begin with 6011, 622126 through 622925, 644 through 649 or 65. // All have 16 digits. 'DISCOVER' => array( '/^6011[0-9]{12}$/', '/^64[4-9][0-9]{13}$/', '/^65[0-9]{14}$/', '/^622(12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|91[0-9]|92[0-5])[0-9]{10}$/', ), // InstaPayment cards begin with 637 through 639 and have 16 digits. 'INSTAPAYMENT' => array( '/^63[7-9][0-9]{13}$/', ), // JCB cards beginning with 2131 or 1800 have 15 digits. // JCB cards beginning with 35 have 16 digits. 'JCB' => array( '/^(?:2131|1800|35[0-9]{3})[0-9]{11}$/', ), // Laser cards begin with either 6304, 6706, 6709 or 6771 and have between 16 and 19 digits. 'LASER' => array( '/^(6304|670[69]|6771)[0-9]{12,15}$/', ), // Maestro international cards begin with 675900..675999 and have between 12 and 19 digits. // Maestro UK cards begin with either 500000..509999 or 560000..699999 and have between 12 and 19 digits. 'MAESTRO' => array( '/^(6759[0-9]{2})[0-9]{6,13}$/', '/^(50[0-9]{4})[0-9]{6,13}$/', '/^5[6-9][0-9]{10,17}$/', '/^6[0-9]{11,18}$/', ), // All MasterCard numbers start with the numbers 51 through 55. All have 16 digits. 'MASTERCARD' => array( '/^5[1-5][0-9]{14}$/', ), // All Visa card numbers start with a 4. New cards have 16 digits. Old cards have 13. 'VISA' => array( '/^4([0-9]{12}|[0-9]{15})$/', ), ); /** * Validates a creditcard belongs to a specified scheme. * * @param mixed $value * @param Constraint $constraint */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof CardScheme) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\CardScheme'); } if (null === $value || '' === $value) { return; } if (!is_numeric($value)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(CardScheme::NOT_NUMERIC_ERROR) ->addViolation(); return; } $schemes = array_flip((array) $constraint->schemes); $schemeRegexes = array_intersect_key($this->schemes, $schemes); foreach ($schemeRegexes as $regexes) { foreach ($regexes as $regex) { if (preg_match($regex, $value)) { return; } } } $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(CardScheme::INVALID_FORMAT_ERROR) ->addViolation(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class DateTime extends Constraint { const INVALID_FORMAT_ERROR = 1; const INVALID_DATE_ERROR = 2; const INVALID_TIME_ERROR = 3; protected static $errorNames = array( self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR', self::INVALID_DATE_ERROR => 'INVALID_DATE_ERROR', self::INVALID_TIME_ERROR => 'INVALID_TIME_ERROR', ); public $message = 'This value is not a valid datetime.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class True extends IsTrue { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"ANNOTATION"}) * * @author Bernhard Schussek */ class Optional extends Existence { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Email extends Constraint { const INVALID_FORMAT_ERROR = 1; const MX_CHECK_FAILED_ERROR = 2; const HOST_CHECK_FAILED_ERROR = 3; protected static $errorNames = array( self::INVALID_FORMAT_ERROR => 'STRICT_CHECK_FAILED_ERROR', self::MX_CHECK_FAILED_ERROR => 'MX_CHECK_FAILED_ERROR', self::HOST_CHECK_FAILED_ERROR => 'HOST_CHECK_FAILED_ERROR', ); public $message = 'This value is not a valid email address.'; public $checkMX = false; public $checkHost = false; public $strict; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * ChoiceValidator validates that the value is one of the expected values. * * @author Fabien Potencier * @author Florian Eckerstorfer * @author Bernhard Schussek * * @api */ class ChoiceValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Choice) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Choice'); } if (!is_array($constraint->choices) && !$constraint->callback) { throw new ConstraintDefinitionException('Either "choices" or "callback" must be specified on constraint Choice'); } if (null === $value) { return; } if ($constraint->multiple && !is_array($value)) { throw new UnexpectedTypeException($value, 'array'); } if ($constraint->callback) { if (!is_callable($choices = array($this->context->getClassName(), $constraint->callback)) && !is_callable($choices = $constraint->callback) ) { throw new ConstraintDefinitionException('The Choice constraint expects a valid callback'); } $choices = call_user_func($choices); } else { $choices = $constraint->choices; } if ($constraint->multiple) { foreach ($value as $_value) { if (!in_array($_value, $choices, $constraint->strict)) { $this->buildViolation($constraint->multipleMessage) ->setParameter('{{ value }}', $this->formatValue($_value)) ->setCode(Choice::NO_SUCH_CHOICE_ERROR) ->setInvalidValue($_value) ->addViolation(); return; } } $count = count($value); if ($constraint->min !== null && $count < $constraint->min) { $this->buildViolation($constraint->minMessage) ->setParameter('{{ limit }}', $constraint->min) ->setPlural((int) $constraint->min) ->setCode(Choice::TOO_FEW_ERROR) ->addViolation(); return; } if ($constraint->max !== null && $count > $constraint->max) { $this->buildViolation($constraint->maxMessage) ->setParameter('{{ limit }}', $constraint->max) ->setPlural((int) $constraint->max) ->setCode(Choice::TOO_MANY_ERROR) ->addViolation(); return; } } elseif (!in_array($value, $choices, $constraint->strict)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Choice::NO_SUCH_CHOICE_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Daniel Holmes */ class NotEqualTo extends AbstractComparison { public $message = 'This value should not be equal to {{ compared_value }}.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * Metadata for the LuhnValidator. * * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Tim Nagel * @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/ * @author Bernhard Schussek */ class Luhn extends Constraint { const INVALID_CHARACTERS_ERROR = 1; const CHECKSUM_FAILED_ERROR = 2; protected static $errorNames = array( self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR', self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR', ); public $message = 'Invalid card number.'; } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"CLASS", "PROPERTY", "METHOD", "ANNOTATION"}) * * @author Fabien Potencier * @author Bernhard Schussek */ class Expression extends Constraint { public $message = 'This value is not valid.'; public $expression; /** * {@inheritdoc} */ public function getDefaultOption() { return 'expression'; } /** * {@inheritdoc} */ public function getRequiredOptions() { return array('expression'); } /** * {@inheritdoc} */ public function getTargets() { return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT); } /** * {@inheritdoc} */ public function validatedBy() { return 'validator.expression'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Bernhard Schussek * * @api */ class Regex extends Constraint { public $message = 'This value is not valid.'; public $pattern; public $htmlPattern; public $match = true; /** * {@inheritdoc} */ public function getDefaultOption() { return 'pattern'; } /** * {@inheritdoc} */ public function getRequiredOptions() { return array('pattern'); } /** * Converts the htmlPattern to a suitable format for HTML5 pattern. * Example: /^[a-z]+$/ would be converted to [a-z]+ * However, if options are specified, it cannot be converted. * * Pattern is also ignored if match=false since the pattern should * then be reversed before application. * * @link http://dev.w3.org/html5/spec/single-page.html#the-pattern-attribute * * @return string|null */ public function getHtmlPattern() { // If htmlPattern is specified, use it if (null !== $this->htmlPattern) { return empty($this->htmlPattern) ? null : $this->htmlPattern; } // Quit if delimiters not at very beginning/end (e.g. when options are passed) if ($this->pattern[0] !== $this->pattern[strlen($this->pattern) - 1]) { return; } $delimiter = $this->pattern[0]; // Unescape the delimiter $pattern = str_replace('\\'.$delimiter, $delimiter, substr($this->pattern, 1, -1)); // If the pattern is inverted, we can simply wrap it in // ((?!pattern).)* if (!$this->match) { return '((?!'.$pattern.').)*'; } // If the pattern contains an or statement, wrap the pattern in // .*(pattern).* and quit. Otherwise we'd need to parse the pattern if (false !== strpos($pattern, '|')) { return '.*('.$pattern.').*'; } // Trim leading ^, otherwise prepend .* $pattern = '^' === $pattern[0] ? substr($pattern, 1) : '.*'.$pattern; // Trim trailing $, otherwise append .* $pattern = '$' === $pattern[strlen($pattern) - 1] ? substr($pattern, 0, -1) : $pattern.'.*'; return $pattern; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Manuel Reinhard * @author Michael Schummel * @author Bernhard Schussek * * @link http://www.michael-schummel.de/2007/10/05/iban-prufung-mit-php/ */ class IbanValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Iban) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Iban'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; // Remove spaces $canonicalized = str_replace(' ', '', $value); // The IBAN must have at least 4 characters... if (strlen($canonicalized) < 4) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Iban::TOO_SHORT_ERROR) ->addViolation(); return; } // ...start with a country code... if (!ctype_alpha($canonicalized{0}) || !ctype_alpha($canonicalized{1})) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Iban::INVALID_COUNTRY_CODE_ERROR) ->addViolation(); return; } // ...contain only digits and characters... if (!ctype_alnum($canonicalized)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Iban::INVALID_CHARACTERS_ERROR) ->addViolation(); return; } // ...and contain uppercase characters only if ($canonicalized !== strtoupper($canonicalized)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Iban::INVALID_CASE_ERROR) ->addViolation(); return; } // Move the first four characters to the end // e.g. CH93 0076 2011 6238 5295 7 // -> 0076 2011 6238 5295 7 CH93 $canonicalized = substr($canonicalized, 4).substr($canonicalized, 0, 4); // Convert all remaining letters to their ordinals // The result is an integer, which is too large for PHP's int // data type, so we store it in a string instead. // e.g. 0076 2011 6238 5295 7 CH93 // -> 0076 2011 6238 5295 7 121893 $checkSum = $this->toBigInt($canonicalized); // Do a modulo-97 operation on the large integer // We cannot use PHP's modulo operator, so we calculate the // modulo step-wisely instead if (1 !== $this->bigModulo97($checkSum)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Iban::CHECKSUM_FAILED_ERROR) ->addViolation(); } } private function toBigInt($string) { $chars = str_split($string); $bigInt = ''; foreach ($chars as $char) { // Convert uppercase characters to ordinals, starting with 10 for "A" if (ctype_upper($char)) { $bigInt .= (ord($char) - 55); continue; } // Simply append digits $bigInt .= $char; } return $bigInt; } private function bigModulo97($bigInt) { $parts = str_split($bigInt, 7); $rest = 0; foreach ($parts as $part) { $rest = ($rest.$part) % 97; } return $rest; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author The Whole Life To Learn * @author Manuel Reinhard * @author Bernhard Schussek */ class Isbn extends Constraint { const TOO_SHORT_ERROR = 1; const TOO_LONG_ERROR = 2; const INVALID_CHARACTERS_ERROR = 3; const CHECKSUM_FAILED_ERROR = 4; const TYPE_NOT_RECOGNIZED_ERROR = 5; protected static $errorNames = array( self::TOO_SHORT_ERROR => 'TOO_SHORT_ERROR', self::TOO_LONG_ERROR => 'TOO_LONG_ERROR', self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR', self::CHECKSUM_FAILED_ERROR => 'CHECKSUM_FAILED_ERROR', self::TYPE_NOT_RECOGNIZED_ERROR => 'TYPE_NOT_RECOGNIZED_ERROR', ); public $isbn10Message = 'This value is not a valid ISBN-10.'; public $isbn13Message = 'This value is not a valid ISBN-13.'; public $bothIsbnMessage = 'This value is neither a valid ISBN-10 nor a valid ISBN-13.'; public $type; public $message; /** * @deprecated Deprecated since version 2.5, to be removed in 3.0. Use option "type" instead. * @var bool */ public $isbn10 = false; /** * @deprecated Deprecated since version 2.5, to be removed in 3.0. Use option "type" instead. * @var bool */ public $isbn13 = false; /** * {@inheritdoc} */ public function getDefaultOption() { return 'type'; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation * * @since 2.5 * @author Bernhard Schussek */ class Traverse extends Constraint { public $traverse = true; public function __construct($options = null) { if (is_array($options) && array_key_exists('groups', $options)) { throw new ConstraintDefinitionException(sprintf( 'The option "groups" is not supported by the constraint %s', __CLASS__ )); } parent::__construct($options); } /** * {@inheritdoc} */ public function getDefaultOption() { return 'traverse'; } /** * {@inheritdoc} */ public function getTargets() { return self::CLASS_CONSTRAINT; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; /** * Metadata for the CardSchemeValidator. * * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * * @author Tim Nagel * @author Bernhard Schussek */ class CardScheme extends Constraint { const NOT_NUMERIC_ERROR = 1; const INVALID_FORMAT_ERROR = 2; protected static $errorNames = array( self::NOT_NUMERIC_ERROR => 'NOT_NUMERIC_ERROR', self::INVALID_FORMAT_ERROR => 'INVALID_FORMAT_ERROR', ); public $message = 'Unsupported card type or invalid card number.'; public $schemes; public function getDefaultOption() { return 'schemes'; } public function getRequiredOptions() { return array('schemes'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek * * @api */ class DateValidator extends ConstraintValidator { const PATTERN = '/^(\d{4})-(\d{2})-(\d{2})$/'; /** * Checks whether a date is valid. * * @param int $year The year * @param int $month The month * @param int $day The day * * @return bool Whether the date is valid * * @internal */ public static function checkDate($year, $month, $day) { return checkdate($month, $day, $year); } /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Date) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Date'); } if (null === $value || '' === $value || $value instanceof \DateTime) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; if (!preg_match(static::PATTERN, $value, $matches)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Date::INVALID_FORMAT_ERROR) ->addViolation(); return; } if (!self::checkDate($matches[1], $matches[2], $matches[3])) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Date::INVALID_DATE_ERROR) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Intl\Intl; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid locale code. * * @author Bernhard Schussek * * @api */ class LocaleValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Locale) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Locale'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; $locales = Intl::getLocaleBundle()->getLocaleNames(); if (!isset($locales[$value])) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * Validates whether a value is a valid IP address. * * @author Bernhard Schussek * @author Joseph Bielawski * * @api */ class IpValidator extends ConstraintValidator { /** * {@inheritdoc} */ public function validate($value, Constraint $constraint) { if (!$constraint instanceof Ip) { throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Ip'); } if (null === $value || '' === $value) { return; } if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) { throw new UnexpectedTypeException($value, 'string'); } $value = (string) $value; switch ($constraint->version) { case Ip::V4: $flag = FILTER_FLAG_IPV4; break; case Ip::V6: $flag = FILTER_FLAG_IPV6; break; case Ip::V4_NO_PRIV: $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE; break; case Ip::V6_NO_PRIV: $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE; break; case Ip::ALL_NO_PRIV: $flag = FILTER_FLAG_NO_PRIV_RANGE; break; case Ip::V4_NO_RES: $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE; break; case Ip::V6_NO_RES: $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE; break; case Ip::ALL_NO_RES: $flag = FILTER_FLAG_NO_RES_RANGE; break; case Ip::V4_ONLY_PUBLIC: $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE; break; case Ip::V6_ONLY_PUBLIC: $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE; break; case Ip::ALL_ONLY_PUBLIC: $flag = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE; break; default: $flag = null; break; } if (!filter_var($value, FILTER_VALIDATE_IP, $flag)) { $this->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->addViolation(); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Constraints; /** * @author Bernhard Schussek * * @api */ class NullValidator extends IsNullValidator { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * @author Bernhard Schussek * * @api */ interface ConstraintValidatorInterface { /** * Initializes the constraint validator. * * @param ExecutionContextInterface $context The current validation context */ public function initialize(ExecutionContextInterface $context); /** * Checks if the passed value is valid. * * @param mixed $value The value that should be validated * @param Constraint $constraint The constraint for the validation * * @api */ public function validate($value, Constraint $constraint); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Doctrine\Common\Annotations\Reader; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Mapping\Cache\CacheInterface; /** * A configurable builder for ValidatorInterface objects. * * @author Bernhard Schussek */ interface ValidatorBuilderInterface { /** * Adds an object initializer to the validator. * * @param ObjectInitializerInterface $initializer The initializer * * @return ValidatorBuilderInterface The builder object */ public function addObjectInitializer(ObjectInitializerInterface $initializer); /** * Adds a list of object initializers to the validator. * * @param array $initializers The initializer * * @return ValidatorBuilderInterface The builder object */ public function addObjectInitializers(array $initializers); /** * Adds an XML constraint mapping file to the validator. * * @param string $path The path to the mapping file * * @return ValidatorBuilderInterface The builder object */ public function addXmlMapping($path); /** * Adds a list of XML constraint mapping files to the validator. * * @param array $paths The paths to the mapping files * * @return ValidatorBuilderInterface The builder object */ public function addXmlMappings(array $paths); /** * Adds a YAML constraint mapping file to the validator. * * @param string $path The path to the mapping file * * @return ValidatorBuilderInterface The builder object */ public function addYamlMapping($path); /** * Adds a list of YAML constraint mappings file to the validator. * * @param array $paths The paths to the mapping files * * @return ValidatorBuilderInterface The builder object */ public function addYamlMappings(array $paths); /** * Enables constraint mapping using the given static method. * * @param string $methodName The name of the method * * @return ValidatorBuilderInterface The builder object */ public function addMethodMapping($methodName); /** * Enables constraint mapping using the given static methods. * * @param array $methodNames The names of the methods * * @return ValidatorBuilderInterface The builder object */ public function addMethodMappings(array $methodNames); /** * Enables annotation based constraint mapping. * * @param Reader $annotationReader The annotation reader to be used * * @return ValidatorBuilderInterface The builder object */ public function enableAnnotationMapping(Reader $annotationReader = null); /** * Disables annotation based constraint mapping. * * @return ValidatorBuilderInterface The builder object */ public function disableAnnotationMapping(); /** * Sets the class metadata factory used by the validator. * * @param MetadataFactoryInterface $metadataFactory The metadata factory * * @return ValidatorBuilderInterface The builder object */ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory); /** * Sets the cache for caching class metadata. * * @param CacheInterface $cache The cache instance * * @return ValidatorBuilderInterface The builder object */ public function setMetadataCache(CacheInterface $cache); /** * Sets the constraint validator factory used by the validator. * * @param ConstraintValidatorFactoryInterface $validatorFactory The validator factory * * @return ValidatorBuilderInterface The builder object */ public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory); /** * Sets the translator used for translating violation messages. * * @param TranslatorInterface $translator The translator instance * * @return ValidatorBuilderInterface The builder object */ public function setTranslator(TranslatorInterface $translator); /** * Sets the default translation domain of violation messages. * * The same message can have different translations in different domains. * Pass the domain that is used for violation messages by default to this * method. * * @param string $translationDomain The translation domain of the violation messages * * @return ValidatorBuilderInterface The builder object */ public function setTranslationDomain($translationDomain); /** * Sets the property accessor for resolving property paths. * * @param PropertyAccessorInterface $propertyAccessor The property accessor * * @return ValidatorBuilderInterface The builder object * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. */ public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor); /** * Sets the API version that the returned validator should support. * * @param int $apiVersion The required API version * * @return ValidatorBuilderInterface The builder object * * @see Validation::API_VERSION_2_4 * @see Validation::API_VERSION_2_5 * @see Validation::API_VERSION_2_5_BC */ public function setApiVersion($apiVersion); /** * Builds and returns a new validator object. * * @return ValidatorInterface The built validator. */ public function getValidator(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Constraints\ExpressionValidator; /** * Default implementation of the ConstraintValidatorFactoryInterface. * * This enforces the convention that the validatedBy() method on any * Constraint will return the class name of the ConstraintValidator that * should validate the Constraint. * * @author Bernhard Schussek */ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface { protected $validators = array(); private $propertyAccessor; public function __construct($propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor; } /** * {@inheritdoc} */ public function getInstance(Constraint $constraint) { $className = $constraint->validatedBy(); if (!isset($this->validators[$className])) { $this->validators[$className] = 'validator.expression' === $className ? new ExpressionValidator($this->propertyAccessor) : new $className(); } return $this->validators[$className]; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A container for validation metadata of a property. * * What exactly you define as "property" is up to you. The validator expects * implementations of {@link MetadataInterface} that contain constraints and * optionally a list of named properties that also have constraints (and may * have further sub properties). Such properties are mapped by implementations * of this interface. * * @author Bernhard Schussek * * @see MetadataInterface * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Mapping\PropertyMetadataInterface} instead. */ interface PropertyMetadataInterface extends MetadataInterface { /** * Returns the name of the property. * * @return string The property name. */ public function getPropertyName(); /** * Extracts the value of the property from the given container. * * @param mixed $containingValue The container to extract the property value from. * * @return mixed The value of the property. */ public function getPropertyValue($containingValue); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Stores the validator's state during validation. * * For example, let's validate the following object graph: * *
 * (Person)---($firstName: string)
 *      \
 *   ($address: Address)---($street: string)
 * 
* * We validate the Person instance, which becomes the "root" of the * validation run (see {@link getRoot}). The state of the context after the * first step will be like this: * *
 * (Person)---($firstName: string)
 *    ^ \
 *   ($address: Address)---($street: string)
 * 
* * The validator is stopped at the Person node, both the root and the * value (see {@link getValue}) of the context point to the Person * instance. The property path is empty at this point (see {@link getPropertyPath}). * The metadata of the context is the metadata of the Person node * (see {@link getMetadata}). * * After advancing to the property $firstName of the Person * instance, the state of the context looks like this: * *
 * (Person)---($firstName: string)
 *      \              ^
 *   ($address: Address)---($street: string)
 * 
* * The validator is stopped at the property $firstName. The root still * points to the Person instance, because this is where the validation * started. The property path is now "firstName" and the current value is the * value of that property. * * After advancing to the $address property and then to the * $street property of the Address instance, the context state * looks like this: * *
 * (Person)---($firstName: string)
 *      \
 *   ($address: Address)---($street: string)
 *                               ^
 * 
* * The validator is stopped at the property $street. The root still * points to the Person instance, but the property path is now * "address.street" and the validated value is the value of that property. * * Apart from the root, the property path and the currently validated value, * the execution context also knows the metadata of the current node (see * {@link getMetadata}) which for example returns a {@link Mapping\PropertyMetadata} * or a {@link Mapping\ClassMetadata} object. he context also contains the * validation group that is currently being validated (see {@link getGroup}) and * the violations that happened up until now (see {@link getViolations}). * * Apart from reading the execution context, you can also use * {@link addViolation} or {@link addViolationAt} to add new violations and * {@link validate} or {@link validateValue} to validate values that the * validator otherwise would not reach. * * @author Bernhard Schussek * * @api * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Context\ExecutionContextInterface} instead. */ interface ExecutionContextInterface { /** * Adds a violation at the current node of the validation graph. * * Note: the parameters $invalidValue, $plural and $code are deprecated since version 2.5 and will be removed in 3.0. * * @param string $message The error message * @param array $params The parameters substituted in the error message * @param mixed $invalidValue The invalid, validated value * @param int|null $plural The number to use to pluralize of the message * @param int|null $code The violation code * * @api */ public function addViolation($message, array $params = array(), $invalidValue = null, $plural = null, $code = null); /** * Adds a violation at the validation graph node with the given property * path relative to the current property path. * * @param string $subPath The relative property path for the violation * @param string $message The error message * @param array $parameters The parameters substituted in the error message * @param mixed $invalidValue The invalid, validated value * @param int|null $plural The number to use to pluralize of the message * @param int|null $code The violation code * * @api * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Context\ExecutionContextInterface::buildViolation()} * instead. */ public function addViolationAt($subPath, $message, array $parameters = array(), $invalidValue = null, $plural = null, $code = null); /** * Validates the given value within the scope of the current validation. * * The value may be any value recognized by the used metadata factory * (see {@link MetadataFactoryInterface::getMetadata}), or an array or a * traversable object of such values. * * Usually you validate a value that is not the current node of the * execution context. For this case, you can pass the {@link $subPath} * argument which is appended to the current property path when a violation * is created. For example, take the following object graph: * *
     * (Person)---($address: Address)---($phoneNumber: PhoneNumber)
     *                     ^
     * 
* * When the execution context stops at the Person instance, the * property path is "address". When you validate the PhoneNumber * instance now, pass "phoneNumber" as sub path to correct the property path * to "address.phoneNumber": * *
     * $context->validate($address->phoneNumber, 'phoneNumber');
     * 
* * Any violations generated during the validation will be added to the * violation list that you can access with {@link getViolations}. * * @param mixed $value The value to validate. * @param string $subPath The path to append to the context's property path. * @param null|string|string[] $groups The groups to validate in. If you don't pass any * groups here, the current group of the context * will be used. * @param bool $traverse Whether to traverse the value if it is an array * or an instance of \Traversable. * @param bool $deep Whether to traverse the value recursively if * it is a collection of collections. * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Context\ExecutionContextInterface::getValidator()} * instead. */ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false); /** * Validates a value against a constraint. * * Use the parameter $subPath to adapt the property path for the * validated value. For example, take the following object graph: * *
     * (Person)---($address: Address)---($street: string)
     *                     ^
     * 
* * When the validator validates the Address instance, the * property path stored in the execution context is "address". When you * manually validate the property $street now, pass the sub path * "street" to adapt the full property path to "address.street": * *
     * $context->validate($address->street, new NotNull(), 'street');
     * 
* * @param mixed $value The value to validate. * @param Constraint|Constraint[] $constraints The constraint(s) to validate against. * @param string $subPath The path to append to the context's property path. * @param null|string|string[] $groups The groups to validate in. If you don't pass any * groups here, the current group of the context * will be used. * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Context\ExecutionContextInterface::getValidator()} * instead. */ public function validateValue($value, $constraints, $subPath = '', $groups = null); /** * Returns the violations generated by the validator so far. * * @return ConstraintViolationListInterface The constraint violation list. * * @api */ public function getViolations(); /** * Returns the value at which validation was started in the object graph. * * The validator, when given an object, traverses the properties and * related objects and their properties. The root of the validation is the * object from which the traversal started. * * The current value is returned by {@link getValue}. * * @return mixed The root value of the validation. */ public function getRoot(); /** * Returns the value that the validator is currently validating. * * If you want to retrieve the object that was originally passed to the * validator, use {@link getRoot}. * * @return mixed The currently validated value. */ public function getValue(); /** * Returns the metadata for the currently validated value. * * With the core implementation, this method returns a * {@link Mapping\ClassMetadata} instance if the current value is an object, * a {@link Mapping\PropertyMetadata} instance if the current value is * the value of a property and a {@link Mapping\GetterMetadata} instance if * the validated value is the result of a getter method. * * If the validated value is neither of these, for example if the validator * has been called with a plain value and constraint, this method returns * null. * * @return MetadataInterface|null The metadata of the currently validated * value. */ public function getMetadata(); /** * Returns the used metadata factory. * * @return MetadataFactoryInterface The metadata factory. * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Context\ExecutionContextInterface::getValidator()} * instead and call * {@link Validator\ValidatorInterface::getMetadataFor()} or * {@link Validator\ValidatorInterface::hasMetadataFor()} there. */ public function getMetadataFactory(); /** * Returns the validation group that is currently being validated. * * @return string The current validation group. */ public function getGroup(); /** * Returns the class name of the current node. * * If the metadata of the current node does not implement * {@link ClassBasedInterface} or if no metadata is available for the * current node, this method returns null. * * @return string|null The class name or null, if no class name could be found. */ public function getClassName(); /** * Returns the property name of the current node. * * If the metadata of the current node does not implement * {@link PropertyMetadataInterface} or if no metadata is available for the * current node, this method returns null. * * @return string|null The property name or null, if no property name could be found. */ public function getPropertyName(); /** * Returns the property path to the value that the validator is currently * validating. * * For example, take the following object graph: * *
     * (Person)---($address: Address)---($street: string)
     * 
* * When the Person instance is passed to the validator, the * property path is initially empty. When the $address property * of that person is validated, the property path is "address". When * the $street property of the related Address instance * is validated, the property path is "address.street". * * Properties of objects are prefixed with a dot in the property path. * Indices of arrays or objects implementing the {@link \ArrayAccess} * interface are enclosed in brackets. For example, if the property in * the previous example is $addresses and contains an array * of Address instance, the property path generated for the * $street property of one of these addresses is for example * "addresses[0].street". * * @param string $subPath Optional. The suffix appended to the current * property path. * * @return string The current property path. The result may be an empty * string if the validator is currently validating the * root value of the validation graph. */ public function getPropertyPath($subPath = ''); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * An object backed by a PHP class. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Mapping\ClassMetadataInterface} instead. */ interface ClassBasedInterface { /** * Returns the name of the backing PHP class. * * @return string The name of the backing class. */ public function getClassName(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ValidatorException; /** * Default implementation of {@link ValidatorInterface}. * * @author Fabien Potencier * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Validator\RecursiveValidator} instead. */ class Validator implements ValidatorInterface, Mapping\Factory\MetadataFactoryInterface { /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * @var ConstraintValidatorFactoryInterface */ private $validatorFactory; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var array */ private $objectInitializers; public function __construct( MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = 'validators', array $objectInitializers = array() ) { $this->metadataFactory = $metadataFactory; $this->validatorFactory = $validatorFactory; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->objectInitializers = $objectInitializers; } /** * {@inheritdoc} */ public function getMetadataFactory() { return $this->metadataFactory; } /** * {@inheritdoc} */ public function getMetadataFor($value) { return $this->metadataFactory->getMetadataFor($value); } /** * {@inheritdoc} */ public function hasMetadataFor($value) { return $this->metadataFactory->hasMetadataFor($value); } /** * {@inheritdoc} */ public function validate($value, $groups = null, $traverse = false, $deep = false) { $visitor = $this->createVisitor($value); foreach ($this->resolveGroups($groups) as $group) { $visitor->validate($value, $group, '', $traverse, $deep); } return $visitor->getViolations(); } /** * {@inheritdoc} * * @throws ValidatorException If the metadata for the value does not support properties. */ public function validateProperty($containingValue, $property, $groups = null) { $visitor = $this->createVisitor($containingValue); $metadata = $this->metadataFactory->getMetadataFor($containingValue); if (!$metadata instanceof PropertyMetadataContainerInterface) { $valueAsString = is_scalar($containingValue) ? '"'.$containingValue.'"' : 'the value of type '.gettype($containingValue); throw new ValidatorException(sprintf('The metadata for %s does not support properties.', $valueAsString)); } foreach ($this->resolveGroups($groups) as $group) { if (!$metadata->hasPropertyMetadata($property)) { continue; } foreach ($metadata->getPropertyMetadata($property) as $propMeta) { $propMeta->accept($visitor, $propMeta->getPropertyValue($containingValue), $group, $property); } } return $visitor->getViolations(); } /** * {@inheritdoc} * * @throws ValidatorException If the metadata for the value does not support properties. */ public function validatePropertyValue($containingValue, $property, $value, $groups = null) { $visitor = $this->createVisitor(is_object($containingValue) ? $containingValue : $value); $metadata = $this->metadataFactory->getMetadataFor($containingValue); if (!$metadata instanceof PropertyMetadataContainerInterface) { $valueAsString = is_scalar($containingValue) ? '"'.$containingValue.'"' : 'the value of type '.gettype($containingValue); throw new ValidatorException(sprintf('The metadata for '.$valueAsString.' does not support properties.')); } // If $containingValue is passed as class name, take $value as root // and start the traversal with an empty property path $propertyPath = is_object($containingValue) ? $property : ''; foreach ($this->resolveGroups($groups) as $group) { if (!$metadata->hasPropertyMetadata($property)) { continue; } foreach ($metadata->getPropertyMetadata($property) as $propMeta) { $propMeta->accept($visitor, $value, $group, $propertyPath); } } return $visitor->getViolations(); } /** * {@inheritdoc} */ public function validateValue($value, $constraints, $groups = null) { $context = new ExecutionContext($this->createVisitor($value), $this->translator, $this->translationDomain); $constraints = is_array($constraints) ? $constraints : array($constraints); foreach ($constraints as $constraint) { if ($constraint instanceof Valid) { // Why can't the Valid constraint be executed directly? // // It cannot be executed like regular other constraints, because regular // constraints are only executed *if they belong to the validated group*. // The Valid constraint, on the other hand, is always executed and propagates // the group to the cascaded object. The propagated group depends on // // * Whether a group sequence is currently being executed. Then the default // group is propagated. // // * Otherwise the validated group is propagated. throw new ValidatorException( sprintf( 'The constraint %s cannot be validated. Use the method validate() instead.', get_class($constraint) ) ); } $context->validateValue($value, $constraint, '', $groups); } return $context->getViolations(); } /** * @param mixed $root * * @return ValidationVisitor */ private function createVisitor($root) { return new ValidationVisitor( $root, $this->metadataFactory, $this->validatorFactory, $this->translator, $this->translationDomain, $this->objectInitializers ); } /** * @param null|string|string[] $groups * * @return string[] */ private function resolveGroups($groups) { return $groups ? (array) $groups : array(Constraint::DEFAULT_GROUP); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * A list of constraint violations. * * @author Bernhard Schussek * * @api */ interface ConstraintViolationListInterface extends \Traversable, \Countable, \ArrayAccess { /** * Adds a constraint violation to this list. * * @param ConstraintViolationInterface $violation The violation to add. * * @api */ public function add(ConstraintViolationInterface $violation); /** * Merges an existing violation list into this list. * * @param ConstraintViolationListInterface $otherList The list to merge. * * @api */ public function addAll(ConstraintViolationListInterface $otherList); /** * Returns the violation at a given offset. * * @param int $offset The offset of the violation. * * @return ConstraintViolationInterface The violation. * * @throws \OutOfBoundsException If the offset does not exist. * * @api */ public function get($offset); /** * Returns whether the given offset exists. * * @param int $offset The violation offset. * * @return bool Whether the offset exists. * * @api */ public function has($offset); /** * Sets a violation at a given offset. * * @param int $offset The violation offset. * @param ConstraintViolationInterface $violation The violation. * * @api */ public function set($offset, ConstraintViolationInterface $violation); /** * Removes a violation at a given offset. * * @param int $offset The offset to remove. * * @api */ public function remove($offset); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\InvalidOptionsException; use Symfony\Component\Validator\Exception\MissingOptionsException; /** * Contains the properties of a constraint definition. * * A constraint can be defined on a class, an option or a getter method. * The Constraint class encapsulates all the configuration required for * validating this class, option or getter result successfully. * * Constraint instances are immutable and serializable. * * @property array $groups The groups that the constraint belongs to * * @author Bernhard Schussek * * @api */ abstract class Constraint { /** * The name of the group given to all constraints with no explicit group. * * @var string */ const DEFAULT_GROUP = 'Default'; /** * Marks a constraint that can be put onto classes. * * @var string */ const CLASS_CONSTRAINT = 'class'; /** * Marks a constraint that can be put onto properties. * * @var string */ const PROPERTY_CONSTRAINT = 'property'; /** * Maps error codes to the names of their constants * @var array */ protected static $errorNames = array(); /** * Domain-specific data attached to a constraint * @var mixed */ public $payload; /** * Returns the name of the given error code. * * @param int $errorCode The error code * * @return string The name of the error code * * @throws InvalidArgumentException If the error code does not exist */ public static function getErrorName($errorCode) { if (!isset(static::$errorNames[$errorCode])) { throw new InvalidArgumentException(sprintf( 'The error code "%s" does not exist for constraint of type "%s".', $errorCode, get_called_class() )); } return static::$errorNames[$errorCode]; } /** * Initializes the constraint with options. * * You should pass an associative array. The keys should be the names of * existing properties in this class. The values should be the value for these * properties. * * Alternatively you can override the method getDefaultOption() to return the * name of an existing property. If no associative array is passed, this * property is set instead. * * You can force that certain options are set by overriding * getRequiredOptions() to return the names of these options. If any * option is not set here, an exception is thrown. * * @param mixed $options The options (as associative array) * or the value for the default * option (any other type) * * @throws InvalidOptionsException When you pass the names of non-existing * options * @throws MissingOptionsException When you don't pass any of the options * returned by getRequiredOptions() * @throws ConstraintDefinitionException When you don't pass an associative * array, but getDefaultOption() returns * null * * @api */ public function __construct($options = null) { $invalidOptions = array(); $missingOptions = array_flip((array) $this->getRequiredOptions()); $knownOptions = get_object_vars($this); // The "groups" option is added to the object lazily $knownOptions['groups'] = true; if (is_array($options) && count($options) >= 1 && isset($options['value']) && !property_exists($this, 'value')) { $options[$this->getDefaultOption()] = $options['value']; unset($options['value']); } if (is_array($options) && count($options) > 0 && is_string(key($options))) { foreach ($options as $option => $value) { if (array_key_exists($option, $knownOptions)) { $this->$option = $value; unset($missingOptions[$option]); } else { $invalidOptions[] = $option; } } } elseif (null !== $options && !(is_array($options) && count($options) === 0)) { $option = $this->getDefaultOption(); if (null === $option) { throw new ConstraintDefinitionException( sprintf('No default option is configured for constraint %s', get_class($this)) ); } if (array_key_exists($option, $knownOptions)) { $this->$option = $options; unset($missingOptions[$option]); } else { $invalidOptions[] = $option; } } if (count($invalidOptions) > 0) { throw new InvalidOptionsException( sprintf('The options "%s" do not exist in constraint %s', implode('", "', $invalidOptions), get_class($this)), $invalidOptions ); } if (count($missingOptions) > 0) { throw new MissingOptionsException( sprintf('The options "%s" must be set for constraint %s', implode('", "', array_keys($missingOptions)), get_class($this)), array_keys($missingOptions) ); } } /** * Sets the value of a lazily initialized option. * * Corresponding properties are added to the object on first access. Hence * this method will be called at most once per constraint instance and * option name. * * @param string $option The option name * @param mixed $value The value to set * * @throws InvalidOptionsException If an invalid option name is given */ public function __set($option, $value) { if ('groups' === $option) { $this->groups = (array) $value; return; } throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint %s', $option, get_class($this)), array($option)); } /** * Returns the value of a lazily initialized option. * * Corresponding properties are added to the object on first access. Hence * this method will be called at most once per constraint instance and * option name. * * @param string $option The option name * * @return mixed The value of the option * * @throws InvalidOptionsException If an invalid option name is given * * @internal This method should not be used or overwritten in userland code. * * @since 2.6 */ public function __get($option) { if ('groups' === $option) { $this->groups = array(self::DEFAULT_GROUP); return $this->groups; } throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint %s', $option, get_class($this)), array($option)); } /** * Adds the given group if this constraint is in the Default group. * * @param string $group * * @api */ public function addImplicitGroupName($group) { if (in_array(self::DEFAULT_GROUP, $this->groups) && !in_array($group, $this->groups)) { $this->groups[] = $group; } } /** * Returns the name of the default option. * * Override this method to define a default option. * * @return string * * @see __construct() * * @api */ public function getDefaultOption() { } /** * Returns the name of the required options. * * Override this method if you want to define required options. * * @return array * * @see __construct() * * @api */ public function getRequiredOptions() { return array(); } /** * Returns the name of the class that validates this constraint. * * By default, this is the fully qualified name of the constraint class * suffixed with "Validator". You can override this method to change that * behaviour. * * @return string * * @api */ public function validatedBy() { return get_class($this).'Validator'; } /** * Returns whether the constraint can be put onto classes, properties or * both. * * This method should return one or more of the constants * Constraint::CLASS_CONSTRAINT and Constraint::PROPERTY_CONSTRAINT. * * @return string|array One or more constant values * * @api */ public function getTargets() { return self::PROPERTY_CONSTRAINT; } /** * Optimizes the serialized value to minimize storage space. * * @return array The properties to serialize * * @internal This method may be replaced by an implementation of * {@link \Serializable} in the future. Please don't use or * overwrite it. * * @since 2.6 */ public function __sleep() { // Initialize "groups" option if it is not set $this->groups; return array_keys(get_object_vars($this)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Stores the node-independent state of a validation run. * * When the validator validates a graph of objects, it uses two classes to * store the state during the validation: * *
    *
  • For each node in the validation graph (objects, properties, getters) the * validator creates an instance of {@link ExecutionContextInterface} that * stores the information about that node.
  • *
  • One single GlobalExecutionContextInterface stores the state * that is independent of the current node.
  • *
* * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Context\ExecutionContextInterface} instead. */ interface GlobalExecutionContextInterface { /** * Returns the violations generated by the validator so far. * * @return ConstraintViolationListInterface A list of constraint violations. */ public function getViolations(); /** * Returns the value at which validation was started in the object graph. * * @return mixed The root value. * * @see ExecutionContextInterface::getRoot() */ public function getRoot(); /** * Returns the visitor instance used to validate the object graph nodes. * * @return ValidationVisitorInterface The validation visitor. */ public function getVisitor(); /** * Returns the factory for constraint validators. * * @return ConstraintValidatorFactoryInterface The constraint validator factory. */ public function getValidatorFactory(); /** * Returns the factory for validation metadata objects. * * @return MetadataFactoryInterface The metadata factory. */ public function getMetadataFactory(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; use Symfony\Component\Translation\TranslatorInterface; /** * Default implementation of {@link ExecutionContextInterface}. * * This class is immutable by design. * * @author Fabien Potencier * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Context\ExecutionContext} instead. */ class ExecutionContext implements ExecutionContextInterface { /** * @var GlobalExecutionContextInterface */ private $globalContext; /** * @var TranslatorInterface */ private $translator; /** * @var null|string */ private $translationDomain; /** * @var MetadataInterface */ private $metadata; /** * @var mixed */ private $value; /** * @var string */ private $group; /** * @var string */ private $propertyPath; /** * Creates a new execution context. * * @param GlobalExecutionContextInterface $globalContext The global context storing node-independent state. * @param TranslatorInterface $translator The translator for translating violation messages. * @param null|string $translationDomain The domain of the validation messages. * @param MetadataInterface $metadata The metadata of the validated node. * @param mixed $value The value of the validated node. * @param string $group The current validation group. * @param string $propertyPath The property path to the current node. */ public function __construct(GlobalExecutionContextInterface $globalContext, TranslatorInterface $translator, $translationDomain = null, MetadataInterface $metadata = null, $value = null, $group = null, $propertyPath = '') { if (null === $group) { $group = Constraint::DEFAULT_GROUP; } $this->globalContext = $globalContext; $this->translator = $translator; $this->translationDomain = $translationDomain; $this->metadata = $metadata; $this->value = $value; $this->propertyPath = $propertyPath; $this->group = $group; } /** * {@inheritdoc} */ public function addViolation($message, array $params = array(), $invalidValue = null, $plural = null, $code = null) { if (null === $plural) { $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain); } else { try { $translatedMessage = $this->translator->transChoice($message, $plural, $params, $this->translationDomain); } catch (\InvalidArgumentException $e) { $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain); } } $this->globalContext->getViolations()->add(new ConstraintViolation( $translatedMessage, $message, $params, $this->globalContext->getRoot(), $this->propertyPath, // check using func_num_args() to allow passing null values func_num_args() >= 3 ? $invalidValue : $this->value, $plural, $code )); } /** * {@inheritdoc} */ public function addViolationAt($subPath, $message, array $parameters = array(), $invalidValue = null, $plural = null, $code = null) { $this->globalContext->getViolations()->add(new ConstraintViolation( null === $plural ? $this->translator->trans($message, $parameters, $this->translationDomain) : $this->translator->transChoice($message, $plural, $parameters, $this->translationDomain), $message, $parameters, $this->globalContext->getRoot(), $this->getPropertyPath($subPath), // check using func_num_args() to allow passing null values func_num_args() >= 4 ? $invalidValue : $this->value, $plural, $code )); } /** * {@inheritdoc} */ public function getViolations() { return $this->globalContext->getViolations(); } /** * {@inheritdoc} */ public function getRoot() { return $this->globalContext->getRoot(); } /** * {@inheritdoc} */ public function getPropertyPath($subPath = '') { if ('' != $subPath && '' !== $this->propertyPath && '[' !== $subPath[0]) { return $this->propertyPath.'.'.$subPath; } return $this->propertyPath.$subPath; } /** * {@inheritdoc} */ public function getClassName() { if ($this->metadata instanceof ClassBasedInterface) { return $this->metadata->getClassName(); } } /** * {@inheritdoc} */ public function getPropertyName() { if ($this->metadata instanceof PropertyMetadataInterface) { return $this->metadata->getPropertyName(); } } /** * {@inheritdoc} */ public function getValue() { return $this->value; } /** * {@inheritdoc} */ public function getGroup() { return $this->group; } /** * {@inheritdoc} */ public function getMetadata() { return $this->metadata; } /** * {@inheritdoc} */ public function getMetadataFor($value) { return $this->globalContext->getMetadataFactory()->getMetadataFor($value); } /** * {@inheritdoc} */ public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false) { $propertyPath = $this->getPropertyPath($subPath); foreach ($this->resolveGroups($groups) as $group) { $this->globalContext->getVisitor()->validate($value, $group, $propertyPath, $traverse, $deep); } } /** * {@inheritdoc} */ public function validateValue($value, $constraints, $subPath = '', $groups = null) { $constraints = is_array($constraints) ? $constraints : array($constraints); if (null === $groups && '' === $subPath) { $context = clone $this; $context->value = $value; $context->executeConstraintValidators($value, $constraints); return; } $propertyPath = $this->getPropertyPath($subPath); foreach ($this->resolveGroups($groups) as $group) { $context = clone $this; $context->value = $value; $context->group = $group; $context->propertyPath = $propertyPath; $context->executeConstraintValidators($value, $constraints); } } /** * {@inheritdoc} */ public function getMetadataFactory() { return $this->globalContext->getMetadataFactory(); } /** * Executes the validators of the given constraints for the given value. * * @param mixed $value The value to validate. * @param Constraint[] $constraints The constraints to match against. */ private function executeConstraintValidators($value, array $constraints) { foreach ($constraints as $constraint) { $validator = $this->globalContext->getValidatorFactory()->getInstance($constraint); $validator->initialize($this); $validator->validate($value, $constraint); } } /** * Returns an array of group names. * * @param null|string|string[] $groups The groups to resolve. If a single string is * passed, it is converted to an array. If null * is passed, an array containing the current * group of the context is returned. * * @return array An array of validation groups. */ private function resolveGroups($groups) { return $groups ? (array) $groups : (array) $this->group; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Entry point for the Validator component. * * @author Bernhard Schussek */ final class Validation { /** * The Validator API provided by Symfony 2.4 and older. */ const API_VERSION_2_4 = 1; /** * The Validator API provided by Symfony 2.5 and newer. */ const API_VERSION_2_5 = 2; /** * The Validator API provided by Symfony 2.5 and newer with a backwards * compatibility layer for 2.4 and older. */ const API_VERSION_2_5_BC = 3; /** * Creates a new validator. * * If you want to configure the validator, use * {@link createValidatorBuilder()} instead. * * @return ValidatorInterface The new validator. */ public static function createValidator() { return self::createValidatorBuilder()->getValidator(); } /** * Creates a configurable builder for validator objects. * * @return ValidatorBuilderInterface The new builder. */ public static function createValidatorBuilder() { return new ValidatorBuilder(); } /** * This class cannot be instantiated. */ private function __construct() { } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base ExceptionInterface for the Validator component. * * @author Bernhard Schussek */ interface ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * @since 2.5 * @author Bernhard Schussek */ class UnsupportedMetadataException extends InvalidArgumentException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base InvalidArgumentException for the Validator component. * * @author Bernhard Schussek */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class MappingException extends ValidatorException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * @author Bernhard Schussek */ class NoSuchMetadataException extends ValidatorException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base RuntimeException for the Validator component. * * @author Bernhard Schussek */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class ConstraintDefinitionException extends ValidatorException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class InvalidOptionsException extends ValidatorException { private $options; public function __construct($message, array $options) { parent::__construct($message); $this->options = $options; } public function getOptions() { return $this->options; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class GroupDefinitionException extends ValidatorException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base BadMethodCallException for the Validator component. * * @author Bernhard Schussek */ class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; /** * Base OutOfBoundsException for the Validator component. * * @author Bernhard Schussek */ class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class UnexpectedTypeException extends ValidatorException { public function __construct($value, $expectedType) { parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value))); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class MissingOptionsException extends ValidatorException { private $options; public function __construct($message, array $options) { parent::__construct($message); $this->options = $options; } public function getOptions() { return $this->options; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Exception; class ValidatorException extends RuntimeException { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; /** * Specifies whether an object should be cascaded. * * Cascading is relevant for any node type but class nodes. If such a node * contains an object of value, and if cascading is enabled, then the node * traverser will try to find class metadata for that object and validate the * object against that metadata. * * If no metadata is found for a cascaded object, and if that object implements * {@link \Traversable}, the node traverser will iterate over the object and * cascade each object or collection contained within, unless iteration is * prohibited by the specified {@link TraversalStrategy}. * * Although the constants currently represent a boolean switch, they are * implemented as bit mask in order to allow future extensions. * * @since 2.5 * @author Bernhard Schussek * * @see TraversalStrategy */ class CascadingStrategy { /** * Specifies that a node should not be cascaded. */ const NONE = 1; /** * Specifies that a node should be cascaded. */ const CASCADE = 2; /** * Not instantiable. */ private function __construct() { } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Factory; use Symfony\Component\Validator\MetadataFactoryInterface as LegacyMetadataFactoryInterface; /** * Returns {@link \Symfony\Component\Validator\Mapping\MetadataInterface} instances for values. * * @since 2.5 * @author Bernhard Schussek */ interface MetadataFactoryInterface extends LegacyMetadataFactoryInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Factory; /** * Metadata factory that does not store metadata. * * This implementation is useful if you want to validate values against * constraints only and you don't need to add constraints to classes and * properties. * * @author Fabien Potencier */ class BlackHoleMetadataFactory implements MetadataFactoryInterface { /** * {@inheritdoc} */ public function getMetadataFor($value) { throw new \LogicException('This class does not support metadata.'); } /** * {@inheritdoc} */ public function hasMetadataFor($value) { return false; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Factory; use Symfony\Component\Validator\Exception\NoSuchMetadataException; use Symfony\Component\Validator\Mapping\Cache\CacheInterface; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\ClassMetadataInterface; use Symfony\Component\Validator\Mapping\Loader\LoaderChain; use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; /** * Creates new {@link ClassMetadataInterface} instances. * * Whenever {@link getMetadataFor()} is called for the first time with a given * class name or object of that class, a new metadata instance is created and * returned. On subsequent requests for the same class, the same metadata * instance will be returned. * * You can optionally pass a {@link LoaderInterface} instance to the constructor. * Whenever a new metadata instance is created, it is passed to the loader, * which can configure the metadata based on configuration loaded from the * filesystem or a database. If you want to use multiple loaders, wrap them in a * {@link LoaderChain}. * * You can also optionally pass a {@link CacheInterface} instance to the * constructor. This cache will be used for persisting the generated metadata * between multiple PHP requests. * * @author Bernhard Schussek */ class LazyLoadingMetadataFactory implements MetadataFactoryInterface { /** * The loader for loading the class metadata * * @var LoaderInterface|null */ protected $loader; /** * The cache for caching class metadata * * @var CacheInterface|null */ protected $cache; /** * The loaded metadata, indexed by class name * * @var ClassMetadata[] */ protected $loadedClasses = array(); /** * Creates a new metadata factory. * * @param LoaderInterface|null $loader The loader for configuring new metadata * @param CacheInterface|null $cache The cache for persisting metadata * between multiple PHP requests */ public function __construct(LoaderInterface $loader = null, CacheInterface $cache = null) { $this->loader = $loader; $this->cache = $cache; } /** * {@inheritdoc} * * If the method was called with the same class name (or an object of that * class) before, the same metadata instance is returned. * * If the factory was configured with a cache, this method will first look * for an existing metadata instance in the cache. If an existing instance * is found, it will be returned without further ado. * * Otherwise, a new metadata instance is created. If the factory was * configured with a loader, the metadata is passed to the * {@link LoaderInterface::loadClassMetadata()} method for further * configuration. At last, the new object is returned. */ public function getMetadataFor($value) { if (!is_object($value) && !is_string($value)) { throw new NoSuchMetadataException(sprintf('Cannot create metadata for non-objects. Got: %s', gettype($value))); } $class = ltrim(is_object($value) ? get_class($value) : $value, '\\'); if (isset($this->loadedClasses[$class])) { return $this->loadedClasses[$class]; } if (null !== $this->cache && false !== ($this->loadedClasses[$class] = $this->cache->read($class))) { return $this->loadedClasses[$class]; } if (!class_exists($class) && !interface_exists($class)) { throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class)); } $metadata = new ClassMetadata($class); // Include constraints from the parent class if ($parent = $metadata->getReflectionClass()->getParentClass()) { $metadata->mergeConstraints($this->getMetadataFor($parent->name)); } // Include constraints from all implemented interfaces foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) { if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) { continue; } $metadata->mergeConstraints($this->getMetadataFor($interface->name)); } if (null !== $this->loader) { $this->loader->loadClassMetadata($metadata); } if (null !== $this->cache) { $this->cache->write($metadata); } return $this->loadedClasses[$class] = $metadata; } /** * {@inheritdoc} */ public function hasMetadataFor($value) { if (!is_object($value) && !is_string($value)) { return false; } $class = ltrim(is_object($value) ? get_class($value) : $value, '\\'); if (class_exists($class) || interface_exists($class)) { return true; } return false; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\MetadataInterface as LegacyMetadataInterface; /** * A container for validation metadata. * * Most importantly, the metadata stores the constraints against which an object * and its properties should be validated. * * Additionally, the metadata stores whether objects should be validated * against their class' metadata and whether traversable objects should be * traversed or not. * * @since 2.5 * @author Bernhard Schussek * * @see CascadingStrategy * @see TraversalStrategy */ interface MetadataInterface extends LegacyMetadataInterface { /** * Returns the strategy for cascading objects. * * @return int The cascading strategy * * @see CascadingStrategy */ public function getCascadingStrategy(); /** * Returns the strategy for traversing traversable objects. * * @return int The traversal strategy * * @see TraversalStrategy */ public function getTraversalStrategy(); /** * Returns all constraints of this element. * * @return Constraint[] A list of Constraint instances */ public function getConstraints(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; /** * Alias of {@link Factory\BlackHoleMetadataFactory}. * * @author Fabien Potencier * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link Factory\BlackHoleMetadataFactory} instead. */ class BlackholeMetadataFactory extends \Symfony\Component\Validator\Mapping\Factory\BlackHoleMetadataFactory { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Exception\ValidatorException; /** * Stores all metadata needed for validating a class property via its getter * method. * * A property getter is any method that is equal to the property's name, * prefixed with either "get" or "is". That method will be used to access the * property's value. * * The getter will be invoked by reflection, so the access of private and * protected getters is supported. * * This class supports serialization and cloning. * * @author Bernhard Schussek * * @see PropertyMetadataInterface */ class GetterMetadata extends MemberMetadata { /** * Constructor. * * @param string $class The class the getter is defined on * @param string $property The property which the getter returns * * @throws ValidatorException */ public function __construct($class, $property) { $getMethod = 'get'.ucfirst($property); $isMethod = 'is'.ucfirst($property); $hasMethod = 'has'.ucfirst($property); if (method_exists($class, $getMethod)) { $method = $getMethod; } elseif (method_exists($class, $isMethod)) { $method = $isMethod; } elseif (method_exists($class, $hasMethod)) { $method = $hasMethod; } else { throw new ValidatorException(sprintf('Neither of these methods exist in class %s: %s, %s, %s', $class, $getMethod, $isMethod, $hasMethod)); } parent::__construct($class, $method, $property); } /** * {@inheritdoc} */ public function getPropertyValue($object) { return $this->newReflectionMember($object)->invoke($object); } /** * {@inheritdoc} */ protected function newReflectionMember($objectOrClassName) { return new \ReflectionMethod($objectOrClassName, $this->getName()); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\ValidationVisitorInterface; /** * Stores all metadata needed for validating a class property. * * The method of accessing the property's value must be specified by subclasses * by implementing the {@link newReflectionMember()} method. * * This class supports serialization and cloning. * * @author Bernhard Schussek * * @see PropertyMetadataInterface */ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadataInterface { /** * @var string * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getClassName()} instead. */ public $class; /** * @var string * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getName()} instead. */ public $name; /** * @var string * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getPropertyName()} instead. */ public $property; /** * @var \ReflectionMethod[]|\ReflectionProperty[] */ private $reflMember = array(); /** * Constructor. * * @param string $class The name of the class this member is defined on * @param string $name The name of the member * @param string $property The property the member belongs to */ public function __construct($class, $name, $property) { $this->class = $class; $this->name = $name; $this->property = $property; } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. */ public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null) { $visitor->visit($this, $value, $group, $propertyPath); if ($this->isCascaded()) { $visitor->validate($value, $propagatedGroup ?: $group, $propertyPath, $this->isCollectionCascaded(), $this->isCollectionCascadedDeeply()); } } /** * {@inheritdoc} */ public function addConstraint(Constraint $constraint) { if (!in_array(Constraint::PROPERTY_CONSTRAINT, (array) $constraint->getTargets())) { throw new ConstraintDefinitionException(sprintf( 'The constraint %s cannot be put on properties or getters', get_class($constraint) )); } parent::addConstraint($constraint); return $this; } /** * {@inheritdoc} */ public function __sleep() { return array_merge(parent::__sleep(), array( 'class', 'name', 'property', )); } /** * Returns the name of the member. * * @return string */ public function getName() { return $this->name; } /** * {@inheritdoc} */ public function getClassName() { return $this->class; } /** * {@inheritdoc} */ public function getPropertyName() { return $this->property; } /** * Returns whether this member is public. * * @param object|string $objectOrClassName The object or the class name * * @return bool */ public function isPublic($objectOrClassName) { return $this->getReflectionMember($objectOrClassName)->isPublic(); } /** * Returns whether this member is protected. * * @param object|string $objectOrClassName The object or the class name * * @return bool */ public function isProtected($objectOrClassName) { return $this->getReflectionMember($objectOrClassName)->isProtected(); } /** * Returns whether this member is private. * * @param object|string $objectOrClassName The object or the class name * * @return bool */ public function isPrivate($objectOrClassName) { return $this->getReflectionMember($objectOrClassName)->isPrivate(); } /** * Returns whether objects stored in this member should be validated. * * @return bool * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link getCascadingStrategy()} instead. */ public function isCascaded() { return (bool) ($this->cascadingStrategy & CascadingStrategy::CASCADE); } /** * Returns whether arrays or traversable objects stored in this member * should be traversed and validated in each entry. * * @return bool * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link getTraversalStrategy()} instead. */ public function isCollectionCascaded() { return (bool) ($this->traversalStrategy & (TraversalStrategy::IMPLICIT | TraversalStrategy::TRAVERSE)); } /** * Returns whether arrays or traversable objects stored in this member * should be traversed recursively for inner arrays/traversable objects. * * @return bool * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link getTraversalStrategy()} instead. */ public function isCollectionCascadedDeeply() { return !($this->traversalStrategy & TraversalStrategy::STOP_RECURSION); } /** * Returns the reflection instance for accessing the member's value. * * @param object|string $objectOrClassName The object or the class name * * @return \ReflectionMethod|\ReflectionProperty The reflection instance */ public function getReflectionMember($objectOrClassName) { $className = is_string($objectOrClassName) ? $objectOrClassName : get_class($objectOrClassName); if (!isset($this->reflMember[$className])) { $this->reflMember[$className] = $this->newReflectionMember($objectOrClassName); } return $this->reflMember[$className]; } /** * Creates a new reflection instance for accessing the member's value. * * Must be implemented by subclasses. * * @param object|string $objectOrClassName The object or the class name * * @return \ReflectionMethod|\ReflectionProperty The reflection instance */ abstract protected function newReflectionMember($objectOrClassName); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\Traverse; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\GroupDefinitionException; use Symfony\Component\Validator\ValidationVisitorInterface; /** * Default implementation of {@link ClassMetadataInterface}. * * This class supports serialization and cloning. * * @author Bernhard Schussek * @author Fabien Potencier */ class ClassMetadata extends ElementMetadata implements ClassMetadataInterface { /** * @var string * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getClassName()} instead. */ public $name; /** * @var string * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getDefaultGroup()} instead. */ public $defaultGroup; /** * @var MemberMetadata[] * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getPropertyMetadata()} instead. */ public $members = array(); /** * @var PropertyMetadata[] * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getPropertyMetadata()} instead. */ public $properties = array(); /** * @var GetterMetadata[] * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getPropertyMetadata()} instead. */ public $getters = array(); /** * @var array * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getGroupSequence()} instead. */ public $groupSequence = array(); /** * @var bool * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link isGroupSequenceProvider()} instead. */ public $groupSequenceProvider = false; /** * The strategy for traversing traversable objects. * * By default, only instances of {@link \Traversable} are traversed. * * @var int * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getTraversalStrategy()} instead. */ public $traversalStrategy = TraversalStrategy::IMPLICIT; /** * @var \ReflectionClass */ private $reflClass; /** * Constructs a metadata for the given class. * * @param string $class */ public function __construct($class) { $this->name = $class; // class name without namespace if (false !== $nsSep = strrpos($class, '\\')) { $this->defaultGroup = substr($class, $nsSep + 1); } else { $this->defaultGroup = $class; } } /** * {@inheritdoc} * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. */ public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null) { if (null === $propagatedGroup && Constraint::DEFAULT_GROUP === $group && ($this->hasGroupSequence() || $this->isGroupSequenceProvider())) { if ($this->hasGroupSequence()) { $groups = $this->getGroupSequence(); } else { $groups = $value->getGroupSequence(); } foreach ($groups as $group) { $this->accept($visitor, $value, $group, $propertyPath, Constraint::DEFAULT_GROUP); if (count($visitor->getViolations()) > 0) { break; } } return; } $visitor->visit($this, $value, $group, $propertyPath); if (null !== $value) { $pathPrefix = empty($propertyPath) ? '' : $propertyPath.'.'; foreach ($this->getConstrainedProperties() as $property) { foreach ($this->getPropertyMetadata($property) as $member) { $member->accept($visitor, $member->getPropertyValue($value), $group, $pathPrefix.$property, $propagatedGroup); } } } } /** * {@inheritdoc} */ public function __sleep() { $parentProperties = parent::__sleep(); // Don't store the cascading strategy. Classes never cascade. unset($parentProperties[array_search('cascadingStrategy', $parentProperties)]); return array_merge($parentProperties, array( 'getters', 'groupSequence', 'groupSequenceProvider', 'members', 'name', 'properties', 'defaultGroup', )); } /** * {@inheritdoc} */ public function getClassName() { return $this->name; } /** * Returns the name of the default group for this class. * * For each class, the group "Default" is an alias for the group * "", where is the non-namespaced name of the * class. All constraints implicitly or explicitly assigned to group * "Default" belong to both of these groups, unless the class defines * a group sequence. * * If a class defines a group sequence, validating the class in "Default" * will validate the group sequence. The constraints assigned to "Default" * can still be validated by validating the class in "". * * @return string The name of the default group */ public function getDefaultGroup() { return $this->defaultGroup; } /** * {@inheritdoc} */ public function addConstraint(Constraint $constraint) { if (!in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets())) { throw new ConstraintDefinitionException(sprintf( 'The constraint "%s" cannot be put on classes.', get_class($constraint) )); } if ($constraint instanceof Valid) { throw new ConstraintDefinitionException(sprintf( 'The constraint "%s" cannot be put on classes.', get_class($constraint) )); } if ($constraint instanceof Traverse) { if ($constraint->traverse) { // If traverse is true, traversal should be explicitly enabled $this->traversalStrategy = TraversalStrategy::TRAVERSE; } else { // If traverse is false, traversal should be explicitly disabled $this->traversalStrategy = TraversalStrategy::NONE; } // The constraint is not added return $this; } $constraint->addImplicitGroupName($this->getDefaultGroup()); parent::addConstraint($constraint); return $this; } /** * Adds a constraint to the given property. * * @param string $property The name of the property * @param Constraint $constraint The constraint * * @return ClassMetadata This object */ public function addPropertyConstraint($property, Constraint $constraint) { if (!isset($this->properties[$property])) { $this->properties[$property] = new PropertyMetadata($this->getClassName(), $property); $this->addPropertyMetadata($this->properties[$property]); } $constraint->addImplicitGroupName($this->getDefaultGroup()); $this->properties[$property]->addConstraint($constraint); return $this; } /** * @param string $property * @param Constraint[] $constraints * * @return ClassMetadata */ public function addPropertyConstraints($property, array $constraints) { foreach ($constraints as $constraint) { $this->addPropertyConstraint($property, $constraint); } return $this; } /** * Adds a constraint to the getter of the given property. * * The name of the getter is assumed to be the name of the property with an * uppercased first letter and either the prefix "get" or "is". * * @param string $property The name of the property * @param Constraint $constraint The constraint * * @return ClassMetadata This object */ public function addGetterConstraint($property, Constraint $constraint) { if (!isset($this->getters[$property])) { $this->getters[$property] = new GetterMetadata($this->getClassName(), $property); $this->addPropertyMetadata($this->getters[$property]); } $constraint->addImplicitGroupName($this->getDefaultGroup()); $this->getters[$property]->addConstraint($constraint); return $this; } /** * @param string $property * @param Constraint[] $constraints * * @return ClassMetadata */ public function addGetterConstraints($property, array $constraints) { foreach ($constraints as $constraint) { $this->addGetterConstraint($property, $constraint); } return $this; } /** * Merges the constraints of the given metadata into this object. * * @param ClassMetadata $source The source metadata */ public function mergeConstraints(ClassMetadata $source) { foreach ($source->getConstraints() as $constraint) { $this->addConstraint(clone $constraint); } foreach ($source->getConstrainedProperties() as $property) { foreach ($source->getPropertyMetadata($property) as $member) { $member = clone $member; foreach ($member->getConstraints() as $constraint) { $constraint->addImplicitGroupName($this->getDefaultGroup()); } $this->addPropertyMetadata($member); if ($member instanceof MemberMetadata && !$member->isPrivate($this->name)) { $property = $member->getPropertyName(); if ($member instanceof PropertyMetadata && !isset($this->properties[$property])) { $this->properties[$property] = $member; } elseif ($member instanceof GetterMetadata && !isset($this->getters[$property])) { $this->getters[$property] = $member; } } } } } /** * Adds a member metadata. * * @param MemberMetadata $metadata * * @deprecated Deprecated since version 2.6, to be removed in 3.0. */ protected function addMemberMetadata(MemberMetadata $metadata) { $this->addPropertyMetadata($metadata); } /** * Returns true if metadatas of members is present for the given property. * * @param string $property The name of the property * * @return bool * * @deprecated Deprecated since version 2.6, to be removed in 3.0. Use {@link hasPropertyMetadata} instead. */ public function hasMemberMetadatas($property) { return $this->hasPropertyMetadata($property); } /** * Returns all metadatas of members describing the given property. * * @param string $property The name of the property * * @return MemberMetadata[] An array of MemberMetadata * * @deprecated Deprecated since version 2.6, to be removed in 3.0. Use {@link getPropertyMetadata} instead. */ public function getMemberMetadatas($property) { return $this->getPropertyMetadata($property); } /** * {@inheritdoc} */ public function hasPropertyMetadata($property) { return array_key_exists($property, $this->members); } /** * {@inheritdoc} */ public function getPropertyMetadata($property) { if (!isset($this->members[$property])) { return array(); } return $this->members[$property]; } /** * {@inheritdoc} */ public function getConstrainedProperties() { return array_keys($this->members); } /** * Sets the default group sequence for this class. * * @param array $groupSequence An array of group names * * @return ClassMetadata * * @throws GroupDefinitionException */ public function setGroupSequence($groupSequence) { if ($this->isGroupSequenceProvider()) { throw new GroupDefinitionException('Defining a static group sequence is not allowed with a group sequence provider'); } if (is_array($groupSequence)) { $groupSequence = new GroupSequence($groupSequence); } if (in_array(Constraint::DEFAULT_GROUP, $groupSequence->groups, true)) { throw new GroupDefinitionException(sprintf('The group "%s" is not allowed in group sequences', Constraint::DEFAULT_GROUP)); } if (!in_array($this->getDefaultGroup(), $groupSequence->groups, true)) { throw new GroupDefinitionException(sprintf('The group "%s" is missing in the group sequence', $this->getDefaultGroup())); } $this->groupSequence = $groupSequence; return $this; } /** * {@inheritdoc} */ public function hasGroupSequence() { return count($this->groupSequence) > 0; } /** * {@inheritdoc} */ public function getGroupSequence() { return $this->groupSequence; } /** * Returns a ReflectionClass instance for this class. * * @return \ReflectionClass */ public function getReflectionClass() { if (!$this->reflClass) { $this->reflClass = new \ReflectionClass($this->getClassName()); } return $this->reflClass; } /** * Sets whether a group sequence provider should be used. * * @param bool $active * * @throws GroupDefinitionException */ public function setGroupSequenceProvider($active) { if ($this->hasGroupSequence()) { throw new GroupDefinitionException('Defining a group sequence provider is not allowed with a static group sequence'); } if (!$this->getReflectionClass()->implementsInterface('Symfony\Component\Validator\GroupSequenceProviderInterface')) { throw new GroupDefinitionException(sprintf('Class "%s" must implement GroupSequenceProviderInterface', $this->name)); } $this->groupSequenceProvider = $active; } /** * {@inheritdoc} */ public function isGroupSequenceProvider() { return $this->groupSequenceProvider; } /** * Class nodes are never cascaded. * * {@inheritdoc} */ public function getCascadingStrategy() { return CascadingStrategy::NONE; } /** * Adds a property metadata. * * @param PropertyMetadataInterface $metadata */ private function addPropertyMetadata(PropertyMetadataInterface $metadata) { $property = $metadata->getPropertyName(); $this->members[$property][] = $metadata; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\ClassBasedInterface; use Symfony\Component\Validator\PropertyMetadataInterface as LegacyPropertyMetadataInterface; /** * Stores all metadata needed for validating the value of a class property. * * Most importantly, the metadata stores the constraints against which the * property's value should be validated. * * Additionally, the metadata stores whether objects stored in the property * should be validated against their class' metadata and whether traversable * objects should be traversed or not. * * @since 2.5 * @author Bernhard Schussek * * @see MetadataInterface * @see CascadingStrategy * @see TraversalStrategy */ interface PropertyMetadataInterface extends MetadataInterface, LegacyPropertyMetadataInterface, ClassBasedInterface { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Exception\ValidatorException; /** * Stores all metadata needed for validating a class property. * * The value of the property is obtained by directly accessing the property. * The property will be accessed by reflection, so the access of private and * protected properties is supported. * * This class supports serialization and cloning. * * @author Bernhard Schussek * * @see PropertyMetadataInterface */ class PropertyMetadata extends MemberMetadata { /** * Constructor. * * @param string $class The class this property is defined on * @param string $name The name of this property * * @throws ValidatorException */ public function __construct($class, $name) { if (!property_exists($class, $name)) { throw new ValidatorException(sprintf('Property %s does not exist in class %s', $name, $class)); } parent::__construct($class, $name, $name); } /** * {@inheritdoc} */ public function getPropertyValue($object) { return $this->getReflectionMember($object)->getValue($object); } /** * {@inheritdoc} */ protected function newReflectionMember($objectOrClassName) { $class = new \ReflectionClass($objectOrClassName); while (!$class->hasProperty($this->getName())) { $class = $class->getParentClass(); } $member = new \ReflectionProperty($class->getName(), $this->getName()); $member->setAccessible(true); return $member; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; /** * Alias of {@link LazyLoadingMetadataFactory}. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Use {@link LazyLoadingMetadataFactory} instead. */ class ClassMetadataFactory extends LazyLoadingMetadataFactory { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; /** * Specifies whether and how a traversable object should be traversed. * * If the node traverser traverses a node whose value is an instance of * {@link \Traversable}, and if that node is either a class node or if * cascading is enabled, then the node's traversal strategy will be checked. * Depending on the requested traversal strategy, the node traverser will * iterate over the object and cascade each object or collection returned by * the iterator. * * The traversal strategy is ignored for arrays. Arrays are always iterated. * * @since 2.1 * @author Bernhard Schussek * * @see CascadingStrategy */ class TraversalStrategy { /** * Specifies that a node's value should be iterated only if it is an * instance of {@link \Traversable}. */ const IMPLICIT = 1; /** * Specifies that a node's value should never be iterated. */ const NONE = 2; /** * Specifies that a node's value should always be iterated. If the value is * not an instance of {@link \Traversable}, an exception should be thrown. */ const TRAVERSE = 4; /** * Specifies that nested instances of {@link \Traversable} should never be * iterated. Can be combined with {@link IMPLICIT} or {@link TRAVERSE}. * * @deprecated This constant was added for backwards compatibility only. * It will be removed in Symfony 3.0. * @internal */ const STOP_RECURSION = 8; /** * Not instantiable. */ private function __construct() { } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Cache; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Persists ClassMetadata instances in a cache. * * @author Bernhard Schussek */ interface CacheInterface { /** * Returns whether metadata for the given class exists in the cache. * * @param string $class */ public function has($class); /** * Returns the metadata for the given class from the cache. * * @param string $class Class Name * * @return ClassMetadata|false A ClassMetadata instance or false on miss */ public function read($class); /** * Stores a class metadata in the cache. * * @param ClassMetadata $metadata A Class Metadata */ public function write(ClassMetadata $metadata); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Cache; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * @deprecated Deprecated since version 2.5, to be removed in 3.0. * Use DoctrineCache with Doctrine\Common\Cache\ApcCache instead. */ class ApcCache implements CacheInterface { private $prefix; public function __construct($prefix) { if (!extension_loaded('apc')) { throw new \RuntimeException('Unable to use ApcCache to cache validator mappings as APC is not enabled.'); } $this->prefix = $prefix; } public function has($class) { if (!function_exists('apc_exists')) { $exists = false; apc_fetch($this->prefix.$class, $exists); return $exists; } return apc_exists($this->prefix.$class); } public function read($class) { return apc_fetch($this->prefix.$class); } public function write(ClassMetadata $metadata) { apc_store($this->prefix.$metadata->getClassName(), $metadata); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Cache; use Doctrine\Common\Cache\Cache; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Adapts a Doctrine cache to a CacheInterface. * * @author Florian Voutzinos */ final class DoctrineCache implements CacheInterface { private $cache; /** * Creates a new Doctrine cache. * * @param Cache $cache The cache to adapt */ public function __construct(Cache $cache) { $this->cache = $cache; } /** * Sets the cache to adapt. * * @param Cache $cache The cache to adapt */ public function setCache(Cache $cache) { $this->cache = $cache; } /** * {@inheritdoc} */ public function has($class) { return $this->cache->contains($class); } /** * {@inheritdoc} */ public function read($class) { return $this->cache->fetch($class); } /** * {@inheritdoc} */ public function write(ClassMetadata $metadata) { $this->cache->save($metadata->getClassName(), $metadata); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Traverse; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\BadMethodCallException; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\ValidationVisitorInterface; /** * A generic container of {@link Constraint} objects. * * This class supports serialization and cloning. * * @since 2.5 * @author Bernhard Schussek */ class GenericMetadata implements MetadataInterface { /** * @var Constraint[] * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getConstraints()} and {@link findConstraints()} instead. */ public $constraints = array(); /** * @var array * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link findConstraints()} instead. */ public $constraintsByGroup = array(); /** * The strategy for cascading objects. * * By default, objects are not cascaded. * * @var int * * @see CascadingStrategy * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getCascadingStrategy()} instead. */ public $cascadingStrategy = CascadingStrategy::NONE; /** * The strategy for traversing traversable objects. * * By default, traversable objects are not traversed. * * @var int * * @see TraversalStrategy * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use * {@link getTraversalStrategy()} instead. */ public $traversalStrategy = TraversalStrategy::NONE; /** * Returns the names of the properties that should be serialized. * * @return string[] */ public function __sleep() { return array( 'constraints', 'constraintsByGroup', 'cascadingStrategy', 'traversalStrategy', ); } /** * Clones this object. */ public function __clone() { $constraints = $this->constraints; $this->constraints = array(); $this->constraintsByGroup = array(); foreach ($constraints as $constraint) { $this->addConstraint(clone $constraint); } } /** * Adds a constraint. * * If the constraint {@link Valid} is added, the cascading strategy will be * changed to {@link CascadingStrategy::CASCADE}. Depending on the * properties $traverse and $deep of that constraint, the traversal strategy * will be set to one of the following: * * - {@link TraversalStrategy::IMPLICIT} if $traverse is enabled and $deep * is enabled * - {@link TraversalStrategy::IMPLICIT} | {@link TraversalStrategy::STOP_RECURSION} * if $traverse is enabled, but $deep is disabled * - {@link TraversalStrategy::NONE} if $traverse is disabled * * @param Constraint $constraint The constraint to add * * @return GenericMetadata This object * * @throws ConstraintDefinitionException When trying to add the * {@link Traverse} constraint */ public function addConstraint(Constraint $constraint) { if ($constraint instanceof Traverse) { throw new ConstraintDefinitionException(sprintf( 'The constraint "%s" can only be put on classes. Please use '. '"Symfony\Component\Validator\Constraints\Valid" instead.', get_class($constraint) )); } if ($constraint instanceof Valid) { $this->cascadingStrategy = CascadingStrategy::CASCADE; if ($constraint->traverse) { // Traverse unless the value is not traversable $this->traversalStrategy = TraversalStrategy::IMPLICIT; if (!$constraint->deep) { $this->traversalStrategy |= TraversalStrategy::STOP_RECURSION; } } else { $this->traversalStrategy = TraversalStrategy::NONE; } return $this; } $this->constraints[] = $constraint; foreach ($constraint->groups as $group) { $this->constraintsByGroup[$group][] = $constraint; } return $this; } /** * Adds an list of constraints. * * @param Constraint[] $constraints The constraints to add * * @return GenericMetadata This object */ public function addConstraints(array $constraints) { foreach ($constraints as $constraint) { $this->addConstraint($constraint); } return $this; } /** * {@inheritdoc} */ public function getConstraints() { return $this->constraints; } /** * Returns whether this element has any constraints. * * @return bool */ public function hasConstraints() { return count($this->constraints) > 0; } /** * {@inheritdoc} * * Aware of the global group (* group). */ public function findConstraints($group) { return isset($this->constraintsByGroup[$group]) ? $this->constraintsByGroup[$group] : array(); } /** * {@inheritdoc} */ public function getCascadingStrategy() { return $this->cascadingStrategy; } /** * {@inheritdoc} */ public function getTraversalStrategy() { return $this->traversalStrategy; } /** * Exists for compatibility with the deprecated * {@link Symfony\Component\Validator\MetadataInterface}. * * Should not be used. * * @throws BadMethodCallException * * @deprecated Implemented for backwards compatibility with Symfony < 2.5. * Will be removed in Symfony 3.0. */ public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath) { throw new BadMethodCallException('Not supported.'); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; /** * Contains the metadata of a structural element. * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. * Extend {@link GenericMetadata} instead. */ abstract class ElementMetadata extends GenericMetadata { } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Loads validation metadata by calling a static method on the loaded class. * * @author Bernhard Schussek */ class StaticMethodLoader implements LoaderInterface { /** * The name of the method to call. * * @var string */ protected $methodName; /** * Creates a new loader. * * @param string $methodName The name of the static method to call */ public function __construct($methodName = 'loadValidatorMetadata') { $this->methodName = $methodName; } /** * {@inheritdoc} */ public function loadClassMetadata(ClassMetadata $metadata) { /** @var \ReflectionClass $reflClass */ $reflClass = $metadata->getReflectionClass(); if (!$reflClass->isInterface() && $reflClass->hasMethod($this->methodName)) { $reflMethod = $reflClass->getMethod($this->methodName); if ($reflMethod->isAbstract()) { return false; } if (!$reflMethod->isStatic()) { throw new MappingException(sprintf('The method %s::%s should be static', $reflClass->name, $this->methodName)); } if ($reflMethod->getDeclaringClass()->name != $reflClass->name) { return false; } $reflMethod->invoke(null, $metadata); return true; } return false; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; /** * Base loader for loading validation metadata from a file. * * @author Bernhard Schussek * * @see YamlFileLoader * @see XmlFileLoader */ abstract class FileLoader extends AbstractLoader { /** * The file to load. * * @var string */ protected $file; /** * Creates a new loader. * * @param string $file The mapping file to load * * @throws MappingException If the file does not exist or is not readable */ public function __construct($file) { if (!is_file($file)) { throw new MappingException(sprintf('The mapping file "%s" does not exist', $file)); } if (!is_readable($file)) { throw new MappingException(sprintf('The mapping file "%s" is not readable', $file)); } if (!stream_is_local($this->file)) { throw new MappingException(sprintf('The mapping file "%s" is not a local file', $file)); } $this->file = $file; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Loads validation metadata from an XML file. * * @author Bernhard Schussek */ class XmlFileLoader extends FileLoader { /** * The XML nodes of the mapping file. * * @var \SimpleXMLElement[]|null */ protected $classes; /** * {@inheritdoc} */ public function loadClassMetadata(ClassMetadata $metadata) { if (null === $this->classes) { // This method may throw an exception. Do not modify the class' // state before it completes $xml = $this->parseFile($this->file); $this->classes = array(); foreach ($xml->namespace as $namespace) { $this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace)); } foreach ($xml->class as $class) { $this->classes[(string) $class['name']] = $class; } } if (isset($this->classes[$metadata->getClassName()])) { $classDescription = $this->classes[$metadata->getClassName()]; $this->loadClassMetadataFromXml($metadata, $classDescription); return true; } return false; } /** * Parses a collection of "constraint" XML nodes. * * @param \SimpleXMLElement $nodes The XML nodes * * @return array The Constraint instances */ protected function parseConstraints(\SimpleXMLElement $nodes) { $constraints = array(); foreach ($nodes as $node) { if (count($node) > 0) { if (count($node->value) > 0) { $options = $this->parseValues($node->value); } elseif (count($node->constraint) > 0) { $options = $this->parseConstraints($node->constraint); } elseif (count($node->option) > 0) { $options = $this->parseOptions($node->option); } else { $options = array(); } } elseif (strlen((string) $node) > 0) { $options = trim($node); } else { $options = null; } $constraints[] = $this->newConstraint((string) $node['name'], $options); } return $constraints; } /** * Parses a collection of "value" XML nodes. * * @param \SimpleXMLElement $nodes The XML nodes * * @return array The values */ protected function parseValues(\SimpleXMLElement $nodes) { $values = array(); foreach ($nodes as $node) { if (count($node) > 0) { if (count($node->value) > 0) { $value = $this->parseValues($node->value); } elseif (count($node->constraint) > 0) { $value = $this->parseConstraints($node->constraint); } else { $value = array(); } } else { $value = trim($node); } if (isset($node['key'])) { $values[(string) $node['key']] = $value; } else { $values[] = $value; } } return $values; } /** * Parses a collection of "option" XML nodes. * * @param \SimpleXMLElement $nodes The XML nodes * * @return array The options */ protected function parseOptions(\SimpleXMLElement $nodes) { $options = array(); foreach ($nodes as $node) { if (count($node) > 0) { if (count($node->value) > 0) { $value = $this->parseValues($node->value); } elseif (count($node->constraint) > 0) { $value = $this->parseConstraints($node->constraint); } else { $value = array(); } } else { $value = XmlUtils::phpize($node); if (is_string($value)) { $value = trim($value); } } $options[(string) $node['name']] = $value; } return $options; } /** * Loads the XML class descriptions from the given file. * * @param string $path The path of the XML file * * @return \SimpleXMLElement The class descriptions * * @throws MappingException If the file could not be loaded */ protected function parseFile($path) { try { $dom = XmlUtils::loadFile($path, __DIR__.'/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd'); } catch (\Exception $e) { throw new MappingException($e->getMessage(), $e->getCode(), $e); } return simplexml_import_dom($dom); } /** * Loads the validation metadata from the given XML class description. * * @param ClassMetadata $metadata The metadata to load * @param array $classDescription The XML class description */ private function loadClassMetadataFromXml(ClassMetadata $metadata, $classDescription) { foreach ($classDescription->{'group-sequence-provider'} as $_) { $metadata->setGroupSequenceProvider(true); } foreach ($classDescription->{'group-sequence'} as $groupSequence) { if (count($groupSequence->value) > 0) { $metadata->setGroupSequence($this->parseValues($groupSequence[0]->value)); } } foreach ($this->parseConstraints($classDescription->constraint) as $constraint) { $metadata->addConstraint($constraint); } foreach ($classDescription->property as $property) { foreach ($this->parseConstraints($property->constraint) as $constraint) { $metadata->addPropertyConstraint((string) $property['name'], $constraint); } } foreach ($classDescription->getter as $getter) { foreach ($this->parseConstraints($getter->constraint) as $constraint) { $metadata->addGetterConstraint((string) $getter['property'], $constraint); } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; /** * Loads validation metadata from a list of YAML files. * * @author Bulat Shakirzyanov * @author Bernhard Schussek * * @see FilesLoader */ class YamlFilesLoader extends FilesLoader { /** * {@inheritdoc} */ public function getFileLoaderInstance($file) { return new YamlFileLoader($file); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Loads validation metadata into {@link ClassMetadata} instances. * * @author Bernhard Schussek */ interface LoaderInterface { /** * Loads validation metadata into a {@link ClassMetadata} instance. * * @param ClassMetadata $metadata The metadata to load * * @return bool Whether the loader succeeded */ public function loadClassMetadata(ClassMetadata $metadata); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Doctrine\Common\Annotations\Reader; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\GroupSequenceProvider; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Loads validation metadata using a Doctrine annotation {@link Reader}. * * @author Bernhard Schussek */ class AnnotationLoader implements LoaderInterface { /** * @var Reader */ protected $reader; public function __construct(Reader $reader) { $this->reader = $reader; } /** * {@inheritdoc} */ public function loadClassMetadata(ClassMetadata $metadata) { $reflClass = $metadata->getReflectionClass(); $className = $reflClass->name; $success = false; foreach ($this->reader->getClassAnnotations($reflClass) as $constraint) { if ($constraint instanceof GroupSequence) { $metadata->setGroupSequence($constraint->groups); } elseif ($constraint instanceof GroupSequenceProvider) { $metadata->setGroupSequenceProvider(true); } elseif ($constraint instanceof Constraint) { $metadata->addConstraint($constraint); } $success = true; } foreach ($reflClass->getProperties() as $property) { if ($property->getDeclaringClass()->name === $className) { foreach ($this->reader->getPropertyAnnotations($property) as $constraint) { if ($constraint instanceof Constraint) { $metadata->addPropertyConstraint($property->name, $constraint); } $success = true; } } } foreach ($reflClass->getMethods() as $method) { if ($method->getDeclaringClass()->name === $className) { foreach ($this->reader->getMethodAnnotations($method) as $constraint) { if ($constraint instanceof Callback) { $constraint->callback = $method->getName(); $constraint->methods = null; $metadata->addConstraint($constraint); } elseif ($constraint instanceof Constraint) { if (preg_match('/^(get|is|has)(.+)$/i', $method->name, $matches)) { $metadata->addGetterConstraint(lcfirst($matches[2]), $constraint); } else { throw new MappingException(sprintf('The constraint on "%s::%s" cannot be added. Constraints can only be added on methods beginning with "get", "is" or "has".', $className, $method->name)); } } $success = true; } } } return $success; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Yaml\Parser as YamlParser; /** * Loads validation metadata from a YAML file. * * @author Bernhard Schussek */ class YamlFileLoader extends FileLoader { /** * An array of YAML class descriptions. * * @var array */ protected $classes = null; /** * Caches the used YAML parser. * * @var YamlParser */ private $yamlParser; /** * {@inheritdoc} */ public function loadClassMetadata(ClassMetadata $metadata) { if (null === $this->classes) { if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } // This method may throw an exception. Do not modify the class' // state before it completes if (false === ($classes = $this->parseFile($this->file))) { return false; } $this->classes = $classes; if (isset($this->classes['namespaces'])) { foreach ($this->classes['namespaces'] as $alias => $namespace) { $this->addNamespaceAlias($alias, $namespace); } unset($this->classes['namespaces']); } } if (isset($this->classes[$metadata->getClassName()])) { $classDescription = $this->classes[$metadata->getClassName()]; $this->loadClassMetadataFromYaml($metadata, $classDescription); return true; } return false; } /** * Parses a collection of YAML nodes. * * @param array $nodes The YAML nodes * * @return array An array of values or Constraint instances */ protected function parseNodes(array $nodes) { $values = array(); foreach ($nodes as $name => $childNodes) { if (is_numeric($name) && is_array($childNodes) && 1 === count($childNodes)) { $options = current($childNodes); if (is_array($options)) { $options = $this->parseNodes($options); } $values[] = $this->newConstraint(key($childNodes), $options); } else { if (is_array($childNodes)) { $childNodes = $this->parseNodes($childNodes); } $values[$name] = $childNodes; } } return $values; } /** * Loads the YAML class descriptions from the given file. * * @param string $path The path of the YAML file * * @return array|null The class descriptions or null, if the file was empty * * @throws \InvalidArgumentException If the file could not be loaded or did * not contain a YAML array */ private function parseFile($path) { $classes = $this->yamlParser->parse(file_get_contents($path)); // empty file if (null === $classes) { return; } // not an array if (!is_array($classes)) { throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $this->file)); } return $classes; } /** * Loads the validation metadata from the given YAML class description. * * @param ClassMetadata $metadata The metadata to load * @param array $classDescription The YAML class description */ private function loadClassMetadataFromYaml(ClassMetadata $metadata, array $classDescription) { if (isset($classDescription['group_sequence_provider'])) { $metadata->setGroupSequenceProvider( (bool) $classDescription['group_sequence_provider'] ); } if (isset($classDescription['group_sequence'])) { $metadata->setGroupSequence($classDescription['group_sequence']); } if (isset($classDescription['constraints']) && is_array($classDescription['constraints'])) { foreach ($this->parseNodes($classDescription['constraints']) as $constraint) { $metadata->addConstraint($constraint); } } if (isset($classDescription['properties']) && is_array($classDescription['properties'])) { foreach ($classDescription['properties'] as $property => $constraints) { if (null !== $constraints) { foreach ($this->parseNodes($constraints) as $constraint) { $metadata->addPropertyConstraint($property, $constraint); } } } } if (isset($classDescription['getters']) && is_array($classDescription['getters'])) { foreach ($classDescription['getters'] as $getter => $constraints) { if (null !== $constraints) { foreach ($this->parseNodes($constraints) as $constraint) { $metadata->addGetterConstraint($getter, $constraint); } } } } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; /** * Loads validation metadata from a list of XML files. * * @author Bulat Shakirzyanov * @author Bernhard Schussek * * @see FilesLoader */ class XmlFilesLoader extends FilesLoader { /** * {@inheritdoc} */ public function getFileLoaderInstance($file) { return new XmlFileLoader($file); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\MappingException; /** * Base loader for validation metadata. * * This loader supports the loading of constraints from Symfony's default * namespace (see {@link DEFAULT_NAMESPACE}) using the short class names of * those constraints. Constraints can also be loaded using their fully * qualified class names. At last, namespace aliases can be defined to load * constraints with the syntax "alias:ShortName". * * @author Bernhard Schussek */ abstract class AbstractLoader implements LoaderInterface { /** * The namespace to load constraints from by default. */ const DEFAULT_NAMESPACE = '\\Symfony\\Component\\Validator\\Constraints\\'; /** * @var array */ protected $namespaces = array(); /** * Adds a namespace alias. * * The namespace alias can be used to reference constraints from specific * namespaces in {@link newConstraint()}: * * $this->addNamespaceAlias('mynamespace', '\\Acme\\Package\\Constraints\\'); * * $constraint = $this->newConstraint('mynamespace:NotNull'); * * @param string $alias The alias * @param string $namespace The PHP namespace */ protected function addNamespaceAlias($alias, $namespace) { $this->namespaces[$alias] = $namespace; } /** * Creates a new constraint instance for the given constraint name. * * @param string $name The constraint name. Either a constraint relative * to the default constraint namespace, or a fully * qualified class name. Alternatively, the constraint * may be preceded by a namespace alias and a colon. * The namespace alias must have been defined using * {@link addNamespaceAlias()}. * @param mixed $options The constraint options * * @return Constraint * * @throws MappingException If the namespace prefix is undefined */ protected function newConstraint($name, $options = null) { if (strpos($name, '\\') !== false && class_exists($name)) { $className = (string) $name; } elseif (strpos($name, ':') !== false) { list($prefix, $className) = explode(':', $name, 2); if (!isset($this->namespaces[$prefix])) { throw new MappingException(sprintf('Undefined namespace prefix "%s"', $prefix)); } $className = $this->namespaces[$prefix].$className; } else { $className = self::DEFAULT_NAMESPACE.$name; } return new $className($options); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; /** * Loads validation metadata from multiple {@link LoaderInterface} instances. * * Pass the loaders when constructing the chain. Once * {@link loadClassMetadata()} is called, that method will be called on all * loaders in the chain. * * @author Bernhard Schussek */ class LoaderChain implements LoaderInterface { /** * @var LoaderInterface[] */ protected $loaders; /** * @param LoaderInterface[] $loaders The metadata loaders to use * * @throws MappingException If any of the loaders has an invalid type */ public function __construct(array $loaders) { foreach ($loaders as $loader) { if (!$loader instanceof LoaderInterface) { throw new MappingException(sprintf('Class %s is expected to implement LoaderInterface', get_class($loader))); } } $this->loaders = $loaders; } /** * {@inheritdoc} */ public function loadClassMetadata(ClassMetadata $metadata) { $success = false; foreach ($this->loaders as $loader) { $success = $loader->loadClassMetadata($metadata) || $success; } return $success; } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping\Loader; /** * Base loader for loading validation metadata from a list of files. * * @author Bulat Shakirzyanov * @author Bernhard Schussek * * @see YamlFilesLoader * @see XmlFilesLoader */ abstract class FilesLoader extends LoaderChain { /** * Creates a new loader. * * @param array $paths An array of file paths */ public function __construct(array $paths) { parent::__construct($this->getFileLoaders($paths)); } /** * Returns an array of file loaders for the given file paths. * * @param array $paths An array of file paths * * @return LoaderInterface[] The metadata loaders */ protected function getFileLoaders($paths) { $loaders = array(); foreach ($paths as $path) { $loaders[] = $this->getFileLoaderInstance($path); } return $loaders; } /** * Creates a loader for the given file path. * * @param string $path The file path * * @return LoaderInterface The created loader */ abstract protected function getFileLoaderInstance($path); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Mapping; use Symfony\Component\Validator\ClassBasedInterface; use Symfony\Component\Validator\PropertyMetadataContainerInterface as LegacyPropertyMetadataContainerInterface; /** * Stores all metadata needed for validating objects of specific class. * * Most importantly, the metadata stores the constraints against which an object * and its properties should be validated. * * Additionally, the metadata stores whether the "Default" group is overridden * by a group sequence for that class and whether instances of that class * should be traversed or not. * * @since 2.5 * @author Bernhard Schussek * * @see MetadataInterface * @see \Symfony\Component\Validator\Constraints\GroupSequence * @see \Symfony\Component\Validator\GroupSequenceProviderInterface * @see TraversalStrategy */ interface ClassMetadataInterface extends MetadataInterface, LegacyPropertyMetadataContainerInterface, ClassBasedInterface { /** * Returns the names of all constrained properties. * * @return string[] A list of property names */ public function getConstrainedProperties(); /** * Returns whether the "Default" group is overridden by a group sequence. * * If it is, you can access the group sequence with {@link getGroupSequence()}. * * @return bool Returns true if the "Default" group is overridden * * @see \Symfony\Component\Validator\Constraints\GroupSequence */ public function hasGroupSequence(); /** * Returns the group sequence that overrides the "Default" group for this * class. * * @return \Symfony\Component\Validator\Constraints\GroupSequence|null The group sequence or null * * @see \Symfony\Component\Validator\Constraints\GroupSequence */ public function getGroupSequence(); /** * Returns whether the "Default" group is overridden by a dynamic group * sequence obtained by the validated objects. * * If this method returns true, the class must implement * {@link \Symfony\Component\Validator\GroupSequenceProviderInterface}. * This interface will be used to obtain the group sequence when an object * of this class is validated. * * @return bool Returns true if the "Default" group is overridden by * a dynamic group sequence * * @see \Symfony\Component\Validator\GroupSequenceProviderInterface */ public function isGroupSequenceProvider(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Validator; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; /** * Validates PHP values against constraints. * * @since 2.5 * @author Bernhard Schussek */ interface ValidatorInterface extends MetadataFactoryInterface { /** * Validates a value against a constraint or a list of constraints. * * If no constraint is passed, the constraint * {@link \Symfony\Component\Validator\Constraints\Valid} is assumed. * * @param mixed $value The value to validate * @param Constraint|Constraint[] $constraints The constraint(s) to validate * against * @param array|null $groups The validation groups to * validate. If none is given, * "Default" is assumed * * @return ConstraintViolationListInterface A list of constraint violations. * If the list is empty, validation * succeeded */ public function validate($value, $constraints = null, $groups = null); /** * Validates a property of an object against the constraints specified * for this property. * * @param object $object The object * @param string $propertyName The name of the validated property * @param array|null $groups The validation groups to validate. If * none is given, "Default" is assumed * * @return ConstraintViolationListInterface A list of constraint violations. * If the list is empty, validation * succeeded */ public function validateProperty($object, $propertyName, $groups = null); /** * Validates a value against the constraints specified for an object's * property. * * @param object|string $objectOrClass The object or its class name * @param string $propertyName The name of the property * @param mixed $value The value to validate against the * property's constraints * @param array|null $groups The validation groups to validate. If * none is given, "Default" is assumed * * @return ConstraintViolationListInterface A list of constraint violations. * If the list is empty, validation * succeeded */ public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null); /** * Starts a new validation context and returns a validator for that context. * * The returned validator collects all violations generated within its * context. You can access these violations with the * {@link ContextualValidatorInterface::getViolations()} method. * * @return ContextualValidatorInterface The validator for the new context */ public function startContext(); /** * Returns a validator in the given execution context. * * The returned validator adds all generated violations to the given * context. * * @param ExecutionContextInterface $context The execution context * * @return ContextualValidatorInterface The validator for that context */ public function inContext(ExecutionContextInterface $context); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Validator; use Symfony\Component\Validator\ConstraintValidatorFactoryInterface; use Symfony\Component\Validator\Context\ExecutionContextFactoryInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\ObjectInitializerInterface; /** * Recursive implementation of {@link ValidatorInterface}. * * @since 2.5 * @author Bernhard Schussek */ class RecursiveValidator implements ValidatorInterface { /** * @var ExecutionContextFactoryInterface */ protected $contextFactory; /** * @var MetadataFactoryInterface */ protected $metadataFactory; /** * @var ConstraintValidatorFactoryInterface */ protected $validatorFactory; /** * @var ObjectInitializerInterface[] */ protected $objectInitializers; /** * Creates a new validator. * * @param ExecutionContextFactoryInterface $contextFactory The factory for * creating new contexts * @param MetadataFactoryInterface $metadataFactory The factory for * fetching the metadata * of validated objects * @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating * constraint validators * @param ObjectInitializerInterface[] $objectInitializers The object initializers */ public function __construct(ExecutionContextFactoryInterface $contextFactory, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, array $objectInitializers = array()) { $this->contextFactory = $contextFactory; $this->metadataFactory = $metadataFactory; $this->validatorFactory = $validatorFactory; $this->objectInitializers = $objectInitializers; } /** * {@inheritdoc} */ public function startContext($root = null) { return new RecursiveContextualValidator( $this->contextFactory->createContext($this, $root), $this->metadataFactory, $this->validatorFactory, $this->objectInitializers ); } /** * {@inheritdoc} */ public function inContext(ExecutionContextInterface $context) { return new RecursiveContextualValidator( $context, $this->metadataFactory, $this->validatorFactory, $this->objectInitializers ); } /** * {@inheritdoc} */ public function getMetadataFor($object) { return $this->metadataFactory->getMetadataFor($object); } /** * {@inheritdoc} */ public function hasMetadataFor($object) { return $this->metadataFactory->hasMetadataFor($object); } /** * {@inheritdoc} */ public function validate($value, $constraints = null, $groups = null) { return $this->startContext($value) ->validate($value, $constraints, $groups) ->getViolations(); } /** * {@inheritdoc} */ public function validateProperty($object, $propertyName, $groups = null) { return $this->startContext($object) ->validateProperty($object, $propertyName, $groups) ->getViolations(); } /** * {@inheritdoc} */ public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null) { // If a class name is passed, take $value as root return $this->startContext(is_object($objectOrClass) ? $objectOrClass : $value) ->validatePropertyValue($objectOrClass, $propertyName, $value, $groups) ->getViolations(); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Validator; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintViolationListInterface; /** * A validator in a specific execution context. * * @since 2.5 * @author Bernhard Schussek */ interface ContextualValidatorInterface { /** * Appends the given path to the property path of the context. * * If called multiple times, the path will always be reset to the context's * original path with the given path appended to it. * * @param string $path The path to append * * @return ContextualValidatorInterface This validator */ public function atPath($path); /** * Validates a value against a constraint or a list of constraints. * * If no constraint is passed, the constraint * {@link \Symfony\Component\Validator\Constraints\Valid} is assumed. * * @param mixed $value The value to validate * @param Constraint|Constraint[] $constraints The constraint(s) to validate * against * @param array|null $groups The validation groups to * validate. If none is given, * "Default" is assumed * * @return ContextualValidatorInterface This validator */ public function validate($value, $constraints = null, $groups = null); /** * Validates a property of an object against the constraints specified * for this property. * * @param object $object The object * @param string $propertyName The name of the validated property * @param array|null $groups The validation groups to validate. If * none is given, "Default" is assumed * * @return ContextualValidatorInterface This validator */ public function validateProperty($object, $propertyName, $groups = null); /** * Validates a value against the constraints specified for an object's * property. * * @param object|string $objectOrClass The object or its class name * @param string $propertyName The name of the property * @param mixed $value The value to validate against the * property's constraints * @param array|null $groups The validation groups to validate. If * none is given, "Default" is assumed * * @return ContextualValidatorInterface This validator */ public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null); /** * Returns the violations that have been generated so far in the context * of the validator. * * @return ConstraintViolationListInterface The constraint violations */ public function getViolations(); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Validator; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\ConstraintValidatorFactoryInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\NoSuchMetadataException; use Symfony\Component\Validator\Exception\RuntimeException; use Symfony\Component\Validator\Exception\UnsupportedMetadataException; use Symfony\Component\Validator\Exception\ValidatorException; use Symfony\Component\Validator\Mapping\CascadingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadataInterface; use Symfony\Component\Validator\Mapping\GenericMetadata; use Symfony\Component\Validator\Mapping\MetadataInterface; use Symfony\Component\Validator\Mapping\PropertyMetadataInterface; use Symfony\Component\Validator\Mapping\TraversalStrategy; use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\ObjectInitializerInterface; use Symfony\Component\Validator\Util\PropertyPath; /** * Recursive implementation of {@link ContextualValidatorInterface}. * * @since 2.5 * * @author Bernhard Schussek */ class RecursiveContextualValidator implements ContextualValidatorInterface { /** * @var ExecutionContextInterface */ private $context; /** * @var MetadataFactoryInterface */ private $metadataFactory; /** * @var ConstraintValidatorFactoryInterface */ private $validatorFactory; /** * @var ObjectInitializerInterface[] */ private $objectInitializers; /** * Creates a validator for the given context. * * @param ExecutionContextInterface $context The execution context * @param MetadataFactoryInterface $metadataFactory The factory for * fetching the metadata * of validated objects * @param ConstraintValidatorFactoryInterface $validatorFactory The factory for creating * constraint validators * @param ObjectInitializerInterface[] $objectInitializers The object initializers */ public function __construct(ExecutionContextInterface $context, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, array $objectInitializers = array()) { $this->context = $context; $this->defaultPropertyPath = $context->getPropertyPath(); $this->defaultGroups = array($context->getGroup() ?: Constraint::DEFAULT_GROUP); $this->metadataFactory = $metadataFactory; $this->validatorFactory = $validatorFactory; $this->objectInitializers = $objectInitializers; } /** * {@inheritdoc} */ public function atPath($path) { $this->defaultPropertyPath = $this->context->getPropertyPath($path); return $this; } /** * {@inheritdoc} */ public function validate($value, $constraints = null, $groups = null) { $groups = $groups ? $this->normalizeGroups($groups) : $this->defaultGroups; $previousValue = $this->context->getValue(); $previousObject = $this->context->getObject(); $previousMetadata = $this->context->getMetadata(); $previousPath = $this->context->getPropertyPath(); $previousGroup = $this->context->getGroup(); // If explicit constraints are passed, validate the value against // those constraints if (null !== $constraints) { // You can pass a single constraint or an array of constraints // Make sure to deal with an array in the rest of the code if (!is_array($constraints)) { $constraints = array($constraints); } $metadata = new GenericMetadata(); $metadata->addConstraints($constraints); $this->validateGenericNode( $value, null, is_object($value) ? spl_object_hash($value) : null, $metadata, $this->defaultPropertyPath, $groups, null, TraversalStrategy::IMPLICIT, $this->context ); $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath); $this->context->setGroup($previousGroup); return $this; } // If an object is passed without explicit constraints, validate that // object against the constraints defined for the object's class if (is_object($value)) { $this->validateObject( $value, $this->defaultPropertyPath, $groups, TraversalStrategy::IMPLICIT, $this->context ); $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath); $this->context->setGroup($previousGroup); return $this; } // If an array is passed without explicit constraints, validate each // object in the array if (is_array($value)) { $this->validateEachObjectIn( $value, $this->defaultPropertyPath, $groups, true, $this->context ); $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath); $this->context->setGroup($previousGroup); return $this; } throw new RuntimeException(sprintf( 'Cannot validate values of type "%s" automatically. Please '. 'provide a constraint.', gettype($value) )); } /** * {@inheritdoc} */ public function validateProperty($object, $propertyName, $groups = null) { $classMetadata = $this->metadataFactory->getMetadataFor($object); if (!$classMetadata instanceof ClassMetadataInterface) { // Cannot be UnsupportedMetadataException because of BC with // Symfony < 2.5 throw new ValidatorException(sprintf( 'The metadata factory should return instances of '. '"\Symfony\Component\Validator\Mapping\ClassMetadataInterface", '. 'got: "%s".', is_object($classMetadata) ? get_class($classMetadata) : gettype($classMetadata) )); } $propertyMetadatas = $classMetadata->getPropertyMetadata($propertyName); $groups = $groups ? $this->normalizeGroups($groups) : $this->defaultGroups; $cacheKey = spl_object_hash($object); $propertyPath = PropertyPath::append($this->defaultPropertyPath, $propertyName); $previousValue = $this->context->getValue(); $previousObject = $this->context->getObject(); $previousMetadata = $this->context->getMetadata(); $previousPath = $this->context->getPropertyPath(); $previousGroup = $this->context->getGroup(); foreach ($propertyMetadatas as $propertyMetadata) { $propertyValue = $propertyMetadata->getPropertyValue($object); $this->validateGenericNode( $propertyValue, $object, $cacheKey.':'.$propertyName, $propertyMetadata, $propertyPath, $groups, null, TraversalStrategy::IMPLICIT, $this->context ); } $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath); $this->context->setGroup($previousGroup); return $this; } /** * {@inheritdoc} */ public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null) { $classMetadata = $this->metadataFactory->getMetadataFor($objectOrClass); if (!$classMetadata instanceof ClassMetadataInterface) { // Cannot be UnsupportedMetadataException because of BC with // Symfony < 2.5 throw new ValidatorException(sprintf( 'The metadata factory should return instances of '. '"\Symfony\Component\Validator\Mapping\ClassMetadataInterface", '. 'got: "%s".', is_object($classMetadata) ? get_class($classMetadata) : gettype($classMetadata) )); } $propertyMetadatas = $classMetadata->getPropertyMetadata($propertyName); $groups = $groups ? $this->normalizeGroups($groups) : $this->defaultGroups; if (is_object($objectOrClass)) { $object = $objectOrClass; $cacheKey = spl_object_hash($objectOrClass); $propertyPath = PropertyPath::append($this->defaultPropertyPath, $propertyName); } else { // $objectOrClass contains a class name $object = null; $cacheKey = null; $propertyPath = $this->defaultPropertyPath; } $previousValue = $this->context->getValue(); $previousObject = $this->context->getObject(); $previousMetadata = $this->context->getMetadata(); $previousPath = $this->context->getPropertyPath(); $previousGroup = $this->context->getGroup(); foreach ($propertyMetadatas as $propertyMetadata) { $this->validateGenericNode( $value, $object, $cacheKey.':'.$propertyName, $propertyMetadata, $propertyPath, $groups, null, TraversalStrategy::IMPLICIT, $this->context ); } $this->context->setNode($previousValue, $previousObject, $previousMetadata, $previousPath); $this->context->setGroup($previousGroup); return $this; } /** * {@inheritdoc} */ public function getViolations() { return $this->context->getViolations(); } /** * Normalizes the given group or list of groups to an array. * * @param mixed $groups The groups to normalize * * @return array A group array */ protected function normalizeGroups($groups) { if (is_array($groups)) { return $groups; } return array($groups); } /** * Validates an object against the constraints defined for its class. * * If no metadata is available for the class, but the class is an instance * of {@link \Traversable} and the selected traversal strategy allows * traversal, the object will be iterated and each nested object will be * validated instead. * * @param object $object The object to cascade * @param string $propertyPath The current property path * @param string[] $groups The validated groups * @param int $traversalStrategy The strategy for traversing the * cascaded object * @param ExecutionContextInterface $context The current execution context * * @throws NoSuchMetadataException If the object has no associated metadata * and does not implement {@link \Traversable} * or if traversal is disabled via the * $traversalStrategy argument * @throws UnsupportedMetadataException If the metadata returned by the * metadata factory does not implement * {@link ClassMetadataInterface} */ private function validateObject($object, $propertyPath, array $groups, $traversalStrategy, ExecutionContextInterface $context) { try { $classMetadata = $this->metadataFactory->getMetadataFor($object); if (!$classMetadata instanceof ClassMetadataInterface) { throw new UnsupportedMetadataException(sprintf( 'The metadata factory should return instances of '. '"Symfony\Component\Validator\Mapping\ClassMetadataInterface", '. 'got: "%s".', is_object($classMetadata) ? get_class($classMetadata) : gettype($classMetadata) )); } $this->validateClassNode( $object, spl_object_hash($object), $classMetadata, $propertyPath, $groups, null, $traversalStrategy, $context ); } catch (NoSuchMetadataException $e) { // Rethrow if not Traversable if (!$object instanceof \Traversable) { throw $e; } // Rethrow unless IMPLICIT or TRAVERSE if (!($traversalStrategy & (TraversalStrategy::IMPLICIT | TraversalStrategy::TRAVERSE))) { throw $e; } $this->validateEachObjectIn( $object, $propertyPath, $groups, $traversalStrategy & TraversalStrategy::STOP_RECURSION, $context ); } } /** * Validates each object in a collection against the constraints defined * for their classes. * * If the parameter $recursive is set to true, nested {@link \Traversable} * objects are iterated as well. Nested arrays are always iterated, * regardless of the value of $recursive. * * @param array|\Traversable $collection The collection * @param string $propertyPath The current property path * @param string[] $groups The validated groups * @param bool $stopRecursion Whether to disable * recursive iteration. For * backwards compatibility * with Symfony < 2.5. * @param ExecutionContextInterface $context The current execution context * * @see ClassNode * @see CollectionNode */ private function validateEachObjectIn($collection, $propertyPath, array $groups, $stopRecursion, ExecutionContextInterface $context) { if ($stopRecursion) { $traversalStrategy = TraversalStrategy::NONE; } else { $traversalStrategy = TraversalStrategy::IMPLICIT; } foreach ($collection as $key => $value) { if (is_array($value)) { // Arrays are always cascaded, independent of the specified // traversal strategy // (BC with Symfony < 2.5) $this->validateEachObjectIn( $value, $propertyPath.'['.$key.']', $groups, $stopRecursion, $context ); continue; } // Scalar and null values in the collection are ignored // (BC with Symfony < 2.5) if (is_object($value)) { $this->validateObject( $value, $propertyPath.'['.$key.']', $groups, $traversalStrategy, $context ); } } } /** * Validates a class node. * * A class node is a combination of an object with a {@link ClassMetadataInterface} * instance. Each class node (conceptionally) has zero or more succeeding * property nodes: * * (Article:class node) * \ * ($title:property node) * * This method validates the passed objects against all constraints defined * at class level. It furthermore triggers the validation of each of the * class' properties against the constraints for that property. * * If the selected traversal strategy allows traversal, the object is * iterated and each nested object is validated against its own constraints. * The object is not traversed if traversal is disabled in the class * metadata. * * If the passed groups contain the group "Default", the validator will * check whether the "Default" group has been replaced by a group sequence * in the class metadata. If this is the case, the group sequence is * validated instead. * * @param object $object The validated object * @param string $cacheKey The key for caching * the validated object * @param ClassMetadataInterface $metadata The class metadata of * the object * @param string $propertyPath The property path leading * to the object * @param string[] $groups The groups in which the * object should be validated * @param string[]|null $cascadedGroups The groups in which * cascaded objects should * be validated * @param int $traversalStrategy The strategy used for * traversing the object * @param ExecutionContextInterface $context The current execution context * * @throws UnsupportedMetadataException If a property metadata does not * implement {@link PropertyMetadataInterface} * @throws ConstraintDefinitionException If traversal was enabled but the * object does not implement * {@link \Traversable} * * @see TraversalStrategy */ private function validateClassNode($object, $cacheKey, ClassMetadataInterface $metadata = null, $propertyPath, array $groups, $cascadedGroups, $traversalStrategy, ExecutionContextInterface $context) { $context->setNode($object, $object, $metadata, $propertyPath); if (!$context->isObjectInitialized($cacheKey)) { foreach ($this->objectInitializers as $initializer) { $initializer->initialize($object); } $context->markObjectAsInitialized($cacheKey); } foreach ($groups as $key => $group) { // If the "Default" group is replaced by a group sequence, remember // to cascade the "Default" group when traversing the group // sequence $defaultOverridden = false; // Use the object hash for group sequences $groupHash = is_object($group) ? spl_object_hash($group) : $group; if ($context->isGroupValidated($cacheKey, $groupHash)) { // Skip this group when validating the properties and when // traversing the object unset($groups[$key]); continue; } $context->markGroupAsValidated($cacheKey, $groupHash); // Replace the "Default" group by the group sequence defined // for the class, if applicable. // This is done after checking the cache, so that // spl_object_hash() isn't called for this sequence and // "Default" is used instead in the cache. This is useful // if the getters below return different group sequences in // every call. if (Constraint::DEFAULT_GROUP === $group) { if ($metadata->hasGroupSequence()) { // The group sequence is statically defined for the class $group = $metadata->getGroupSequence(); $defaultOverridden = true; } elseif ($metadata->isGroupSequenceProvider()) { // The group sequence is dynamically obtained from the validated // object /* @var \Symfony\Component\Validator\GroupSequenceProviderInterface $object */ $group = $object->getGroupSequence(); $defaultOverridden = true; if (!$group instanceof GroupSequence) { $group = new GroupSequence($group); } } } // If the groups (=[,G3,G4]) contain a group sequence // (=), then call validateClassNode() with each entry of the // group sequence and abort if necessary (G1, G2) if ($group instanceof GroupSequence) { $this->stepThroughGroupSequence( $object, $object, $cacheKey, $metadata, $propertyPath, $traversalStrategy, $group, $defaultOverridden ? Constraint::DEFAULT_GROUP : null, $context ); // Skip the group sequence when validating properties, because // stepThroughGroupSequence() already validates the properties unset($groups[$key]); continue; } $this->validateInGroup($object, $cacheKey, $metadata, $group, $context); } // If no more groups should be validated for the property nodes, // we can safely quit if (0 === count($groups)) { return; } // Validate all properties against their constraints foreach ($metadata->getConstrainedProperties() as $propertyName) { // If constraints are defined both on the getter of a property as // well as on the property itself, then getPropertyMetadata() // returns two metadata objects, not just one foreach ($metadata->getPropertyMetadata($propertyName) as $propertyMetadata) { if (!$propertyMetadata instanceof PropertyMetadataInterface) { throw new UnsupportedMetadataException(sprintf( 'The property metadata instances should implement '. '"Symfony\Component\Validator\Mapping\PropertyMetadataInterface", '. 'got: "%s".', is_object($propertyMetadata) ? get_class($propertyMetadata) : gettype($propertyMetadata) )); } $propertyValue = $propertyMetadata->getPropertyValue($object); $this->validateGenericNode( $propertyValue, $object, $cacheKey.':'.$propertyName, $propertyMetadata, PropertyPath::append($propertyPath, $propertyName), $groups, $cascadedGroups, TraversalStrategy::IMPLICIT, $context ); } } // If no specific traversal strategy was requested when this method // was called, use the traversal strategy of the class' metadata if ($traversalStrategy & TraversalStrategy::IMPLICIT) { // Keep the STOP_RECURSION flag, if it was set $traversalStrategy = $metadata->getTraversalStrategy() | ($traversalStrategy & TraversalStrategy::STOP_RECURSION); } // Traverse only if IMPLICIT or TRAVERSE if (!($traversalStrategy & (TraversalStrategy::IMPLICIT | TraversalStrategy::TRAVERSE))) { return; } // If IMPLICIT, stop unless we deal with a Traversable if ($traversalStrategy & TraversalStrategy::IMPLICIT && !$object instanceof \Traversable) { return; } // If TRAVERSE, fail if we have no Traversable if (!$object instanceof \Traversable) { // Must throw a ConstraintDefinitionException for backwards // compatibility reasons with Symfony < 2.5 throw new ConstraintDefinitionException(sprintf( 'Traversal was enabled for "%s", but this class '. 'does not implement "\Traversable".', get_class($object) )); } $this->validateEachObjectIn( $object, $propertyPath, $groups, $traversalStrategy & TraversalStrategy::STOP_RECURSION, $context ); } /** * Validates a node that is not a class node. * * Currently, two such node types exist: * * - property nodes, which consist of the value of an object's * property together with a {@link PropertyMetadataInterface} instance * - generic nodes, which consist of a value and some arbitrary * constraints defined in a {@link MetadataInterface} container * * In both cases, the value is validated against all constraints defined * in the passed metadata object. Then, if the value is an instance of * {@link \Traversable} and the selected traversal strategy permits it, * the value is traversed and each nested object validated against its own * constraints. Arrays are always traversed. * * @param mixed $value The validated value * @param object|null $object The current object * @param string $cacheKey The key for caching * the validated value * @param MetadataInterface $metadata The metadata of the * value * @param string $propertyPath The property path leading * to the value * @param string[] $groups The groups in which the * value should be validated * @param string[]|null $cascadedGroups The groups in which * cascaded objects should * be validated * @param int $traversalStrategy The strategy used for * traversing the value * @param ExecutionContextInterface $context The current execution context * * @see TraversalStrategy */ private function validateGenericNode($value, $object, $cacheKey, MetadataInterface $metadata = null, $propertyPath, array $groups, $cascadedGroups, $traversalStrategy, ExecutionContextInterface $context) { $context->setNode($value, $object, $metadata, $propertyPath); foreach ($groups as $key => $group) { if ($group instanceof GroupSequence) { $this->stepThroughGroupSequence( $value, $object, $cacheKey, $metadata, $propertyPath, $traversalStrategy, $group, null, $context ); // Skip the group sequence when cascading, as the cascading // logic is already done in stepThroughGroupSequence() unset($groups[$key]); continue; } $this->validateInGroup($value, $cacheKey, $metadata, $group, $context); } if (0 === count($groups)) { return; } if (null === $value) { return; } $cascadingStrategy = $metadata->getCascadingStrategy(); // Quit unless we have an array or a cascaded object if (!is_array($value) && !($cascadingStrategy & CascadingStrategy::CASCADE)) { return; } // If no specific traversal strategy was requested when this method // was called, use the traversal strategy of the node's metadata if ($traversalStrategy & TraversalStrategy::IMPLICIT) { // Keep the STOP_RECURSION flag, if it was set $traversalStrategy = $metadata->getTraversalStrategy() | ($traversalStrategy & TraversalStrategy::STOP_RECURSION); } // The $cascadedGroups property is set, if the "Default" group is // overridden by a group sequence // See validateClassNode() $cascadedGroups = count($cascadedGroups) > 0 ? $cascadedGroups : $groups; if (is_array($value)) { // Arrays are always traversed, independent of the specified // traversal strategy // (BC with Symfony < 2.5) $this->validateEachObjectIn( $value, $propertyPath, $cascadedGroups, $traversalStrategy & TraversalStrategy::STOP_RECURSION, $context ); return; } // If the value is a scalar, pass it anyway, because we want // a NoSuchMetadataException to be thrown in that case // (BC with Symfony < 2.5) $this->validateObject( $value, $propertyPath, $cascadedGroups, $traversalStrategy, $context ); // Currently, the traversal strategy can only be TRAVERSE for a // generic node if the cascading strategy is CASCADE. Thus, traversable // objects will always be handled within validateObject() and there's // nothing more to do here. // see GenericMetadata::addConstraint() } /** * Sequentially validates a node's value in each group of a group sequence. * * If any of the constraints generates a violation, subsequent groups in the * group sequence are skipped. * * @param mixed $value The validated value * @param object|null $object The current object * @param string $cacheKey The key for caching * the validated value * @param MetadataInterface $metadata The metadata of the * value * @param string $propertyPath The property path leading * to the value * @param int $traversalStrategy The strategy used for * traversing the value * @param GroupSequence $groupSequence The group sequence * @param string[]|null $cascadedGroup The group that should * be passed to cascaded * objects instead of * the group sequence * @param ExecutionContextInterface $context The execution context */ private function stepThroughGroupSequence($value, $object, $cacheKey, MetadataInterface $metadata = null, $propertyPath, $traversalStrategy, GroupSequence $groupSequence, $cascadedGroup, ExecutionContextInterface $context) { $violationCount = count($context->getViolations()); $cascadedGroups = $cascadedGroup ? array($cascadedGroup) : null; foreach ($groupSequence->groups as $groupInSequence) { $groups = array($groupInSequence); if ($metadata instanceof ClassMetadataInterface) { $this->validateClassNode( $value, $cacheKey, $metadata, $propertyPath, $groups, $cascadedGroups, $traversalStrategy, $context ); } else { $this->validateGenericNode( $value, $object, $cacheKey, $metadata, $propertyPath, $groups, $cascadedGroups, $traversalStrategy, $context ); } // Abort sequence validation if a violation was generated if (count($context->getViolations()) > $violationCount) { break; } } } /** * Validates a node's value against all constraints in the given group. * * @param mixed $value The validated value * @param string $cacheKey The key for caching the * validated value * @param MetadataInterface $metadata The metadata of the value * @param string $group The group to validate * @param ExecutionContextInterface $context The execution context */ private function validateInGroup($value, $cacheKey, MetadataInterface $metadata, $group, ExecutionContextInterface $context) { $context->setGroup($group); foreach ($metadata->findConstraints($group) as $constraint) { // Prevent duplicate validation of constraints, in the case // that constraints belong to multiple validated groups if (null !== $cacheKey) { $constraintHash = spl_object_hash($constraint); if ($context->isConstraintValidated($cacheKey, $constraintHash)) { continue; } $context->markConstraintAsValidated($cacheKey, $constraintHash); } $context->setConstraint($constraint); $validator = $this->validatorFactory->getInstance($constraint); $validator->initialize($context); $validator->validate($value, $constraint); } } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator\Validator; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface; /** * A validator that supports both the API of Symfony < 2.5 and Symfony 2.5+. * * This class is incompatible with PHP versions < 5.3.9, because it implements * two different interfaces specifying the same method validate(): * * - {@link \Symfony\Component\Validator\ValidatorInterface} * - {@link \Symfony\Component\Validator\Validator\ValidatorInterface} * * In PHP versions prior to 5.3.9, either use {@link RecursiveValidator} or the * deprecated class {@link \Symfony\Component\Validator\Validator} instead. * * @since 2.5 * @author Bernhard Schussek * * @see \Symfony\Component\Validator\ValidatorInterface * @see \Symfony\Component\Validator\Validator\ValidatorInterface * * @deprecated Implemented for backwards compatibility with Symfony < 2.5. * To be removed in Symfony 3.0. */ class LegacyValidator extends RecursiveValidator implements LegacyValidatorInterface { public function validate($value, $groups = null, $traverse = false, $deep = false) { $numArgs = func_num_args(); // Use new signature if constraints are given in the second argument if (self::testConstraints($groups) && ($numArgs < 3 || 3 === $numArgs && self::testGroups($traverse))) { // Rename to avoid total confusion ;) $constraints = $groups; $groups = $traverse; return parent::validate($value, $constraints, $groups); } $constraint = new Valid(array('traverse' => $traverse, 'deep' => $deep)); return parent::validate($value, $constraint, $groups); } public function validateValue($value, $constraints, $groups = null) { return parent::validate($value, $constraints, $groups); } public function getMetadataFactory() { return $this->metadataFactory; } private static function testConstraints($constraints) { return null === $constraints || $constraints instanceof Constraint || (is_array($constraints) && (0 === count($constraints) || current($constraints) instanceof Constraint)); } private static function testGroups($groups) { return null === $groups || is_string($groups) || $groups instanceof GroupSequence || (is_array($groups) && (is_string(current($groups)) || current($groups) instanceof GroupSequence)); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Prepares an object for validation. * * Concrete implementations of this interface are used by {@link ValidationVisitorInterface} * to initialize objects just before validating them. * * @author Fabien Potencier * @author Bernhard Schussek * * @api */ interface ObjectInitializerInterface { /** * Initializes an object just before validation. * * @param object $object The object to validate * * @api */ public function initialize($object); } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Default implementation of {@ConstraintViolationListInterface}. * * @author Bernhard Schussek */ class ConstraintViolationList implements \IteratorAggregate, ConstraintViolationListInterface { /** * @var ConstraintViolationInterface[] */ private $violations = array(); /** * Creates a new constraint violation list. * * @param ConstraintViolationInterface[] $violations The constraint violations to add to the list */ public function __construct(array $violations = array()) { foreach ($violations as $violation) { $this->add($violation); } } /** * Converts the violation into a string for debugging purposes. * * @return string The violation as string. */ public function __toString() { $string = ''; foreach ($this->violations as $violation) { $string .= $violation."\n"; } return $string; } /** * {@inheritdoc} */ public function add(ConstraintViolationInterface $violation) { $this->violations[] = $violation; } /** * {@inheritdoc} */ public function addAll(ConstraintViolationListInterface $otherList) { foreach ($otherList as $violation) { $this->violations[] = $violation; } } /** * {@inheritdoc} */ public function get($offset) { if (!isset($this->violations[$offset])) { throw new \OutOfBoundsException(sprintf('The offset "%s" does not exist.', $offset)); } return $this->violations[$offset]; } /** * {@inheritdoc} */ public function has($offset) { return isset($this->violations[$offset]); } /** * {@inheritdoc} */ public function set($offset, ConstraintViolationInterface $violation) { $this->violations[$offset] = $violation; } /** * {@inheritdoc} */ public function remove($offset) { unset($this->violations[$offset]); } /** * {@inheritdoc} */ public function getIterator() { return new \ArrayIterator($this->violations); } /** * {@inheritdoc} */ public function count() { return count($this->violations); } /** * {@inheritdoc} */ public function offsetExists($offset) { return $this->has($offset); } /** * {@inheritdoc} */ public function offsetGet($offset) { return $this->get($offset); } /** * {@inheritdoc} */ public function offsetSet($offset, $violation) { if (null === $offset) { $this->add($violation); } else { $this->set($offset, $violation); } } /** * {@inheritdoc} */ public function offsetUnset($offset) { $this->remove($offset); } } * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Validator; /** * Validates values against constraints defined in {@link MetadataInterface} * instances. * * This interface is an implementation of the Visitor design pattern. A value * is validated by first passing it to the {@link validate} method. That method * will determine the matching {@link MetadataInterface} for validating the * value. It then calls the {@link MetadataInterface::accept} method of that * metadata. accept() does two things: * *
    *
  1. It calls {@link visit} to validate the value against the constraints of * the metadata.
  2. *
  3. It calls accept() on all nested metadata instances with the * corresponding values extracted from the current value. For example, if the * current metadata represents a class and the current value is an object of * that class, the metadata contains nested instances for each property of that * class. It forwards the call to these nested metadata with the values of the * corresponding properties in the original object.
  4. *
* * @author Bernhard Schussek * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. */ interface ValidationVisitorInterface { /** * Validates a value. * * If the value is an array or a traversable object, you can set the * parameter $traverse to true in order to run through * the collection and validate each element. If these elements can be * collections again and you want to traverse them recursively, set the * parameter $deep to true as well. * * If you set $traversable to true, the visitor will * nevertheless try to find metadata for the collection and validate its * constraints. If no such metadata is found, the visitor ignores that and * only iterates the collection. * * If you don't set $traversable to true and the visitor * does not find metadata for the given value, it will fail with an * exception. * * @param mixed $value The value to validate. * @param string $group The validation group to validate. * @param string $propertyPath The current property path in the validation graph. * @param bool $traverse Whether to traverse the value if it is traversable. * @param bool $deep Whether to traverse nested traversable values recursively. * * @throws Exception\NoSuchMetadataException If no metadata can be found for * the given value. * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. */ public function validate($value, $group, $propertyPath, $traverse = false, $deep = false); /** * Validates a value against the constraints defined in some metadata. * * This method implements the Visitor design pattern. See also * {@link ValidationVisitorInterface}. * * @param MetadataInterface $metadata The metadata holding the constraints. * @param mixed $value The value to validate. * @param string $group The validation group to validate. * @param string $propertyPath The current property path in the validation graph. * * @deprecated Deprecated since version 2.5, to be removed in Symfony 3.0. */ public function visit(MetadataInterface $metadata, $value, $group, $propertyPath); } * * @deprecated since 1.12 (to be removed in 2.0) */ interface Twig_FilterCallableInterface { public function getCallable(); } * * @deprecated since 1.12 (to be removed in 2.0) */ interface Twig_TestCallableInterface { public function getCallable(); } * {% spaceless %} *
* foo *
* {% endspaceless %} * * {# output will be
foo
#} *
*/ class Twig_TokenParser_Spaceless extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ 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'); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'spaceless'; } } parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); return new Twig_Node_Flush($token->getLine(), $this->getTag()); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'flush'; } } * {% if users %} *
    * {% for user in users %} *
  • {{ user.username|e }}
  • * {% endfor %} *
* {% endif %} * */ class Twig_TokenParser_If extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ 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->getFilename()); } } $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')); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'if'; } } * {% 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 %} * */ class Twig_TokenParser_Set extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ 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->getFilename()); } } 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->getFilename()); } $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'); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'set'; } } * {% include 'header.html' %} * Body * {% include 'footer.html' %} * */ class Twig_TokenParser_Include extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ public function parse(Twig_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()); } protected function parseArguments() { $stream = $this->parser->getStream(); $ignoreMissing = false; if ($stream->nextIf(Twig_Token::NAME_TYPE, 'ignore')) { $stream->expect(Twig_Token::NAME_TYPE, 'missing'); $ignoreMissing = true; } $variables = null; if ($stream->nextIf(Twig_Token::NAME_TYPE, 'with')) { $variables = $this->parser->getExpressionParser()->parseExpression(); } $only = false; if ($stream->nextIf(Twig_Token::NAME_TYPE, 'only')) { $only = true; } $stream->expect(Twig_Token::BLOCK_END_TYPE); return array($variables, $only, $ignoreMissing); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'include'; } } * {% from 'forms.html' import forms %} * */ class Twig_TokenParser_From extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ 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->getFilename()); } $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var')); } return $node; } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'from'; } } * {% block head %} * * {% block title %}{% endblock %} - My Webpage * {% endblock %} * */ class Twig_TokenParser_Block extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ 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 '$name' has already been defined line %d", $this->parser->getBlock($name)->getLine()), $stream->getCurrent()->getLine(), $stream->getFilename()); } $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->getFilename()); } } } 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'); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'block'; } } * {% sandbox %} * {% include 'user.html' %} * {% endsandbox %} * * * @see http://www.twig-project.org/doc/api.html#sandbox-extension for details */ class Twig_TokenParser_Sandbox extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ public function parse(Twig_Token $token) { $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); // 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->getLine(), $this->parser->getFilename()); } } } return new Twig_Node_Sandbox($body, $token->getLine(), $this->getTag()); } public function decideBlockEnd(Twig_Token $token) { return $token->test('endsandbox'); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'sandbox'; } } * {% import 'forms.html' as forms %} * */ class Twig_TokenParser_Import extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ 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()); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'import'; } } parser->getStream(); $parent = $this->parser->getExpressionParser()->parseExpression(); list($variables, $only, $ignoreMissing) = $this->parseArguments(); // 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()), new Twig_Token(Twig_Token::STRING_TYPE, '__parent__', $token->getLine()), 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 $module->setNode('parent', $parent); $this->parser->embedTemplate($module); $stream->expect(Twig_Token::BLOCK_END_TYPE); return new Twig_Node_Embed($module->getAttribute('filename'), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); } public function decideBlockEnd(Twig_Token $token) { return $token->test('endembed'); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'embed'; } } * {% extends "base.html" %} * */ class Twig_TokenParser_Extends extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ public function parse(Twig_Token $token) { if (!$this->parser->isMainScope()) { throw new Twig_Error_Syntax('Cannot extend from a block', $token->getLine(), $this->parser->getFilename()); } if (null !== $this->parser->getParent()) { throw new Twig_Error_Syntax('Multiple extends tags are forbidden', $token->getLine(), $this->parser->getFilename()); } $this->parser->setParent($this->parser->getExpressionParser()->parseExpression()); $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'extends'; } } parser->getExpressionParser()->parseExpression(); $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); return new Twig_Node_Do($expr, $token->getLine(), $this->getTag()); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'do'; } } * {% filter upper %} * This text becomes uppercase * {% endfilter %} * */ class Twig_TokenParser_Filter extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ public function parse(Twig_Token $token) { $name = $this->parser->getVarName(); $ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), true, $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'); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'filter'; } } * {% 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 %} * */ class Twig_TokenParser_AutoEscape extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ 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 Boolean.', $stream->getCurrent()->getLine(), $stream->getFilename()); } $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.', E_USER_DEPRECATED); if (false === $value) { throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getFilename()); } $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'); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'autoescape'; } } *
    * {% for user in users %} *
  • {{ user.username|e }}
  • * {% endfor %} *
* */ class Twig_TokenParser_For extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ 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->getLine()); $valueTarget = $targets->getNode(1); $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine()); } else { $keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno); $valueTarget = $targets->getNode(0); $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine()); } 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->getLine(), $stream->getFilename()); } 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->getLine(), $stream->getFilename()); } } // 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); } } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'for'; } } * {% 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. */ class Twig_TokenParser_Use extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ 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->getFilename()); } $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)))); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'use'; } } * {% macro input(name, value, type, size) %} * * {% endmacro %} * */ class Twig_TokenParser_Macro extends Twig_TokenParser { /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance */ 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->getFilename()); } } $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'); } /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag() { return 'macro'; } } */ class Twig_Compiler implements Twig_CompilerInterface { protected $lastLine; protected $source; protected $indentation; protected $env; protected $debugInfo = array(); protected $sourceOffset; protected $sourceLine; protected $filename; /** * Constructor. * * @param Twig_Environment $env The twig environment instance */ public function __construct(Twig_Environment $env) { $this->env = $env; } public function getFilename() { return $this->filename; } /** * Returns the environment instance related to this compiler. * * @return Twig_Environment The environment instance */ public function getEnvironment() { return $this->env; } /** * Gets the current PHP code after compilation. * * @return string The PHP code */ public function getSource() { return $this->source; } /** * Compiles a node. * * @param Twig_NodeInterface $node The node to compile * @param int $indentation The current indentation * * @return Twig_Compiler The current compiler instance */ public function compile(Twig_NodeInterface $node, $indentation = 0) { $this->lastLine = null; $this->source = ''; $this->debugInfo = array(); $this->sourceOffset = 0; // source code starts at 1 (as we then increment it when we encounter new lines) $this->sourceLine = 1; $this->indentation = $indentation; if ($node instanceof Twig_Node_Module) { $this->filename = $node->getAttribute('filename'); } $node->compile($this); return $this; } public function subcompile(Twig_NodeInterface $node, $raw = true) { if (false === $raw) { $this->addIndentation(); } $node->compile($this); return $this; } /** * Adds a raw string to the compiled code. * * @param string $string The string * * @return Twig_Compiler The current compiler instance */ public function raw($string) { $this->source .= $string; return $this; } /** * Writes a string to the compiled code by adding indentation. * * @return Twig_Compiler The current compiler instance */ public function write() { $strings = func_get_args(); foreach ($strings as $string) { $this->addIndentation(); $this->source .= $string; } return $this; } /** * Appends an indentation to the current PHP code after compilation. * * @return Twig_Compiler The current compiler instance */ public function addIndentation() { $this->source .= str_repeat(' ', $this->indentation * 4); return $this; } /** * Adds a quoted string to the compiled code. * * @param string $value The string * * @return Twig_Compiler The current compiler instance */ public function string($value) { $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\")); return $this; } /** * Returns a PHP representation of a given value. * * @param mixed $value The value to convert * * @return Twig_Compiler The current compiler instance */ public function repr($value) { if (is_int($value) || is_float($value)) { if (false !== $locale = setlocale(LC_NUMERIC, 0)) { setlocale(LC_NUMERIC, 'C'); } $this->raw($value); if (false !== $locale) { setlocale(LC_NUMERIC, $locale); } } elseif (null === $value) { $this->raw('null'); } elseif (is_bool($value)) { $this->raw($value ? 'true' : 'false'); } elseif (is_array($value)) { $this->raw('array('); $first = true; foreach ($value as $key => $v) { if (!$first) { $this->raw(', '); } $first = false; $this->repr($key); $this->raw(' => '); $this->repr($v); } $this->raw(')'); } else { $this->string($value); } return $this; } /** * Adds debugging information. * * @param Twig_NodeInterface $node The related twig node * * @return Twig_Compiler The current compiler instance */ public function addDebugInfo(Twig_NodeInterface $node) { if ($node->getLine() != $this->lastLine) { $this->write(sprintf("// line %d\n", $node->getLine())); // when mbstring.func_overload is set to 2 // mb_substr_count() replaces substr_count() // but they have different signatures! if (((int) ini_get('mbstring.func_overload')) & 2) { // this is much slower than the "right" version $this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n"); } else { $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset); } $this->sourceOffset = strlen($this->source); $this->debugInfo[$this->sourceLine] = $node->getLine(); $this->lastLine = $node->getLine(); } return $this; } public function getDebugInfo() { ksort($this->debugInfo); return $this->debugInfo; } /** * Indents the generated code. * * @param int $step The number of indentation to add * * @return Twig_Compiler The current compiler instance */ public function indent($step = 1) { $this->indentation += $step; return $this; } /** * Outdents the generated code. * * @param int $step The number of indentation to remove * * @return Twig_Compiler The current compiler instance * * @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'); } $this->indentation -= $step; return $this; } public function getVarName() { return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); } } */ class Twig_Markup implements Countable { protected $content; protected $charset; public function __construct($content, $charset) { $this->content = (string) $content; $this->charset = $charset; } public function __toString() { return $this->content; } public function count() { return function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : strlen($this->content); } } * * @deprecated since 1.12 (to be removed in 2.0) */ abstract class Twig_Test implements Twig_TestInterface, Twig_TestCallableInterface { protected $options; protected $arguments = array(); public function __construct(array $options = array()) { $this->options = array_merge(array( 'callable' => null, ), $options); } public function getCallable() { return $this->options['callable']; } } */ class Twig_Error_Runtime extends Twig_Error { } */ class Twig_Error_Syntax extends Twig_Error { } */ class Twig_Error_Loader extends Twig_Error { public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null) { parent::__construct($message, false, false, $previous); } } */ class Twig_Node_Spaceless extends Twig_Node { public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless') { parent::__construct(array('body' => $body), array(), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ 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 Twig_Node_Flush extends Twig_Node { public function __construct($lineno, $tag) { parent::__construct(array(), array(), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write("flush();\n") ; } } */ class Twig_Node_If extends Twig_Node { public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null) { parent::__construct(array('tests' => $tests, 'else' => $else), array(), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler->addDebugInfo($this); for ($i = 0, $count = count($this->getNode('tests')); $i < $count; $i += 2) { if ($i > 0) { $compiler ->outdent() ->write('} elseif (') ; } else { $compiler ->write('if (') ; } $compiler ->subcompile($this->getNode('tests')->getNode($i)) ->raw(") {\n") ->indent() ->subcompile($this->getNode('tests')->getNode($i + 1)) ; } if ($this->hasNode('else') && null !== $this->getNode('else')) { $compiler ->outdent() ->write("} else {\n") ->indent() ->subcompile($this->getNode('else')) ; } $compiler ->outdent() ->write("}\n"); } } */ class Twig_Node_Set extends Twig_Node { 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); /* * 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"); */ 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->getLine())); $this->setAttribute('capture', false); } } } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler->addDebugInfo($this); if (count($this->getNode('names')) > 1) { $compiler->write('list('); foreach ($this->getNode('names') as $idx => $node) { if ($idx) { $compiler->raw(', '); } $compiler->subcompile($node); } $compiler->raw(')'); } else { if ($this->getAttribute('capture')) { $compiler ->write("ob_start();\n") ->subcompile($this->getNode('values')) ; } $compiler->subcompile($this->getNode('names'), false); if ($this->getAttribute('capture')) { $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())"); } } if (!$this->getAttribute('capture')) { $compiler->raw(' = '); if (count($this->getNode('names')) > 1) { $compiler->write('array('); foreach ($this->getNode('values') as $idx => $value) { if ($idx) { $compiler->raw(', '); } $compiler->subcompile($value); } $compiler->raw(')'); } else { if ($this->getAttribute('safe')) { $compiler ->raw("('' === \$tmp = ") ->subcompile($this->getNode('values')) ->raw(") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())") ; } else { $compiler->subcompile($this->getNode('values')); } } } $compiler->raw(";\n"); } } */ 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) { parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ 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($compiler->getFilename()) ->raw(', ') ->repr($this->getLine()) ->raw(')') ; } protected function addTemplateArguments(Twig_Compiler $compiler) { if (null === $this->getNode('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 Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface { public function __construct($name, $lineno, $tag = null) { parent::__construct(array(), array('name' => $name), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name'))) ; } } */ class Twig_Node_Block extends Twig_Node { public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null) { parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this->getAttribute('name')), "{\n") ->indent() ; $compiler ->subcompile($this->getNode('body')) ->outdent() ->write("}\n\n") ; } } */ class Twig_Node_Sandbox extends Twig_Node { public function __construct(Twig_NodeInterface $body, $lineno, $tag = null) { parent::__construct(array('body' => $body), array(), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write("\$sandbox = \$this->env->getExtension('sandbox');\n") ->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n") ->indent() ->write("\$sandbox->enableSandbox();\n") ->outdent() ->write("}\n") ->subcompile($this->getNode('body')) ->write("if (!\$alreadySandboxed) {\n") ->indent() ->write("\$sandbox->disableSandbox();\n") ->outdent() ->write("}\n") ; } } */ class Twig_Node_SandboxedPrint extends Twig_Node_Print { public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) { parent::__construct($expr, $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write('echo $this->env->getExtension(\'sandbox\')->ensureToStringAllowed(') ->subcompile($this->getNode('expr')) ->raw(");\n") ; } /** * Removes node filters. * * This is mostly needed when another visitor adds filters (like the escaper one). * * @param Twig_Node $node A Node * * @return Twig_Node */ protected function removeNodeFilter($node) { if ($node instanceof Twig_Node_Expression_Filter) { return $this->removeNodeFilter($node->getNode('node')); } return $node; } } $node, 'arguments' => $arguments), array('method' => $method, 'safe' => false), $lineno); if ($node instanceof Twig_Node_Expression_Name) { $node->setAttribute('always_defined', true); } } public function compile(Twig_Compiler $compiler) { $compiler ->subcompile($this->getNode('node')) ->raw('->') ->raw($this->getAttribute('method')) ->raw('(') ; $first = true; foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) { if (!$first) { $compiler->raw(', '); } $first = false; $compiler->subcompile($pair['value']); } $compiler->raw(')'); } } $node, 'arguments' => $arguments), array('name' => $name), $lineno); } public function compile(Twig_Compiler $compiler) { $name = $this->getAttribute('name'); $test = $compiler->getEnvironment()->getTest($name); $this->setAttribute('name', $name); $this->setAttribute('type', 'test'); $this->setAttribute('thing', $test); if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) { $this->setAttribute('callable', $test->getCallable()); } if ($test instanceof Twig_SimpleTest) { $this->setAttribute('is_variadic', $test->isVariadic()); } $this->compileCallable($compiler); } } */ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression { public function __construct(Twig_NodeInterface $name, $asString = false, $lineno, $tag = null) { parent::__construct(array('name' => $name), array('as_string' => $asString, 'output' => false), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { if ($this->getAttribute('as_string')) { $compiler->raw('(string) '); } if ($this->getAttribute('output')) { $compiler ->addDebugInfo($this) ->write('$this->displayBlock(') ->subcompile($this->getNode('name')) ->raw(", \$context, \$blocks);\n") ; } else { $compiler ->raw('$this->renderBlock(') ->subcompile($this->getNode('name')) ->raw(', $context, $blocks)') ; } } } raw('-'); } } raw('!'); } } raw('+'); } } hasAttribute('callable') && $callable = $this->getAttribute('callable')) { if (is_string($callable)) { $compiler->raw($callable); } elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) { $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $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'))); $closingParenthesis = true; } } else { $compiler->raw($this->getAttribute('thing')->compile()); } $this->compileArguments($compiler); if ($closingParenthesis) { $compiler->raw(')'); } } protected function compileArguments(Twig_Compiler $compiler) { $compiler->raw('('); $first = true; if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { $compiler->raw('$this->env'); $first = false; } if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { if (!$first) { $compiler->raw(', '); } $compiler->raw('$context'); $first = false; } if ($this->hasAttribute('arguments')) { foreach ($this->getAttribute('arguments') as $argument) { if (!$first) { $compiler->raw(', '); } $compiler->string($argument); $first = false; } } if ($this->hasNode('node')) { if (!$first) { $compiler->raw(', '); } $compiler->subcompile($this->getNode('node')); $first = false; } if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) { $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null; $arguments = $this->getArguments($callable, $this->getNode('arguments')); foreach ($arguments as $node) { if (!$first) { $compiler->raw(', '); } $compiler->subcompile($node); $first = false; } } $compiler->raw(')'); } protected function getArguments($callable, $arguments) { $callType = $this->getAttribute('type'); $callName = $this->getAttribute('name'); $parameters = array(); $named = false; foreach ($arguments as $name => $node) { 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)); } $parameters[$name] = $node; } $isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic'); if (!$named && !$isVariadic) { return $parameters; } if (!$callable) { if ($named) { $message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName); } else { $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName); } throw new LogicException($message); } // manage named arguments if (is_array($callable)) { $r = new ReflectionMethod($callable[0], $callable[1]); } elseif (is_object($callable) && !$callable instanceof Closure) { $r = new ReflectionObject($callable); $r = $r->getMethod('__invoke'); } elseif (is_string($callable) && false !== strpos($callable, '::')) { $r = new ReflectionMethod($callable); } else { $r = new ReflectionFunction($callable); } $definition = $r->getParameters(); if ($this->hasNode('node')) { array_shift($definition); } if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { array_shift($definition); } if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { array_shift($definition); } if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) { foreach ($this->getAttribute('arguments') as $argument) { array_shift($definition); } } if ($isVariadic) { $argument = end($definition); if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) { array_pop($definition); } else { $callableName = $r->name; if ($r->getDeclaringClass()) { $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, $callType, $callName)); } } $arguments = array(); $names = array(); $missingArguments = array(); $optionalArguments = array(); $pos = 0; foreach ($definition as $param) { $names[] = $name = $this->normalizeName($param->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 (!empty($missingArguments)) { throw new Twig_Error_Syntax(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)) ); } $arguments = array_merge($arguments, $optionalArguments); $arguments[] = $parameters[$name]; unset($parameters[$name]); $optionalArguments = array(); } elseif (array_key_exists($pos, $parameters)) { $arguments = array_merge($arguments, $optionalArguments); $arguments[] = $parameters[$pos]; unset($parameters[$pos]); $optionalArguments = array(); ++$pos; } elseif ($param->isDefaultValueAvailable()) { $optionalArguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1); } elseif ($param->isOptional()) { if (empty($parameters)) { break; } else { $missingArguments[] = $name; } } else { throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName)); } } if ($isVariadic) { $arbitraryArguments = new Twig_Node_Expression_Array(array(), -1); foreach ($parameters as $key => $value) { if (is_int($key)) { $arbitraryArguments->addElement($value); } else { $arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1)); } unset($parameters[$key]); } if ($arbitraryArguments->count()) { $arguments = array_merge($arguments, $optionalArguments); $arguments[] = $arbitraryArguments; } } if (!empty($parameters)) { $unknownParameter = null; foreach ($parameters as $parameter) { if ($parameter instanceof Twig_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->getLine() : -1); } return $arguments; } 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)); } } $arguments), array('name' => $name), $lineno); } public function compile(Twig_Compiler $compiler) { $name = $this->getAttribute('name'); $function = $compiler->getEnvironment()->getFunction($name); $this->setAttribute('name', $name); $this->setAttribute('type', 'function'); $this->setAttribute('thing', $function); $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) { $this->setAttribute('callable', $function->getCallable()); } if ($function instanceof Twig_SimpleFunction) { $this->setAttribute('is_variadic', $function->isVariadic()); } $this->compileCallable($compiler); } } raw('$context[') ->string($this->getAttribute('name')) ->raw(']') ; } } * {{ 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->getLine()), $arguments, $node->getLine()); 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->getLine()); $false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getLine()); $node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getLine()); } else { $node = $default; } parent::__construct($node, $filterName, $arguments, $lineno, $tag); } public function compile(Twig_Compiler $compiler) { $compiler->subcompile($this->getNode('node')); } } 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) { $this->index = $pair['key']->getAttribute('value'); } } } public function getKeyValuePairs() { $pairs = array(); foreach (array_chunk($this->nodes, 2) as $pair) { $pairs[] = array( 'key' => $pair[0], 'value' => $pair[1], ); } return $pairs; } public function hasElement(Twig_Node_Expression $key) { foreach ($this->getKeyValuePairs() as $pair) { // we compare the string representation of the keys // to avoid comparing the line numbers which are not relevant here. if ((string) $key == (string) $pair['key']) { return true; } } return false; } public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null) { if (null === $key) { $key = new Twig_Node_Expression_Constant(++$this->index, $value->getLine()); } array_push($this->nodes, $key, $value); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler->raw('array('); $first = true; foreach ($this->getKeyValuePairs() as $pair) { if (!$first) { $compiler->raw(', '); } $first = false; $compiler ->subcompile($pair['key']) ->raw(' => ') ->subcompile($pair['value']) ; } $compiler->raw(')'); } } $expr1, 'expr2' => $expr2, 'expr3' => $expr3), array(), $lineno); } public function compile(Twig_Compiler $compiler) { $compiler ->raw('((') ->subcompile($this->getNode('expr1')) ->raw(') ? (') ->subcompile($this->getNode('expr2')) ->raw(') : (') ->subcompile($this->getNode('expr3')) ->raw('))') ; } } */ class Twig_Node_Expression_Parent extends Twig_Node_Expression { public function __construct($name, $lineno, $tag = null) { parent::__construct(array(), array('output' => false, 'name' => $name), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { if ($this->getAttribute('output')) { $compiler ->addDebugInfo($this) ->write('$this->displayParentBlock(') ->string($this->getAttribute('name')) ->raw(", \$context, \$blocks);\n") ; } else { $compiler ->raw('$this->renderParentBlock(') ->string($this->getAttribute('name')) ->raw(', $context, $blocks)') ; } } } $value), $lineno); } public function compile(Twig_Compiler $compiler) { $compiler->repr($this->getAttribute('value')); } } $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno); } public function compile(Twig_Compiler $compiler) { if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) { $compiler->raw('twig_template_get_attributes($this, '); } else { $compiler->raw('$this->getAttribute('); } if ($this->getAttribute('ignore_strict_check')) { $this->getNode('node')->setAttribute('ignore_strict_check', true); } $compiler->subcompile($this->getNode('node')); $compiler->raw(', ')->subcompile($this->getNode('attribute')); // 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'); $needFirst = $needSecond || null !== $this->getNode('arguments'); if ($needFirst) { if (null !== $this->getNode('arguments')) { $compiler->raw(', ')->subcompile($this->getNode('arguments')); } else { $compiler->raw(', array()'); } } if ($needSecond) { $compiler->raw(', ')->repr($this->getAttribute('type')); } if ($needThird) { $compiler->raw(', ')->repr($this->getAttribute('is_defined_test')); } if ($needFourth) { $compiler->raw(', ')->repr($this->getAttribute('ignore_strict_check')); } $compiler->raw(')'); } } raw('pow(') ->subcompile($this->getNode('left')) ->raw(', ') ->subcompile($this->getNode('right')) ->raw(')') ; } public function operator(Twig_Compiler $compiler) { return $compiler->raw('**'); } } raw('&'); } } raw('||'); } } getVarName(); $right = $compiler->getVarName(); $compiler ->raw(sprintf('(is_string($%s = ', $left)) ->subcompile($this->getNode('left')) ->raw(sprintf(') && is_string($%s = ', $right)) ->subcompile($this->getNode('right')) ->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s, -strlen($%2$s))))', $left, $right)) ; } public function operator(Twig_Compiler $compiler) { return $compiler->raw(''); } } raw('preg_match(') ->subcompile($this->getNode('right')) ->raw(', ') ->subcompile($this->getNode('left')) ->raw(')') ; } public function operator(Twig_Compiler $compiler) { return $compiler->raw(''); } } raw('>='); } } raw('.'); } } getVarName(); $right = $compiler->getVarName(); $compiler ->raw(sprintf('(is_string($%s = ', $left)) ->subcompile($this->getNode('left')) ->raw(sprintf(') && is_string($%s = ', $right)) ->subcompile($this->getNode('right')) ->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s, $%2$s)))', $left, $right)) ; } public function operator(Twig_Compiler $compiler) { return $compiler->raw(''); } } raw('twig_in_filter(') ->subcompile($this->getNode('left')) ->raw(', ') ->subcompile($this->getNode('right')) ->raw(')') ; } public function operator(Twig_Compiler $compiler) { return $compiler->raw('in'); } } raw('|'); } } raw('%'); } } raw('>'); } } raw('/'); } } raw('^'); } } raw('range(') ->subcompile($this->getNode('left')) ->raw(', ') ->subcompile($this->getNode('right')) ->raw(')') ; } public function operator(Twig_Compiler $compiler) { return $compiler->raw('..'); } } raw('<='); } } raw('+'); } } raw('<'); } } raw('!='); } } raw('intval(floor('); parent::compile($compiler); $compiler->raw('))'); } public function operator(Twig_Compiler $compiler) { return $compiler->raw('/'); } } raw('!twig_in_filter(') ->subcompile($this->getNode('left')) ->raw(', ') ->subcompile($this->getNode('right')) ->raw(')') ; } public function operator(Twig_Compiler $compiler) { return $compiler->raw('not in'); } } raw('=='); } } raw('&&'); } } raw('*'); } } raw('-'); } } $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); } $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag); } public function compile(Twig_Compiler $compiler) { $name = $this->getNode('filter')->getAttribute('value'); $filter = $compiler->getEnvironment()->getFilter($name); $this->setAttribute('name', $name); $this->setAttribute('type', 'filter'); $this->setAttribute('thing', $filter); $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) { $this->setAttribute('callable', $filter->getCallable()); } if ($filter instanceof Twig_SimpleFilter) { $this->setAttribute('is_variadic', $filter->isVariadic()); } $this->compileCallable($compiler); } } $name), $lineno); } public function compile(Twig_Compiler $compiler) { $compiler ->raw('$_') ->raw($this->getAttribute('name')) ->raw('_') ; } } '$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); } public function compile(Twig_Compiler $compiler) { $name = $this->getAttribute('name'); $compiler->addDebugInfo($this); if ($this->getAttribute('is_defined_test')) { if ($this->isSpecial()) { if ('_self' === $name) { @trigger_error(sprintf('Global variable "_self" is deprecated in %s at line %d', '?', $this->getLine()), E_USER_DEPRECATED); } $compiler->repr(true); } else { $compiler->raw('array_key_exists(')->repr($name)->raw(', $context)'); } } elseif ($this->isSpecial()) { if ('_self' === $name) { @trigger_error(sprintf('Global variable "_self" is deprecated in %s at line %d', '?', $this->getLine()), E_USER_DEPRECATED); } $compiler->raw($this->specialVars[$name]); } elseif ($this->getAttribute('always_defined')) { $compiler ->raw('$context[') ->string($name) ->raw(']') ; } else { // remove the non-PHP 5.4 version when PHP 5.3 support is dropped // as the non-optimized version is just a workaround for slow ternary operator // when the context has a lot of variables if (PHP_VERSION_ID >= 50400) { // PHP 5.4 ternary operator performance was optimized $compiler ->raw('(isset($context[') ->string($name) ->raw(']) ? $context[') ->string($name) ->raw('] : ') ; if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) { $compiler->raw('null)'); } else { $compiler->raw('$this->getContext($context, ')->string($name)->raw('))'); } } else { $compiler ->raw('$this->getContext($context, ') ->string($name) ; if ($this->getAttribute('ignore_strict_check')) { $compiler->raw(', true'); } $compiler ->raw(')') ; } } } public function isSpecial() { return isset($this->specialVars[$this->getAttribute('name')]); } public function isSimple() { return !$this->isSpecial() && !$this->getAttribute('is_defined_test'); } } $left, 'right' => $right), array(), $lineno); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->raw('(') ->subcompile($this->getNode('left')) ->raw(' ') ; $this->operator($compiler); $compiler ->raw(' ') ->subcompile($this->getNode('right')) ->raw(')') ; } abstract public function operator(Twig_Compiler $compiler); } */ class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression { public function __construct($name, $lineno, $tag = null) { parent::__construct(array(), array('name' => $name), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name'))); } } */ class Twig_Node_Module extends Twig_Node { public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $filename) { // embedded templates are set as attributes so that they are only visited once by the visitors parent::__construct(array( 'parent' => $parent, '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(), ), array( 'filename' => $filename, 'index' => null, 'embedded_templates' => $embeddedTemplates, ), 1); } public function setIndex($index) { $this->setAttribute('index', $index); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $this->compileTemplate($compiler); foreach ($this->getAttribute('embedded_templates') as $template) { $compiler->subcompile($template); } } protected function compileTemplate(Twig_Compiler $compiler) { if (!$this->getAttribute('index')) { $compiler->write('compileClassHeader($compiler); if ( count($this->getNode('blocks')) || count($this->getNode('traits')) || null === $this->getNode('parent') || $this->getNode('parent') instanceof Twig_Node_Expression_Constant || count($this->getNode('constructor_start')) || count($this->getNode('constructor_end')) ) { $this->compileConstructor($compiler); } $this->compileGetParent($compiler); $this->compileDisplay($compiler); $compiler->subcompile($this->getNode('blocks')); $this->compileMacros($compiler); $this->compileGetTemplateName($compiler); $this->compileIsTraitable($compiler); $this->compileDebugInfo($compiler); $this->compileClassFooter($compiler); } protected function compileGetParent(Twig_Compiler $compiler) { if (null === $parent = $this->getNode('parent')) { return; } $compiler ->write("protected function doGetParent(array \$context)\n", "{\n") ->indent() ->addDebugInfo($parent) ->write('return ') ; if ($parent instanceof Twig_Node_Expression_Constant) { $compiler->subcompile($parent); } else { $compiler ->raw('$this->loadTemplate(') ->subcompile($parent) ->raw(', ') ->repr($compiler->getFilename()) ->raw(', ') ->repr($this->getNode('parent')->getLine()) ->raw(')') ; } $compiler ->raw(";\n") ->outdent() ->write("}\n\n") ; } protected function compileClassHeader(Twig_Compiler $compiler) { $compiler ->write("\n\n") // if the filename contains */, add a blank to avoid a PHP parse error ->write('/* '.str_replace('*/', '* /', $this->getAttribute('filename'))." */\n") ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index'))) ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass())) ->write("{\n") ->indent() ; } protected function compileConstructor(Twig_Compiler $compiler) { $compiler ->write("public function __construct(Twig_Environment \$env)\n", "{\n") ->indent() ->subcompile($this->getNode('constructor_start')) ->write("parent::__construct(\$env);\n\n") ; // parent if (null === $parent = $this->getNode('parent')) { $compiler->write("\$this->parent = false;\n\n"); } elseif ($parent instanceof Twig_Node_Expression_Constant) { $compiler ->addDebugInfo($parent) ->write('$this->parent = $this->loadTemplate(') ->subcompile($parent) ->raw(', ') ->repr($compiler->getFilename()) ->raw(', ') ->repr($this->getNode('parent')->getLine()) ->raw(");\n") ; } $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)); $compiler ->addDebugInfo($trait->getNode('template')) ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i)) ->indent() ->write("throw new Twig_Error_Runtime('Template \"'.") ->subcompile($trait->getNode('template')) ->raw(".'\" cannot be used as a trait.');\n") ->outdent() ->write("}\n") ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i)) ; foreach ($trait->getNode('targets') as $key => $value) { $compiler ->write(sprintf('if (!isset($_trait_%s_blocks[', $i)) ->string($key) ->raw("])) {\n") ->indent() ->write("throw new Twig_Error_Runtime(sprintf('Block ") ->string($key) ->raw(' is not defined in trait ') ->subcompile($trait->getNode('template')) ->raw(".'));\n") ->outdent() ->write("}\n\n") ->write(sprintf('$_trait_%s_blocks[', $i)) ->subcompile($value) ->raw(sprintf('] = $_trait_%s_blocks[', $i)) ->string($key) ->raw(sprintf(']; unset($_trait_%s_blocks[', $i)) ->string($key) ->raw("]);\n\n") ; } } if ($countTraits > 1) { $compiler ->write("\$this->traits = array_merge(\n") ->indent() ; for ($i = 0; $i < $countTraits; ++$i) { $compiler ->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i)) ; } $compiler ->outdent() ->write(");\n\n") ; } else { $compiler ->write("\$this->traits = \$_trait_0_blocks;\n\n") ; } $compiler ->write("\$this->blocks = array_merge(\n") ->indent() ->write("\$this->traits,\n") ->write("array(\n") ; } else { $compiler ->write("\$this->blocks = array(\n") ; } // blocks $compiler ->indent() ; foreach ($this->getNode('blocks') as $name => $node) { $compiler ->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name)) ; } if ($countTraits) { $compiler ->outdent() ->write(")\n") ; } $compiler ->outdent() ->write(");\n") ->outdent() ->subcompile($this->getNode('constructor_end')) ->write("}\n\n") ; } protected function compileDisplay(Twig_Compiler $compiler) { $compiler ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n") ->indent() ->subcompile($this->getNode('display_start')) ->subcompile($this->getNode('body')) ; if (null !== $parent = $this->getNode('parent')) { $compiler->addDebugInfo($parent); if ($parent instanceof Twig_Node_Expression_Constant) { $compiler->write('$this->parent'); } else { $compiler->write('$this->getParent($context)'); } $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n"); } $compiler ->subcompile($this->getNode('display_end')) ->outdent() ->write("}\n\n") ; } protected function compileClassFooter(Twig_Compiler $compiler) { $compiler ->subcompile($this->getNode('class_end')) ->outdent() ->write("}\n") ; } protected function compileMacros(Twig_Compiler $compiler) { $compiler->subcompile($this->getNode('macros')); } protected function compileGetTemplateName(Twig_Compiler $compiler) { $compiler ->write("public function getTemplateName()\n", "{\n") ->indent() ->write('return ') ->repr($this->getAttribute('filename')) ->raw(";\n") ->outdent() ->write("}\n\n") ; } protected function compileIsTraitable(Twig_Compiler $compiler) { // A template can be used as a trait if: // * it has no parent // * it has no macros // * it has no body // // Put another way, a template can be used as a trait if it // only contains blocks and use statements. $traitable = null === $this->getNode('parent') && 0 === count($this->getNode('macros')); if ($traitable) { if ($this->getNode('body') instanceof Twig_Node_Body) { $nodes = $this->getNode('body')->getNode(0); } else { $nodes = $this->getNode('body'); } if (!count($nodes)) { $nodes = new Twig_Node(array($nodes)); } foreach ($nodes as $node) { if (!count($node)) { continue; } if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) { continue; } if ($node instanceof Twig_Node_BlockReference) { continue; } $traitable = false; break; } } if ($traitable) { return; } $compiler ->write("public function isTraitable()\n", "{\n") ->indent() ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false')) ->outdent() ->write("}\n\n") ; } protected function compileDebugInfo(Twig_Compiler $compiler) { $compiler ->write("public function getDebugInfo()\n", "{\n") ->indent() ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true)))) ->outdent() ->write("}\n") ; } protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var) { if ($node instanceof Twig_Node_Expression_Constant) { $compiler ->write(sprintf('%s = $this->loadTemplate(', $var)) ->subcompile($node) ->raw(', ') ->repr($compiler->getFilename()) ->raw(', ') ->repr($node->getLine()) ->raw(");\n") ; } else { throw new LogicException('Trait templates can only be constant nodes'); } } } */ class Twig_Node_Import extends Twig_Node { public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null) { parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write('') ->subcompile($this->getNode('var')) ->raw(' = ') ; if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) { $compiler->raw('$this'); } else { $compiler ->raw('$this->loadTemplate(') ->subcompile($this->getNode('expr')) ->raw(', ') ->repr($compiler->getFilename()) ->raw(', ') ->repr($this->getLine()) ->raw(')') ; } $compiler->raw(";\n"); } } */ class Twig_Node_Embed extends Twig_Node_Include { // 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($filename, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) { parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag); $this->setAttribute('filename', $filename); $this->setAttribute('index', $index); } protected function addGetTemplate(Twig_Compiler $compiler) { $compiler ->write('$this->loadTemplate(') ->string($this->getAttribute('filename')) ->raw(', ') ->repr($compiler->getFilename()) ->raw(', ') ->repr($this->getLine()) ->raw(', ') ->string($this->getAttribute('index')) ->raw(')') ; } } */ class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface { public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) { parent::__construct(array('expr' => $expr), array(), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write('echo ') ->subcompile($this->getNode('expr')) ->raw(";\n") ; } } */ class Twig_Node_Do extends Twig_Node { public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) { parent::__construct(array('expr' => $expr), array(), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write('') ->subcompile($this->getNode('expr')) ->raw(";\n") ; } } */ class Twig_Node_AutoEscape extends Twig_Node { public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape') { parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler->subcompile($this->getNode('body')); } } */ class Twig_Node_For extends Twig_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) { $body = new Twig_Node(array($body, $this->loop = new Twig_Node_ForLoop($lineno, $tag))); if (null !== $ifexpr) { $body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag); } parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else), array('with_loop' => true, 'ifexpr' => null !== $ifexpr), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write("\$context['_parent'] = \$context;\n") ->write("\$context['_seq'] = twig_ensure_traversable(") ->subcompile($this->getNode('seq')) ->raw(");\n") ; if (null !== $this->getNode('else')) { $compiler->write("\$context['_iterated'] = false;\n"); } if ($this->getAttribute('with_loop')) { $compiler ->write("\$context['loop'] = array(\n") ->write(" 'parent' => \$context['_parent'],\n") ->write(" 'index0' => 0,\n") ->write(" 'index' => 1,\n") ->write(" 'first' => true,\n") ->write(");\n") ; if (!$this->getAttribute('ifexpr')) { $compiler ->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") ->write("\$context['loop']['revindex'] = \$length;\n") ->write("\$context['loop']['length'] = \$length;\n") ->write("\$context['loop']['last'] = 1 === \$length;\n") ->outdent() ->write("}\n") ; } } $this->loop->setAttribute('else', null !== $this->getNode('else')); $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop')); $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr')); $compiler ->write("foreach (\$context['_seq'] as ") ->subcompile($this->getNode('key_target')) ->raw(' => ') ->subcompile($this->getNode('value_target')) ->raw(") {\n") ->indent() ->subcompile($this->getNode('body')) ->outdent() ->write("}\n") ; if (null !== $this->getNode('else')) { $compiler ->write("if (!\$context['_iterated']) {\n") ->indent() ->subcompile($this->getNode('else')) ->outdent() ->write("}\n") ; } $compiler->write("\$_parent = \$context['_parent'];\n"); // remove some "private" loop variables (needed for nested loops) $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n"); // keep the values set in the inner context for variables defined in the outer context $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n"); } } */ class Twig_Node_CheckSecurity extends Twig_Node { protected $usedFilters; protected $usedTags; protected $usedFunctions; public function __construct(array $usedFilters, array $usedTags, array $usedFunctions) { $this->usedFilters = $usedFilters; $this->usedTags = $usedTags; $this->usedFunctions = $usedFunctions; parent::__construct(); } public function compile(Twig_Compiler $compiler) { $tags = $filters = $functions = array(); foreach (array('tags', 'filters', 'functions') as $type) { foreach ($this->{'used'.ucfirst($type)} as $name => $node) { if ($node instanceof Twig_Node) { ${$type}[$name] = $node->getLine(); } else { ${$type}[$node] = null; } } } $compiler ->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('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") ->outdent() ->write(");\n") ->outdent() ->write("} catch (Twig_Sandbox_SecurityError \$e) {\n") ->indent() ->write("\$e->setTemplateFile(\$this->getTemplateName());\n\n") ->write("if (\$e instanceof Twig_Sandbox_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") ->indent() ->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n") ->outdent() ->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n") ->indent() ->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n") ->outdent() ->write("}\n\n") ->write("throw \$e;\n") ->outdent() ->write("}\n\n") ; } } */ class Twig_Node_ForLoop extends Twig_Node { public function __construct($lineno, $tag = null) { parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { if ($this->getAttribute('else')) { $compiler->write("\$context['_iterated'] = true;\n"); } if ($this->getAttribute('with_loop')) { $compiler ->write("++\$context['loop']['index0'];\n") ->write("++\$context['loop']['index'];\n") ->write("\$context['loop']['first'] = false;\n") ; if (!$this->getAttribute('ifexpr')) { $compiler ->write("if (isset(\$context['loop']['length'])) {\n") ->indent() ->write("--\$context['loop']['revindex0'];\n") ->write("--\$context['loop']['revindex'];\n") ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n") ->outdent() ->write("}\n") ; } } } } */ abstract class Twig_Node_Expression extends Twig_Node { } */ class Twig_Node_Body extends Twig_Node { } */ class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface { public function __construct($data, $lineno) { parent::__construct(array(), array('data' => $data), $lineno); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write('echo ') ->string($this->getAttribute('data')) ->raw(";\n") ; } } $name), $lineno); } public function compile(Twig_Compiler $compiler) { $name = $this->getAttribute('name'); $compiler ->addDebugInfo($this) ->write('if (isset($context[') ->string($name) ->raw('])) { $_') ->raw($name) ->raw('_ = $context[') ->repr($name) ->raw(']; } else { $_') ->raw($name) ->raw("_ = null; }\n") ; } } */ class Twig_Node_Macro extends Twig_Node { const VARARGS_NAME = 'varargs'; 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->getLine()); } } parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag); } /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler) { $compiler ->addDebugInfo($this) ->write(sprintf('public function get%s(', $this->getAttribute('name'))) ; $count = count($this->getNode('arguments')); $pos = 0; foreach ($this->getNode('arguments') as $name => $default) { $compiler ->raw('$__'.$name.'__ = ') ->subcompile($default) ; if (++$pos < $count) { $compiler->raw(', '); } } if (PHP_VERSION_ID >= 50600) { if ($count) { $compiler->raw(', '); } $compiler->raw('...$__varargs__'); } $compiler ->raw(")\n") ->write("{\n") ->indent() ; $compiler ->write("\$context = \$this->env->mergeGlobals(array(\n") ->indent() ; foreach ($this->getNode('arguments') as $name => $default) { $compiler ->addIndentation() ->string($name) ->raw(' => $__'.$name.'__') ->raw(",\n") ; } $compiler ->addIndentation() ->string(self::VARARGS_NAME) ->raw(' => ') ; if (PHP_VERSION_ID >= 50600) { $compiler->raw("\$__varargs__,\n"); } else { $compiler ->raw('func_num_args() > ') ->repr($count) ->raw(' ? array_slice(func_get_args(), ') ->repr($count) ->raw(") : array(),\n") ; } $compiler ->outdent() ->write("));\n\n") ->write("\$blocks = array();\n\n") ->write("ob_start();\n") ->write("try {\n") ->indent() ->subcompile($this->getNode('body')) ->outdent() ->write("} catch (Exception \$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") ->outdent() ->write("}\n\n") ; } } policy = $policy; $this->sandboxedGlobally = $sandboxed; } /** * Returns the token parser instances to add to the existing list. * * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances */ public function getTokenParsers() { return array(new Twig_TokenParser_Sandbox()); } /** * Returns the node visitor instances to add to the existing list. * * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances */ public function getNodeVisitors() { return array(new Twig_NodeVisitor_Sandbox()); } public function enableSandbox() { $this->sandboxed = true; } public function disableSandbox() { $this->sandboxed = false; } public function isSandboxed() { return $this->sandboxedGlobally || $this->sandboxed; } public function isSandboxedGlobally() { return $this->sandboxedGlobally; } public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy) { $this->policy = $policy; } public function getSecurityPolicy() { return $this->policy; } public function checkSecurity($tags, $filters, $functions) { if ($this->isSandboxed()) { $this->policy->checkSecurity($tags, $filters, $functions); } } public function checkMethodAllowed($obj, $method) { if ($this->isSandboxed()) { $this->policy->checkMethodAllowed($obj, $method); } } public function checkPropertyAllowed($obj, $method) { if ($this->isSandboxed()) { $this->policy->checkPropertyAllowed($obj, $method); } } public function ensureToStringAllowed($obj) { if ($this->isSandboxed() && is_object($obj)) { $this->policy->checkMethodAllowed($obj, '__toString'); } return $obj; } /** * Returns the name of the extension. * * @return string The extension name */ public function getName() { return 'sandbox'; } } * * @internal */ class Twig_Extension_Staging extends Twig_Extension { protected $functions = array(); protected $filters = array(); protected $visitors = array(); protected $tokenParsers = array(); protected $globals = array(); protected $tests = array(); public function addFunction($name, $function) { $this->functions[$name] = $function; } /** * {@inheritdoc} */ public function getFunctions() { return $this->functions; } public function addFilter($name, $filter) { $this->filters[$name] = $filter; } /** * {@inheritdoc} */ public function getFilters() { return $this->filters; } public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) { $this->visitors[] = $visitor; } /** * {@inheritdoc} */ public function getNodeVisitors() { return $this->visitors; } public function addTokenParser(Twig_TokenParserInterface $parser) { $this->tokenParsers[] = $parser; } /** * {@inheritdoc} */ public function getTokenParsers() { return $this->tokenParsers; } public function addGlobal($name, $value) { $this->globals[$name] = $value; } /** * {@inheritdoc} */ public function getGlobals() { return $this->globals; } public function addTest($name, $test) { $this->tests[$name] = $test; } /** * {@inheritdoc} */ public function getTests() { return $this->tests; } /** * {@inheritdoc} */ public function getName() { return 'staging'; } } optimizers = $optimizers; } /** * {@inheritdoc} */ public function getNodeVisitors() { return array(new Twig_NodeVisitor_Optimizer($this->optimizers)); } /** * {@inheritdoc} */ public function getName() { return 'optimizer'; } } $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)), ); } /** * Returns the name of the extension. * * @return string The extension name */ public function getName() { return 'debug'; } } function twig_var_dump(Twig_Environment $env, $context) { if (!$env->isDebug()) { return; } ob_start(); $count = func_num_args(); if (2 === $count) { $vars = array(); foreach ($context as $key => $value) { if (!$value instanceof Twig_Template) { $vars[$key] = $value; } } var_dump($vars); } else { for ($i = 2; $i < $count; ++$i) { var_dump(func_get_arg($i)); } } return ob_get_clean(); } actives[] = $profile; } public function enter(Twig_Profiler_Profile $profile) { $this->actives[0]->addProfile($profile); array_unshift($this->actives, $profile); } public function leave(Twig_Profiler_Profile $profile) { $profile->leave(); array_shift($this->actives); if (1 === count($this->actives)) { $this->actives[0]->leave(); } } /** * {@inheritdoc} */ public function getNodeVisitors() { return array(new Twig_Profiler_NodeVisitor_Profiler($this->getName())); } /** * {@inheritdoc} */ public function getName() { return 'profiler'; } } true)), ); } /** * {@inheritdoc} */ 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 A Twig_Template instance */ function twig_template_from_string(Twig_Environment $env, $template) { return $env->createTemplate((string) $template); } 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; } /** * Returns the token parser instance to add to the existing list. * * @return Twig_TokenParser[] An array of Twig_TokenParser instances */ 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(), ); } /** * Returns a list of filters to add to the existing list. * * @return array An array of filters */ 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', 'trim'), 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; } /** * Returns a list of global functions to add to the existing list. * * @return array An array of global functions */ 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'))), ); } /** * Returns a list of tests to add to the existing list. * * @return array An array of tests */ 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' => true, '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' => true, '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'), ); } /** * Returns a list of operators to add to the existing list. * * @return array An array of operators */ 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, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), 'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), '**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT), ), ); } public function parseNotTestExpression(Twig_Parser $parser, Twig_NodeInterface $node) { return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($parser, $node), $parser->getCurrentToken()->getLine()); } public function parseTestExpression(Twig_Parser $parser, Twig_NodeInterface $node) { $stream = $parser->getStream(); list($name, $test) = $this->getTest($parser, $node->getLine()); if ($test instanceof Twig_SimpleTest && $test->isDeprecated()) { $message = sprintf('Twig Test "%s" is deprecated', $name); if ($test->getAlternative()) { $message .= sprintf('. Use "%s" instead', $test->getAlternative()); } $message .= sprintf(' in %s at line %d.', $stream->getFilename(), $stream->getCurrent()->getLine()); @trigger_error($message, E_USER_DEPRECATED); } $class = $this->getTestNodeClass($parser, $test); $arguments = null; if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { $arguments = $parser->getExpressionParser()->parseArguments(true); } return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine()); } protected function getTest(Twig_Parser $parser, $line) { $stream = $parser->getStream(); $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); $env = $parser->getEnvironment(); if ($test = $env->getTest($name)) { return array($name, $test); } if ($stream->test(Twig_Token::NAME_TYPE)) { // try 2-words tests $name = $name.' '.$parser->getCurrentToken()->getValue(); if ($test = $env->getTest($name)) { $parser->getStream()->next(); return array($name, $test); } } $message = sprintf('The test "%s" does not exist', $name); if ($alternatives = $env->computeAlternatives($name, array_keys($env->getTests()))) { $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); } throw new Twig_Error_Syntax($message, $line, $parser->getFilename()); } protected function getTestNodeClass(Twig_Parser $parser, $test) { if ($test instanceof Twig_SimpleTest) { return $test->getNodeClass(); } return $test instanceof Twig_Test_Node ? $test->getClass() : 'Twig_Node_Expression_Test'; } /** * Returns the name of the extension. * * @return string The extension name */ public function getName() { return 'core'; } } /** * Cycles over a value. * * @param ArrayAccess|array $values An array or an ArrayAccess instance * @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 A Twig_Environment instance * @param Traversable|array|int|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 A Twig_Environment instance * @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('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 A Twig_Environment instance * @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 A Twig_Environment instance * @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('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('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('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 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 A Twig_Environment instance * @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('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 A Twig_Environment instance * @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) { if ($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 A Twig_Environment instance * @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 A Twig_Environment instance * @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 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) { return array_keys(iterator_to_array($array)); } if (!is_array($array)) { return array(); } return array_keys($array); } /** * Reverses a variable. * * @param Twig_Environment $env A Twig_Environment instance * @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) { return in_array($value, iterator_to_array($compare, false), is_object($value) || is_resource($value)); } return false; } /** * Escapes a string. * * @param Twig_Environment $env A Twig_Environment instance * @param string $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; } else { 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; if (null === $htmlspecialcharsCharsets) { if (defined('HHVM_VERSION')) { $htmlspecialcharsCharsets = array('utf-8' => true, 'UTF-8' => true); } else { $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) ? false : true)) { 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) ? false : true)) { 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) ? false : true)) { 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('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'); return '\\u'.strtoupper(substr('0000'.bin2hex($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 A Twig_Environment instance * @param mixed $thing A variable * * @return int The length of the value */ function twig_length_filter(Twig_Environment $env, $thing) { return is_scalar($thing) ? mb_strlen($thing, $env->getCharset()) : count($thing); } /** * Converts a string to uppercase. * * @param Twig_Environment $env A Twig_Environment instance * @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 A Twig_Environment instance * @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 A Twig_Environment instance * @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 A Twig_Environment instance * @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 A Twig_Environment instance * @param mixed $thing A variable * * @return int The length of the value */ function twig_length_filter(Twig_Environment $env, $thing) { return is_scalar($thing) ? strlen($thing) : count($thing); } /** * Returns a titlecased string. * * @param Twig_Environment $env A Twig_Environment instance * @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 A Twig_Environment instance * @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); } 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('sandbox')) { $sandbox = $env->getExtension('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; } } if ($isSandboxed && !$alreadySandboxed) { $sandbox->disableSandbox(); } return $result; } /** * 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(Twig_Environment $env, $name, $ignoreMissing = false) { try { return $env->getLoader()->getSource($name); } 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); } /** * 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; } setDefaultStrategy($defaultStrategy); } /** * Returns the token parser instances to add to the existing list. * * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances */ public function getTokenParsers() { return array(new Twig_TokenParser_AutoEscape()); } /** * Returns the node visitor instances to add to the existing list. * * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances */ public function getNodeVisitors() { return array(new Twig_NodeVisitor_Escaper()); } /** * Returns a list of filters to add to the existing list. * * @return array An array of filters */ public function getFilters() { return array( new Twig_SimpleFilter('raw', 'twig_raw_filter', array('is_safe' => array('all'))), ); } /** * Sets the default strategy to use when not defined by the user. * * The strategy can be a valid PHP callback that takes the template * "filename" as an argument and returns the strategy to use. * * @param string|false|callable $defaultStrategy An escaping strategy */ public function setDefaultStrategy($defaultStrategy) { // for BC if (true === $defaultStrategy) { @trigger_error('Using "true" as the default strategy is deprecated. Use "html" instead.', E_USER_DEPRECATED); $defaultStrategy = 'html'; } if ('filename' === $defaultStrategy) { $defaultStrategy = array('Twig_FileExtensionEscapingStrategy', 'guess'); } $this->defaultStrategy = $defaultStrategy; } /** * Gets the default strategy to use when not defined by the user. * * @param string $filename The template "filename" * * @return string|false The default strategy to use for the template */ public function getDefaultStrategy($filename) { // 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, $filename); } return $this->defaultStrategy; } /** * Returns the name of the extension. * * @return string The extension name */ public function getName() { return 'escaper'; } } /** * Marks a variable as being safe. * * @param string $string A PHP variable * * @return string */ function twig_raw_filter($string) { return $string; } */ abstract class Twig_Template implements Twig_TemplateInterface { protected static $cache = array(); protected $parent; protected $parents = array(); protected $env; protected $blocks = array(); protected $traits = array(); /** * Constructor. * * @param Twig_Environment $env A Twig_Environment instance */ public function __construct(Twig_Environment $env) { $this->env = $env; } /** * Returns the template name. * * @return string The template name */ abstract public function getTemplateName(); /** * @deprecated since 1.20 (to be removed in 2.0) */ public function getEnvironment() { @trigger_error('The '.__METHOD__.' method is deprecated since version 1.20 and will be removed in 2.0.', E_USER_DEPRECATED); return $this->env; } /** * Returns the parent template. * * This method is for internal use only and should never be called * directly. * * @param array $context * * @return Twig_TemplateInterface|false The parent template or false if there is no parent * * @internal */ public function getParent(array $context) { if (null !== $this->parent) { return $this->parent; } try { $parent = $this->doGetParent($context); if (false === $parent) { return false; } if ($parent instanceof self) { return $this->parents[$parent->getTemplateName()] = $parent; } if (!isset($this->parents[$parent])) { $this->parents[$parent] = $this->loadTemplate($parent); } } catch (Twig_Error_Loader $e) { $e->setTemplateFile(null); $e->guess(); throw $e; } return $this->parents[$parent]; } protected function doGetParent(array $context) { return false; } public function isTraitable() { return true; } /** * Displays a parent block. * * This method is for internal use only and should never be called * directly. * * @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()) { $name = (string) $name; if (isset($this->traits[$name])) { $this->traits[$name][0]->displayBlock($name, $context, $blocks, false); } 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->getTemplateName()); } } /** * Displays a block. * * This method is for internal use only and should never be called * directly. * * @param string $name The block name to display * @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) { $name = (string) $name; if ($useBlocks && isset($blocks[$name])) { $template = $blocks[$name][0]; $block = $blocks[$name][1]; } elseif (isset($this->blocks[$name])) { $template = $this->blocks[$name][0]; $block = $this->blocks[$name][1]; } else { $template = null; $block = null; } if (null !== $template) { // avoid RCEs when sandbox is enabled if (!$template instanceof self) { throw new LogicException('A block must be a method on a Twig_Template instance.'); } try { $template->$block($context, $blocks); } catch (Twig_Error $e) { if (!$e->getTemplateFile()) { $e->setTemplateFile($template->getTemplateName()); } // this is mostly useful for Twig_Error_Loader exceptions // see Twig_Error_Loader if (false === $e->getTemplateLine()) { $e->setTemplateLine(-1); $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->getTemplateName(), $e); } } elseif (false !== $parent = $this->getParent($context)) { $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false); } } /** * Renders a parent block. * * This method is for internal use only and should never be called * directly. * * @param string $name The block name to render from the parent * @param array $context The context * @param array $blocks The current set of blocks * * @return string The rendered block * * @internal */ public function renderParentBlock($name, array $context, array $blocks = array()) { ob_start(); $this->displayParentBlock($name, $context, $blocks); return ob_get_clean(); } /** * Renders a block. * * This method is for internal use only and should never be called * directly. * * @param string $name The block name to render * @param array $context The context * @param array $blocks The current set of blocks * @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) { ob_start(); $this->displayBlock($name, $context, $blocks, $useBlocks); return ob_get_clean(); } /** * Returns whether a block exists or not. * * This method is for internal use only and should never be called * directly. * * This method does only return blocks defined in the current template * or defined in "used" traits. * * It does not return blocks from parent templates as the parent * template name can be dynamic, which is only known based on the * current context. * * @param string $name The block name * * @return bool true if the block exists, false otherwise * * @internal */ public function hasBlock($name) { return isset($this->blocks[(string) $name]); } /** * Returns all block names. * * This method is for internal use only and should never be called * directly. * * @return array An array of block names * * @see hasBlock * * @internal */ public function getBlockNames() { return array_keys($this->blocks); } protected function loadTemplate($template, $templateName = null, $line = null, $index = null) { try { if (is_array($template)) { return $this->env->resolveTemplate($template); } if ($template instanceof self) { return $template; } return $this->env->loadTemplate($template, $index); } catch (Twig_Error $e) { if (!$e->getTemplateFile()) { $e->setTemplateFile($templateName ? $templateName : $this->getTemplateName()); } if ($e->getTemplateLine()) { throw $e; } if (!$line) { $e->guess(); } else { $e->setTemplateLine($line); } throw $e; } } /** * Returns all blocks. * * This method is for internal use only and should never be called * directly. * * @return array An array of blocks * * @see hasBlock * * @internal */ public function getBlocks() { return $this->blocks; } /** * Returns the template source code. * * @return string|null The template source code or null if it is not available */ public function getSource() { $reflector = new ReflectionClass($this); $file = $reflector->getFileName(); if (!file_exists($file)) { return; } $source = file($file, FILE_IGNORE_NEW_LINES); array_splice($source, 0, $reflector->getEndLine()); $i = 0; while (isset($source[$i]) && '/* */' === substr_replace($source[$i], '', 3, -2)) { $source[$i] = str_replace('*//* ', '*/', substr($source[$i], 3, -2)); ++$i; } array_splice($source, $i); return implode("\n", $source); } /** * {@inheritdoc} */ public function display(array $context, array $blocks = array()) { $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks)); } /** * {@inheritdoc} */ public function render(array $context) { $level = ob_get_level(); ob_start(); try { $this->display($context); } catch (Exception $e) { while (ob_get_level() > $level) { ob_end_clean(); } throw $e; } return ob_get_clean(); } protected function displayWithErrorHandling(array $context, array $blocks = array()) { try { $this->doDisplay($context, $blocks); } catch (Twig_Error $e) { if (!$e->getTemplateFile()) { $e->setTemplateFile($this->getTemplateName()); } // this is mostly useful for Twig_Error_Loader exceptions // see Twig_Error_Loader if (false === $e->getTemplateLine()) { $e->setTemplateLine(-1); $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->getTemplateName(), $e); } } /** * Auto-generated method to display the template with the given context. * * @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()); /** * Returns a variable from the context. * * This method is for internal use only and should never be called * directly. * * This method should not be overridden in a sub-class as this is an * implementation detail that has been introduced to optimize variable * access for versions of PHP before 5.4. This is not a way to override * the way to get a variable value. * * @param array $context The context * @param string $item The variable to return from the context * @param bool $ignoreStrictCheck Whether to ignore the strict variable check or not * * @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 * * @internal */ final protected function getContext($context, $item, $ignoreStrictCheck = false) { 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->getTemplateName()); } return $context[$item]; } /** * Returns the attribute value for a given array/object. * * @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 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 */ protected function getAttribute($object, $item, array $arguments = array(), $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false) { // array if (self::METHOD_CALL !== $type) { $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item; if ((is_array($object) && array_key_exists($arrayItem, $object)) || ($object instanceof ArrayAccess && isset($object[$arrayItem])) ) { if ($isDefinedTest) { return true; } return $object[$arrayItem]; } if (self::ARRAY_CALL === $type || !is_object($object)) { if ($isDefinedTest) { return false; } if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { 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 (empty($object)) { $message = sprintf('Key "%s" does not exist as the array is empty', $arrayItem); } else { $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))); } } elseif (self::ARRAY_CALL === $type) { 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); } } 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); } throw new Twig_Error_Runtime($message, -1, $this->getTemplateName()); } } if (!is_object($object)) { if ($isDefinedTest) { return false; } if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { return; } if (null === $object) { $message = sprintf('Impossible to invoke a method ("%s") on a null variable', $item); } else { $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->getTemplateName()); } // 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 ($isDefinedTest) { return true; } if ($this->env->hasExtension('sandbox')) { $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item); } return $object->$item; } } $class = get_class($object); // object method if (!isset(self::$cache[$class]['methods'])) { // 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(); foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) { $methodName = strtolower($refMethod->name); // Accessing the environment from templates is forbidden to prevent untrusted changes to the environment if ('getenvironment' !== $methodName) { $methods[$methodName] = true; } } self::$cache[$class]['methods'] = $methods; } else { self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object))); } } $call = false; $lcItem = strtolower($item); if (isset(self::$cache[$class]['methods'][$lcItem])) { $method = (string) $item; } elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) { $method = 'get'.$item; } elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) { $method = 'is'.$item; } elseif (isset(self::$cache[$class]['methods']['__call'])) { $method = (string) $item; $call = true; } else { if ($isDefinedTest) { return false; } if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { return; } throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName()); } if ($isDefinedTest) { return true; } if ($this->env->hasExtension('sandbox')) { $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method); } // Some objects throw exceptions when they have __call, and the method we try // to call is not supported. If ignoreStrictCheck is true, we should return null. try { $ret = call_user_func_array(array($object, $method), $arguments); } catch (BadMethodCallException $e) { if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) { return; } throw $e; } // useful when calling a template method from a template // this is not supported but unfortunately heavily used in the Symfony profiler if ($object instanceof Twig_TemplateInterface) { return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset()); } return $ret; } } * * @deprecated since 1.12 (to be removed in 2.0) */ interface Twig_TestInterface { /** * Compiles a test. * * @return string The PHP code for the test */ public function compile(); } * * @deprecated since 1.12 (to be removed in 2.0) */ interface Twig_FunctionCallableInterface { public function getCallable(); } * * @deprecated since 1.12 (to be removed in 2.0) */ abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface { protected $options; protected $arguments = array(); public function __construct(array $options = array()) { $this->options = array_merge(array( 'needs_environment' => false, 'needs_context' => false, 'callable' => null, ), $options); } public function setArguments($arguments) { $this->arguments = $arguments; } public function getArguments() { return $this->arguments; } public function needsEnvironment() { return $this->options['needs_environment']; } public function needsContext() { return $this->options['needs_context']; } public function getSafe(Twig_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 array(); } public function getCallable() { return $this->options['callable']; } } */ class Twig_Util_DeprecationCollector { private $twig; private $deprecations; public function __construct(Twig_Environment $twig) { $this->twig = $twig; } /** * Returns deprecations for templates contained in a directory. * * @param string $dir A directory where templates are stored * @param string $ext Limit the loaded templates by extension * * @return array() An array of deprecations */ public function collectDir($dir, $ext = '.twig') { $iterator = new RegexIterator( new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY ), '{'.preg_quote($ext).'$}' ); return $this->collect(new Twig_Util_TemplateDirIterator($iterator)); } /** * Returns deprecations for passed templates. * * @param Iterator $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(Iterator $iterator) { $this->deprecations = array(); set_error_handler(array($this, 'errorHandler')); foreach ($iterator as $name => $contents) { try { $this->twig->parse($this->twig->tokenize($contents, $name)); } catch (Twig_Error_Syntax $e) { // ignore templates containing syntax errors } } restore_error_handler(); $deprecations = $this->deprecations; $this->deprecations = array(); return $deprecations; } /** * @internal */ public function errorHandler($type, $msg) { if (E_USER_DEPRECATED === $type) { $this->deprecations[] = $msg; } } } */ class Twig_Util_TemplateDirIterator extends IteratorIterator { public function current() { return file_get_contents(parent::current()); } public function key() { return (string) parent::key(); } } */ interface Twig_TokenParserInterface { /** * Sets the parser associated with this token parser. * * @param Twig_Parser $parser A Twig_Parser instance */ public function setParser(Twig_Parser $parser); /** * Parses a token and returns a node. * * @param Twig_Token $token A Twig_Token instance * * @return Twig_NodeInterface A Twig_NodeInterface instance * * @throws Twig_Error_Syntax */ public function parse(Twig_Token $token); /** * Gets the tag name associated with this token parser. * * @return string The tag name */ public function getTag(); } */ class Twig_Error extends Exception { protected $lineno; protected $filename; protected $rawMessage; protected $previous; /** * Constructor. * * Set both the line number and the filename 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 filename 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 string $filename The template file name where the error occurred * @param Exception $previous The previous exception */ public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null) { if (PHP_VERSION_ID < 50300) { $this->previous = $previous; parent::__construct(''); } else { parent::__construct('', 0, $previous); } $this->lineno = $lineno; $this->filename = $filename; if (-1 === $this->lineno || null === $this->filename) { $this->guessTemplateInfo(); } $this->rawMessage = $message; $this->updateRepr(); } /** * Gets the raw message. * * @return string The raw message */ public function getRawMessage() { return $this->rawMessage; } /** * Gets the filename where the error occurred. * * @return string The filename */ public function getTemplateFile() { return $this->filename; } /** * Sets the filename where the error occurred. * * @param string $filename The filename */ public function setTemplateFile($filename) { $this->filename = $filename; $this->updateRepr(); } /** * Gets the template line where the error occurred. * * @return int The template line */ public function getTemplateLine() { return $this->lineno; } /** * Sets the template line where the error occurred. * * @param int $lineno The template line */ public function setTemplateLine($lineno) { $this->lineno = $lineno; $this->updateRepr(); } public function guess() { $this->guessTemplateInfo(); $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)); } protected function updateRepr() { $this->message = $this->rawMessage; $dot = false; if ('.' === substr($this->message, -1)) { $this->message = substr($this->message, 0, -1); $dot = true; } if ($this->filename) { if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) { $filename = sprintf('"%s"', $this->filename); } else { $filename = json_encode($this->filename); } $this->message .= sprintf(' in %s', $filename); } if ($this->lineno && $this->lineno >= 0) { $this->message .= sprintf(' at line %d', $this->lineno); } if ($dot) { $this->message .= '.'; } } protected function guessTemplateInfo() { $template = null; $templateClass = null; if (PHP_VERSION_ID >= 50306) { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT); } else { $backtrace = debug_backtrace(); } foreach ($backtrace as $trace) { if (isset($trace['object']) && $trace['object'] instanceof Twig_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']); } } } // update template filename if (null !== $template && null === $this->filename) { $this->filename = $template->getTemplateName(); } if (null === $template || $this->lineno > -1) { return; } $r = new ReflectionObject($template); $file = $r->getFileName(); // hhvm has a bug where eval'ed files comes out as the current directory if (is_dir($file)) { $file = ''; } $exceptions = array($e = $this); while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) { $exceptions[] = $e; } while ($e = array_pop($exceptions)) { $traces = $e->getTrace(); array_unshift($traces, array('file' => $e->getFile(), 'line' => $e->getLine())); while ($trace = array_shift($traces)) { if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) { continue; } foreach ($template->getDebugInfo() as $codeLine => $templateLine) { if ($codeLine <= $trace['line']) { // update template line $this->lineno = $templateLine; return; } } } } } } * * @deprecated since 1.12 (to be removed in 2.0) */ class Twig_Filter_Function extends Twig_Filter { protected $function; public function __construct($function, array $options = array()) { $options['callable'] = $function; parent::__construct($options); $this->function = $function; } public function compile() { return $this->function; } } * * @deprecated since 1.12 (to be removed in 2.0) */ class Twig_Filter_Method extends Twig_Filter { protected $extension; protected $method; public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) { $options['callable'] = array($extension, $method); parent::__construct($options); $this->extension = $extension; $this->method = $method; } public function compile() { return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method); } } * * @deprecated since 1.12 (to be removed in 2.0) */ class Twig_Filter_Node extends Twig_Filter { protected $class; public function __construct($class, array $options = array()) { parent::__construct($options); $this->class = $class; } public function getClass() { return $this->class; } public function compile() { } } */ interface Twig_LoaderInterface { /** * Gets the source code of a template, given its name. * * @param string $name The name of the template to load * * @return string The template source code * * @throws Twig_Error_Loader When $name is not found */ public function getSource($name); /** * Gets the cache key to use for the cache for a given template name. * * @param string $name The name of the template to load * * @return string The cache key * * @throws Twig_Error_Loader When $name is not found */ public function getCacheKey($name); /** * Returns true if the template is still fresh. * * @param string $name The template name * @param int $time Timestamp of the last modification time of the * cached template * * @return bool true if the template is fresh, false otherwise * * @throws Twig_Error_Loader When $name is not found */ public function isFresh($name, $time); } * * @deprecated since 1.12 (to be removed in 3.0) */ interface Twig_ExistsLoaderInterface { /** * Check if we have the source code of a template, given its name. * * @param string $name The name of the template to check if we can load * * @return bool If the template source code is handled by this loader or not */ public function exists($name); } */ class Twig_ExpressionParser { const OPERATOR_LEFT = 1; const OPERATOR_RIGHT = 2; protected $parser; protected $unaryOperators; protected $binaryOperators; public function __construct(Twig_Parser $parser, array $unaryOperators, array $binaryOperators) { $this->parser = $parser; $this->unaryOperators = $unaryOperators; $this->binaryOperators = $binaryOperators; } public function parseExpression($precedence = 0) { $expr = $this->getPrimary(); $token = $this->parser->getCurrentToken(); while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) { $op = $this->binaryOperators[$token->getValue()]; $this->parser->getStream()->next(); if (isset($op['callable'])) { $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']; $expr = new $class($expr, $expr1, $token->getLine()); } $token = $this->parser->getCurrentToken(); } if (0 === $precedence) { return $this->parseConditionalExpression($expr); } return $expr; } protected function getPrimary() { $token = $this->parser->getCurrentToken(); if ($this->isUnary($token)) { $operator = $this->unaryOperators[$token->getValue()]; $this->parser->getStream()->next(); $expr = $this->parseExpression($operator['precedence']); $class = $operator['class']; return $this->parsePostfixExpression(new $class($expr, $token->getLine())); } elseif ($token->test(Twig_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'); return $this->parsePostfixExpression($expr); } return $this->parsePrimaryExpression(); } protected function parseConditionalExpression($expr) { while ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, '?')) { if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { $expr2 = $this->parseExpression(); if ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { $expr3 = $this->parseExpression(); } else { $expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine()); } } else { $expr2 = $expr; $expr3 = $this->parseExpression(); } $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine()); } return $expr; } protected function isUnary(Twig_Token $token) { return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]); } protected function isBinary(Twig_Token $token) { return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]); } public function parsePrimaryExpression() { $token = $this->parser->getCurrentToken(); switch ($token->getType()) { case Twig_Token::NAME_TYPE: $this->parser->getStream()->next(); switch ($token->getValue()) { case 'true': case 'TRUE': $node = new Twig_Node_Expression_Constant(true, $token->getLine()); break; case 'false': case 'FALSE': $node = new Twig_Node_Expression_Constant(false, $token->getLine()); break; case 'none': case 'NONE': case 'null': case 'NULL': $node = new Twig_Node_Expression_Constant(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()); } } break; case Twig_Token::NUMBER_TYPE: $this->parser->getStream()->next(); $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); break; case Twig_Token::STRING_TYPE: case Twig_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()) { // in this context, string operators are variable names $this->parser->getStream()->next(); $node = new Twig_Node_Expression_Name($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->getFilename()); } $this->parser->getStream()->next(); $expr = $this->parsePrimaryExpression(); $node = new $class($expr, $token->getLine()); break; } default: if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) { $node = $this->parseArrayExpression(); } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) { $node = $this->parseHashExpression(); } else { throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getFilename()); } } return $this->parsePostfixExpression($node); } public function parseStringExpression() { $stream = $this->parser->getStream(); $nodes = array(); // 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()); $nextCanBeString = false; } elseif ($stream->nextIf(Twig_Token::INTERPOLATION_START_TYPE)) { $nodes[] = $this->parseExpression(); $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); $nextCanBeString = true; } else { break; } } $expr = array_shift($nodes); foreach ($nodes as $node) { $expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getLine()); } return $expr; } public function parseArrayExpression() { $stream = $this->parser->getStream(); $stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected'); $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); $first = true; while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { if (!$first) { $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma'); // trailing ,? if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { break; } } $first = false; $node->addElement($this->parseExpression()); } $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed'); return $node; } public function parseHashExpression() { $stream = $this->parser->getStream(); $stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected'); $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); $first = true; while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { if (!$first) { $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma'); // trailing ,? if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { break; } } $first = false; // a hash key can be: // // * a number -- 12 // * 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, '(')) { $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(), $this->parser->getFilename()); } $stream->expect(Twig_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'); return $node; } public function parsePostfixExpression($node) { while (true) { $token = $this->parser->getCurrentToken(); if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) { if ('.' == $token->getValue() || '[' == $token->getValue()) { $node = $this->parseSubscriptExpression($node); } elseif ('|' == $token->getValue()) { $node = $this->parseFilterExpression($node); } else { break; } } else { break; } } return $node; } public function getFunctionNode($name, $line) { 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->getFilename()); } 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->getFilename()); } return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line); case 'block': return new Twig_Node_Expression_BlockReference($this->parseArguments()->getNode(0), false, $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->getFilename()); } return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line); default: if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) { $arguments = new Twig_Node_Expression_Array(array(), $line); foreach ($this->parseArguments() as $n) { $arguments->addElement($n); } $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line); $node->setAttribute('safe', true); return $node; } $args = $this->parseArguments(true); $class = $this->getFunctionNodeClass($name, $line); return new $class($name, $args, $line); } } public function parseSubscriptExpression($node) { $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() == '.') { $token = $stream->next(); if ( $token->getType() == Twig_Token::NAME_TYPE || $token->getType() == Twig_Token::NUMBER_TYPE || ($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue())) ) { $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { $type = Twig_TemplateInterface::METHOD_CALL; foreach ($this->parseArguments() as $n) { $arguments->addElement($n); } } } else { throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename()); } 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(), $this->parser->getFilename()); } $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(), $this->parser->getFilename()); } $node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno); $node->setAttribute('safe', true); return $node; } } else { $type = Twig_Template::ARRAY_CALL; // slice? $slice = false; if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) { $slice = true; $arg = new Twig_Node_Expression_Constant(0, $token->getLine()); } else { $arg = $this->parseExpression(); } if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { $slice = true; } if ($slice) { if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { $length = new Twig_Node_Expression_Constant(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()); $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); return $filter; } $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); } return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno); } public function parseFilterExpression($node) { $this->parser->getStream()->next(); return $this->parseFilterExpressionRaw($node); } public function parseFilterExpressionRaw($node, $tag = null) { while (true) { $token = $this->parser->getStream()->expect(Twig_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(); } else { $arguments = $this->parseArguments(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, '|')) { break; } $this->parser->getStream()->next(); } return $node; } /** * Parses arguments. * * @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 * * @throws Twig_Error_Syntax */ public function parseArguments($namedArguments = false, $definition = false) { $args = array(); $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, ')')) { if (!empty($args)) { $stream->expect(Twig_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()); } else { $value = $this->parseExpression(); } $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(), $this->parser->getFilename()); } $name = $value->getAttribute('name'); if ($definition) { $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(), $this->parser->getFilename()); } } else { $value = $this->parseExpression(); } } if ($definition) { if (null === $name) { $name = $value->getAttribute('name'); $value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine()); } $args[$name] = $value; } else { if (null === $name) { $args[] = $value; } else { $args[$name] = $value; } } } $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); return new Twig_Node($args); } public function parseAssignmentExpression() { $targets = array(); while (true) { $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to'); if (in_array($token->getValue(), array('true', 'false', 'none'))) { throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine(), $this->parser->getFilename()); } $targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine()); if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { break; } } return new Twig_Node($targets); } public function parseMultitargetExpression() { $targets = array(); while (true) { $targets[] = $this->parseExpression(); if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { break; } } return new Twig_Node($targets); } protected function getFunctionNodeClass($name, $line) { $env = $this->parser->getEnvironment(); if (false === $function = $env->getFunction($name)) { $message = sprintf('The function "%s" does not exist', $name); if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFunctions()))) { $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); } throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename()); } if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) { $message = sprintf('Twig Function "%s" is deprecated', $function->getName()); if ($function->getAlternative()) { $message .= sprintf('. Use "%s" instead', $function->getAlternative()); } $message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line); @trigger_error($message, E_USER_DEPRECATED); } if ($function instanceof Twig_SimpleFunction) { return $function->getNodeClass(); } return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function'; } protected function getFilterNodeClass($name, $line) { $env = $this->parser->getEnvironment(); if (false === $filter = $env->getFilter($name)) { $message = sprintf('The filter "%s" does not exist', $name); if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFilters()))) { $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); } throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename()); } if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) { $message = sprintf('Twig Filter "%s" is deprecated', $filter->getName()); if ($filter->getAlternative()) { $message .= sprintf('. Use "%s" instead', $filter->getAlternative()); } $message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line); @trigger_error($message, E_USER_DEPRECATED); } if ($filter instanceof Twig_SimpleFilter) { return $filter->getNodeClass(); } return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter'; } // checks that the node only contains "constant" elements 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 )) { return false; } foreach ($node as $n) { if (!$this->checkConstantExpression($n)) { return false; } } return true; } } */ class Twig_Lexer implements Twig_LexerInterface { protected $tokens; protected $code; protected $cursor; protected $lineno; protected $end; protected $state; protected $states; protected $brackets; protected $env; protected $filename; protected $options; protected $regexes; protected $position; protected $positions; protected $currentVarBlockLine; const STATE_DATA = 0; const STATE_BLOCK = 1; const STATE_VAR = 2; const STATE_STRING = 3; 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_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()) { $this->env = $env; $this->options = array_merge(array( 'tag_comment' => array('{#', '#}'), 'tag_block' => array('{%', '%}'), 'tag_variable' => array('{{', '}}'), 'whitespace_trim' => '-', 'interpolation' => array('#{', '}'), ), $options); $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', ); } /** * {@inheritdoc} */ public function tokenize($code, $filename = null) { 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", $code); $this->filename = $filename; $this->cursor = 0; $this->lineno = 1; $this->end = strlen($this->code); $this->tokens = array(); $this->state = self::STATE_DATA; $this->states = array(); $this->brackets = array(); $this->position = -1; // find all token starts in one go preg_match_all($this->regexes['lex_tokens_start'], $this->code, $matches, PREG_OFFSET_CAPTURE); $this->positions = $matches; while ($this->cursor < $this->end) { // dispatch to the lexing functions depending // on the current state switch ($this->state) { case self::STATE_DATA: $this->lexData(); break; case self::STATE_BLOCK: $this->lexBlock(); break; case self::STATE_VAR: $this->lexVar(); break; case self::STATE_STRING: $this->lexString(); break; case self::STATE_INTERPOLATION: $this->lexInterpolation(); break; } } $this->pushToken(Twig_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->filename); } if ($mbEncoding) { mb_internal_encoding($mbEncoding); } return new Twig_TokenStream($this->tokens, $this->filename); } 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)); $this->cursor = $this->end; return; } // 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) { return; } $position = $this->positions[0][++$this->position]; } // push the template text first $text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor); if (isset($this->positions[2][$this->position][0])) { $text = rtrim($text); } $this->pushToken(Twig_Token::TEXT_TYPE, $text); $this->moveCursor($textContent.$position[0]); switch ($this->positions[1][$this->position][0]) { case $this->options['tag_comment'][0]: $this->lexComment(); break; case $this->options['tag_block'][0]: // raw data? if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, null, $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)) { $this->moveCursor($match[0]); $this->lineno = (int) $match[1]; } else { $this->pushToken(Twig_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->pushState(self::STATE_VAR); $this->currentVarBlockLine = $this->lineno; break; } } 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); $this->moveCursor($match[0]); $this->popState(); } else { $this->lexExpression(); } } 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); $this->moveCursor($match[0]); $this->popState(); } else { $this->lexExpression(); } } protected function lexExpression() { // whitespace if (preg_match('/\s+/A', $this->code, $match, null, $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->filename); } } // operators if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) { $this->pushToken(Twig_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]); $this->moveCursor($match[0]); } // numbers elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $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->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); } // 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->filename); } 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->filename); } } $this->pushToken(Twig_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))); $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); $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->filename); } } protected function lexRawData($tag) { if ('raw' === $tag) { @trigger_error(sprintf('Twig Tag "raw" is deprecated. Use "verbatim" instead in %s at line %d.', $this->filename, $this->lineno), E_USER_DEPRECATED); } 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->filename); } $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); } $this->pushToken(Twig_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->filename); } $this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]); } 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); $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])); $this->moveCursor($match[0]); } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $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->filename); } $this->popState(); ++$this->cursor; } } 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)) { array_pop($this->brackets); $this->pushToken(Twig_Token::INTERPOLATION_END_TYPE); $this->moveCursor($match[0]); $this->popState(); } else { $this->lexExpression(); } } protected function pushToken($type, $value = '') { // do not push empty text tokens if (Twig_Token::TEXT_TYPE === $type && '' === $value) { return; } $this->tokens[] = new Twig_Token($type, $value, $this->lineno); } protected function moveCursor($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()) ); $operators = array_combine($operators, array_map('strlen', $operators)); arsort($operators); $regex = array(); foreach ($operators as $operator => $length) { // an operator that ends with a character must be followed by // a whitespace or a parenthesis if (ctype_alpha($operator[$length - 1])) { $r = preg_quote($operator, '/').'(?=[\s()])'; } else { $r = preg_quote($operator, '/'); } // an operator with a space can be any amount of whitespaces $r = preg_replace('/\s+/', '\s+', $r); $regex[] = $r; } return '/'.implode('|', $regex).'/A'; } protected function pushState($state) { $this->states[] = $this->state; $this->state = $state; } protected function popState() { if (0 === count($this->states)) { throw new Exception('Cannot pop state without a previous state'); } $this->state = array_pop($this->states); } } */ class Twig_NodeVisitor_Sandbox extends Twig_BaseNodeVisitor { protected $inAModule = false; protected $tags; protected $filters; protected $functions; /** * {@inheritdoc} */ 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->getLine(), $node->getNodeTag()); } } return $node; } /** * {@inheritdoc} */ 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; } /** * {@inheritdoc} */ public function getPriority() { return 0; } } safeVars = $safeVars; } public function getSafe(Twig_NodeInterface $node) { $hash = spl_object_hash($node); if (!isset($this->data[$hash])) { return; } foreach ($this->data[$hash] as $bucket) { if ($bucket['key'] !== $node) { continue; } if (in_array('html_attr', $bucket['value'])) { $bucket['value'][] = 'html'; } return $bucket['value']; } } protected function setSafe(Twig_NodeInterface $node, array $safe) { $hash = spl_object_hash($node); if (isset($this->data[$hash])) { foreach ($this->data[$hash] as &$bucket) { if ($bucket['key'] === $node) { $bucket['value'] = $safe; return; } } } $this->data[$hash][] = array( 'key' => $node, 'value' => $safe, ); } /** * {@inheritdoc} */ protected function doEnterNode(Twig_Node $node, Twig_Environment $env) { return $node; } /** * {@inheritdoc} */ protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) { if ($node instanceof Twig_Node_Expression_Constant) { // constants are marked safe for all $this->setSafe($node, array('all')); } elseif ($node instanceof Twig_Node_Expression_BlockReference) { // blocks are safe by definition $this->setSafe($node, array('all')); } elseif ($node instanceof Twig_Node_Expression_Parent) { // parent block is safe by definition $this->setSafe($node, array('all')); } elseif ($node instanceof Twig_Node_Expression_Conditional) { // 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) { // filter expression is safe when the filter is safe $name = $node->getNode('filter')->getAttribute('value'); $args = $node->getNode('arguments'); if (false !== $filter = $env->getFilter($name)) { $safe = $filter->getSafe($args); if (null === $safe) { $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety()); } $this->setSafe($node, $safe); } else { $this->setSafe($node, array()); } } elseif ($node instanceof Twig_Node_Expression_Function) { // function expression is safe when the function is safe $name = $node->getAttribute('name'); $args = $node->getNode('arguments'); $function = $env->getFunction($name); if (false !== $function) { $this->setSafe($node, $function->getSafe($args)); } else { $this->setSafe($node, array()); } } elseif ($node instanceof Twig_Node_Expression_MethodCall) { if ($node->getAttribute('safe')) { $this->setSafe($node, array('all')); } else { $this->setSafe($node, array()); } } elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) { $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')); } else { $this->setSafe($node, array()); } } else { $this->setSafe($node, array()); } return $node; } protected function intersectSafe(array $a = null, array $b = null) { if (null === $a || null === $b) { return array(); } if (in_array('all', $a)) { return $b; } if (in_array('all', $b)) { return $a; } return array_intersect($a, $b); } /** * {@inheritdoc} */ public function getPriority() { return 0; } } */ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor { const OPTIMIZE_ALL = -1; const OPTIMIZE_NONE = 0; const OPTIMIZE_FOR = 2; const OPTIMIZE_RAW_FILTER = 4; const OPTIMIZE_VAR_ACCESS = 8; protected $loops = array(); protected $loopsTargets = array(); protected $optimizers; protected $prependedNodes = array(); protected $inABody = false; /** * Constructor. * * @param int $optimizers The optimizer mode */ 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)); } $this->optimizers = $optimizers; } /** * {@inheritdoc} */ protected function doEnterNode(Twig_Node $node, Twig_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('sandbox')) { if ($this->inABody) { if (!$node instanceof Twig_Node_Expression) { if (get_class($node) !== 'Twig_Node') { array_unshift($this->prependedNodes, array()); } } else { $node = $this->optimizeVariables($node, $env); } } elseif ($node instanceof Twig_Node_Body) { $this->inABody = true; } } return $node; } /** * {@inheritdoc} */ protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) { $expression = $node instanceof Twig_Node_Expression; if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { $this->leaveOptimizeFor($node, $env); } if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) { $node = $this->optimizeRawFilter($node, $env); } $node = $this->optimizePrintNode($node, $env); if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) { if ($node instanceof Twig_Node_Body) { $this->inABody = false; } elseif ($this->inABody) { if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) { $nodes = array(); foreach (array_unique($prependedNodes) as $name) { $nodes[] = new Twig_Node_SetTemp($name, $node->getLine()); } $nodes[] = $node; $node = new Twig_Node($nodes); } } } return $node; } protected function optimizeVariables(Twig_NodeInterface $node, Twig_Environment $env) { 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->getLine()); } return $node; } /** * Optimizes print nodes. * * It replaces: * * * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()" * * @param Twig_NodeInterface $node A Node * @param Twig_Environment $env The current Twig environment * * @return Twig_NodeInterface */ protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env) { if (!$node instanceof Twig_Node_Print) { return $node; } if ( $node->getNode('expr') instanceof Twig_Node_Expression_BlockReference || $node->getNode('expr') instanceof Twig_Node_Expression_Parent ) { $node->getNode('expr')->setAttribute('output', true); return $node->getNode('expr'); } return $node; } /** * Removes "raw" filters. * * @param Twig_NodeInterface $node A Node * @param Twig_Environment $env The current Twig environment * * @return Twig_NodeInterface */ protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env) { if ($node instanceof Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) { return $node->getNode('node'); } return $node; } /** * Optimizes "for" tag by removing the "loop" variable creation whenever possible. * * @param Twig_NodeInterface $node A Node * @param Twig_Environment $env The current Twig environment */ protected function enterOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env) { if ($node instanceof Twig_Node_For) { // disable the loop variable by default $node->setAttribute('with_loop', false); array_unshift($this->loops, $node); array_unshift($this->loopsTargets, $node->getNode('value_target')->getAttribute('name')); array_unshift($this->loopsTargets, $node->getNode('key_target')->getAttribute('name')); } elseif (!$this->loops) { // we are outside a loop return; } // 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')) { $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)) { $node->setAttribute('always_defined', true); } // block reference elseif ($node instanceof Twig_Node_BlockReference || $node instanceof Twig_Node_Expression_BlockReference) { $this->addLoopToCurrent(); } // include without the only attribute elseif ($node instanceof Twig_Node_Include && !$node->getAttribute('only')) { $this->addLoopToAll(); } // include function without the with_context=false parameter elseif ($node instanceof Twig_Node_Expression_Function && 'include' === $node->getAttribute('name') && (!$node->getNode('arguments')->hasNode('with_context') || false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value') ) ) { $this->addLoopToAll(); } // the loop variable is referenced via an attribute elseif ($node instanceof Twig_Node_Expression_GetAttr && (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant || 'parent' === $node->getNode('attribute')->getAttribute('value') ) && (true === $this->loops[0]->getAttribute('with_loop') || ($node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' === $node->getNode('node')->getAttribute('name') ) ) ) { $this->addLoopToAll(); } } /** * Optimizes "for" tag by removing the "loop" variable creation whenever possible. * * @param Twig_NodeInterface $node A Node * @param Twig_Environment $env The current Twig environment */ protected function leaveOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env) { if ($node instanceof Twig_Node_For) { array_shift($this->loops); array_shift($this->loopsTargets); array_shift($this->loopsTargets); } } protected function addLoopToCurrent() { $this->loops[0]->setAttribute('with_loop', true); } protected function addLoopToAll() { foreach ($this->loops as $loop) { $loop->setAttribute('with_loop', true); } } /** * {@inheritdoc} */ public function getPriority() { return 255; } } */ 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(); } /** * {@inheritdoc} */ protected function doEnterNode(Twig_Node $node, Twig_Environment $env) { if ($node instanceof Twig_Node_Module) { if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) { $this->defaultStrategy = $defaultStrategy; } $this->safeVars = 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; } /** * {@inheritdoc} */ protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) { if ($node instanceof Twig_Node_Module) { $this->defaultStrategy = false; $this->safeVars = 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->getLine() ); } 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->getLine(); $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); } /** * {@inheritdoc} */ public function getPriority() { return 0; } } */ class Twig_NodeTraverser { protected $env; protected $visitors = array(); /** * Constructor. * * @param Twig_Environment $env A Twig_Environment instance * @param Twig_NodeVisitorInterface[] $visitors An array of Twig_NodeVisitorInterface instances */ public function __construct(Twig_Environment $env, array $visitors = array()) { $this->env = $env; foreach ($visitors as $visitor) { $this->addVisitor($visitor); } } /** * Adds a visitor. * * @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance */ public function addVisitor(Twig_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. * * @param Twig_NodeInterface $node A Twig_NodeInterface instance * * @return Twig_NodeInterface */ public function traverse(Twig_NodeInterface $node) { ksort($this->visitors); foreach ($this->visitors as $visitors) { foreach ($visitors as $visitor) { $node = $this->traverseForVisitor($visitor, $node); } } return $node; } protected function traverseForVisitor(Twig_NodeVisitorInterface $visitor, Twig_NodeInterface $node = null) { if (null === $node) { return; } $node = $visitor->enterNode($node, $this->env); foreach ($node as $k => $n) { if (false !== $n = $this->traverseForVisitor($visitor, $n)) { $node->setNode($k, $n); } else { $node->removeNode($k); } } return $visitor->leaveNode($node, $this->env); } } * * @deprecated since 1.12 (to be removed in 2.0) */ interface Twig_TokenParserBrokerInterface { /** * Gets a TokenParser suitable for a tag. * * @param string $tag A tag name * * @return null|Twig_TokenParserInterface 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. * * @param Twig_ParserInterface $parser A Twig_ParserInterface interface */ public function setParser(Twig_ParserInterface $parser); /** * Gets the Twig_ParserInterface. * * @return null|Twig_ParserInterface A Twig_ParserInterface instance or null */ public function getParser(); } */ class Twig_SimpleFilter { protected $name; protected $callable; protected $options; protected $arguments = array(); public function __construct($name, $callable, array $options = array()) { $this->name = $name; $this->callable = $callable; $this->options = array_merge(array( 'needs_environment' => false, 'needs_context' => false, 'is_variadic' => false, 'is_safe' => null, 'is_safe_callback' => null, 'pre_escape' => null, 'preserves_safety' => null, 'node_class' => 'Twig_Node_Expression_Filter', 'deprecated' => false, 'alternative' => null, ), $options); } public function getName() { return $this->name; } public function getCallable() { return $this->callable; } public function getNodeClass() { return $this->options['node_class']; } public function setArguments($arguments) { $this->arguments = $arguments; } public function getArguments() { return $this->arguments; } public function needsEnvironment() { return $this->options['needs_environment']; } public function needsContext() { return $this->options['needs_context']; } public function getSafe(Twig_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); } } public function getPreservesSafety() { return $this->options['preserves_safety']; } public function getPreEscape() { return $this->options['pre_escape']; } public function isVariadic() { return $this->options['is_variadic']; } public function isDeprecated() { return $this->options['deprecated']; } public function getAlternative() { return $this->options['alternative']; } } * * @deprecated since 1.12 (to be removed in 3.0) */ interface Twig_CompilerInterface { /** * Compiles a node. * * @param Twig_NodeInterface $node The node to compile * * @return Twig_CompilerInterface The current compiler instance */ public function compile(Twig_NodeInterface $node); /** * Gets the current PHP code after compilation. * * @return string The PHP code */ public function getSource(); } */ interface Twig_CacheInterface { /** * Generates a cache key for the given template class name. * * @param string $name The template name * @param string $className The template class name * * @return string */ public function generateKey($name, $className); /** * Writes the compiled template to cache. * * @param string $key The cache key * @param string $content The template representation as a PHP class */ public function write($key, $content); /** * Loads a template from the cache. * * @param string $key The cache key */ public function load($key); /** * Returns the modification timestamp of a key. * * @param string $key The cache key * * @return int */ public function getTimestamp($key); } * * @deprecated since 1.12 (to be removed in 3.0) */ interface Twig_ParserInterface { /** * Converts a token stream to a node tree. * * @param Twig_TokenStream $stream A token stream instance * * @return Twig_Node_Module A node tree * * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong */ public function parse(Twig_TokenStream $stream); } */ abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface { /** * {@inheritdoc} */ 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); } /** * {@inheritdoc} */ 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. * * @param Twig_Node $node The node to visit * @param Twig_Environment $env The Twig environment instance * * @return Twig_Node The modified node */ abstract protected function doEnterNode(Twig_Node $node, Twig_Environment $env); /** * Called after child nodes are visited. * * @param Twig_Node $node The node to visit * @param Twig_Environment $env The Twig environment instance * * @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 Twig_Parser implements Twig_ParserInterface { protected $stack = array(); protected $stream; protected $parent; protected $handlers; protected $visitors; protected $expressionParser; protected $blocks; protected $blockStack; protected $macros; protected $env; protected $reservedMacroNames; protected $importedSymbols; protected $traits; protected $embeddedTemplates = array(); /** * Constructor. * * @param Twig_Environment $env A Twig_Environment instance */ public function __construct(Twig_Environment $env) { $this->env = $env; } public function getEnvironment() { return $this->env; } public function getVarName() { return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); } public function getFilename() { return $this->stream->getFilename(); } /** * {@inheritdoc} */ public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false) { // push all variables into the stack to keep the current state of the parser $vars = get_object_vars($this); unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames']); $this->stack[] = $vars; // tag handlers if (null === $this->handlers) { $this->handlers = $this->env->getTokenParsers(); $this->handlers->setParser($this); } // node visitors if (null === $this->visitors) { $this->visitors = $this->env->getNodeVisitors(); } if (null === $this->expressionParser) { $this->expressionParser = new Twig_ExpressionParser($this, $this->env->getUnaryOperators(), $this->env->getBinaryOperators()); } $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(); try { $body = $this->subparse($test, $dropNeedle); if (null !== $this->parent) { if (null === $body = $this->filterBodyNodes($body)) { $body = new Twig_Node(); } } } catch (Twig_Error_Syntax $e) { if (!$e->getTemplateFile()) { $e->setTemplateFile($this->getFilename()); } if (!$e->getTemplateLine()) { $e->setTemplateLine($this->stream->getCurrent()->getLine()); } 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, $this->getFilename()); $traverser = new Twig_NodeTraverser($this->env, $this->visitors); $node = $traverser->traverse($node); // restore previous stack so previous parse() call can resume working foreach (array_pop($this->stack) as $key => $val) { $this->$key = $val; } return $node; } public function subparse($test, $dropNeedle = false) { $lineno = $this->getCurrentToken()->getLine(); $rv = array(); while (!$this->stream->isEOF()) { switch ($this->getCurrentToken()->getType()) { case Twig_Token::TEXT_TYPE: $token = $this->stream->next(); $rv[] = new Twig_Node_Text($token->getValue(), $token->getLine()); break; case Twig_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()); break; case Twig_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->getFilename()); } if (null !== $test && call_user_func($test, $token)) { if ($dropNeedle) { $this->stream->next(); } if (1 === count($rv)) { return $rv[0]; } return new Twig_Node($rv, array(), $lineno); } $subparser = $this->handlers->getTokenParser($token->getValue()); if (null === $subparser) { if (null !== $test) { $error = sprintf('Unexpected tag name "%s"', $token->getValue()); if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) { $error .= sprintf(' (expecting closing tag for the "%s" tag defined near line %s)', $test[0]->getTag(), $lineno); } throw new Twig_Error_Syntax($error, $token->getLine(), $this->getFilename()); } $message = sprintf('Unknown tag name "%s"', $token->getValue()); if ($alternatives = $this->env->computeAlternatives($token->getValue(), array_keys($this->env->getTags()))) { $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); } throw new Twig_Error_Syntax($message, $token->getLine(), $this->getFilename()); } $this->stream->next(); $node = $subparser->parse($token); if (null !== $node) { $rv[] = $node; } break; default: throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', 0, $this->getFilename()); } } if (1 === count($rv)) { return $rv[0]; } return new Twig_Node($rv, array(), $lineno); } public function addHandler($name, $class) { $this->handlers[$name] = $class; } public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) { $this->visitors[] = $visitor; } public function getBlockStack() { return $this->blockStack; } public function peekBlockStack() { return $this->blockStack[count($this->blockStack) - 1]; } public function popBlockStack() { array_pop($this->blockStack); } public function pushBlockStack($name) { $this->blockStack[] = $name; } public function hasBlock($name) { return isset($this->blocks[$name]); } public function getBlock($name) { return $this->blocks[$name]; } public function setBlock($name, Twig_Node_Block $value) { $this->blocks[$name] = new Twig_Node_Body(array($value), array(), $value->getLine()); } public function hasMacro($name) { return isset($this->macros[$name]); } public function setMacro($name, Twig_Node_Macro $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->getLine(), $this->getFilename()); } $this->macros[$name] = $node; } public function isReservedMacroName($name) { if (null === $this->reservedMacroNames) { $this->reservedMacroNames = array(); $r = new ReflectionClass($this->env->getBaseTemplateClass()); foreach ($r->getMethods() as $method) { $methodName = strtolower($method->getName()); if ('get' === substr($methodName, 0, 3) && isset($methodName[3])) { $this->reservedMacroNames[] = substr($methodName, 3); } } } return in_array(strtolower($name), $this->reservedMacroNames); } public function addTrait($trait) { $this->traits[] = $trait; } public function hasTraits() { return count($this->traits) > 0; } public function embedTemplate(Twig_Node_Module $template) { $template->setIndex(mt_rand()); $this->embeddedTemplates[] = $template; } public function addImportedSymbol($type, $alias, $name = null, Twig_Node_Expression $node = null) { $this->importedSymbols[0][$type][$alias] = array('name' => $name, 'node' => $node); } public function getImportedSymbol($type, $alias) { foreach ($this->importedSymbols as $functions) { if (isset($functions[$type][$alias])) { return $functions[$type][$alias]; } } } public function isMainScope() { return 1 === count($this->importedSymbols); } public function pushLocalScope() { array_unshift($this->importedSymbols, array()); } public function popLocalScope() { array_shift($this->importedSymbols); } /** * Gets the expression parser. * * @return Twig_ExpressionParser The expression parser */ public function getExpressionParser() { return $this->expressionParser; } public function getParent() { return $this->parent; } public function setParent($parent) { $this->parent = $parent; } /** * Gets the token stream. * * @return Twig_TokenStream The token stream */ public function getStream() { return $this->stream; } /** * Gets the current token. * * @return Twig_Token The current token */ public function getCurrentToken() { return $this->stream->getCurrent(); } 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 Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface) ) { if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) { throw new Twig_Error_Syntax('A template that extends another one cannot have a body but a byte order mark (BOM) has been detected; it must be removed.', $node->getLine(), $this->getFilename()); } throw new Twig_Error_Syntax('A template that extends another one cannot have a body.', $node->getLine(), $this->getFilename()); } // bypass "set" nodes as they "capture" the output if ($node instanceof Twig_Node_Set) { return $node; } if ($node instanceof Twig_NodeOutputInterface) { return; } foreach ($node as $k => $n) { if (null !== $n && null === $this->filterBodyNodes($n)) { $node->removeNode($k); } } return $node; } } */ class Twig_SimpleFunction { protected $name; protected $callable; protected $options; protected $arguments = array(); public function __construct($name, $callable, array $options = array()) { $this->name = $name; $this->callable = $callable; $this->options = array_merge(array( 'needs_environment' => false, 'needs_context' => false, 'is_variadic' => false, 'is_safe' => null, 'is_safe_callback' => null, 'node_class' => 'Twig_Node_Expression_Function', 'deprecated' => false, 'alternative' => null, ), $options); } public function getName() { return $this->name; } public function getCallable() { return $this->callable; } public function getNodeClass() { return $this->options['node_class']; } public function setArguments($arguments) { $this->arguments = $arguments; } public function getArguments() { return $this->arguments; } public function needsEnvironment() { return $this->options['needs_environment']; } public function needsContext() { return $this->options['needs_context']; } public function getSafe(Twig_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 array(); } public function isVariadic() { return $this->options['is_variadic']; } public function isDeprecated() { return $this->options['deprecated']; } public function getAlternative() { return $this->options['alternative']; } } * * @deprecated Use Composer instead. Will be removed in Twig 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. Use Composer instead.', E_USER_DEPRECATED); if (PHP_VERSION_ID < 50300) { spl_autoload_register(array(__CLASS__, 'autoload')); } else { spl_autoload_register(array(__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 = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) { require $file; } } } */ class Twig_Environment { const VERSION = '1.22.2'; protected $charset; protected $loader; protected $debug; protected $autoReload; protected $cache; protected $lexer; protected $parser; protected $compiler; protected $baseTemplateClass; protected $extensions; protected $parsers; protected $visitors; protected $filters; protected $tests; protected $functions; protected $globals; protected $runtimeInitialized = false; protected $extensionInitialized = false; protected $loadedTemplates; protected $strictVariables; protected $unaryOperators; protected $binaryOperators; protected $templateClassPrefix = '__TwigTemplate_'; protected $functionCallbacks = array(); protected $filterCallbacks = array(); protected $staging; private $originalCache; private $bcWriteCacheFile = false; private $bcGetCacheFilename = false; /** * Constructor. * * Available options: * * * debug: When set to true, it automatically set "auto_reload" to true as * well (default to false). * * * 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). * * * cache: An absolute path where to store the compiled templates, * a Twig_Cache_Interface implementation, * or false to disable compilation cache (default). * * * auto_reload: Whether to reload the template if the original source changed. * If you don't provide the auto_reload option, it will be * determined automatically based on the debug value. * * * strict_variables: Whether to ignore invalid variables in templates * (default to false). * * * autoescape: Whether to enable auto-escaping (default to html): * * false: disable auto-escaping * * true: equivalent to html * * html, js: set the autoescaping to one of the supported strategies * * filename: set the autoescaping strategy based on the template filename extension * * PHP callback: a PHP callback that returns an escaping strategy based on the template "filename" * * * 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 A Twig_LoaderInterface instance * @param array $options An array of options */ public function __construct(Twig_LoaderInterface $loader = null, $options = array()) { if (null !== $loader) { $this->setLoader($loader); } else { @trigger_error('Not passing a Twig_LoaderInterface as the first constructor argument of Twig_Environment is deprecated.', E_USER_DEPRECATED); } $options = array_merge(array( 'debug' => false, 'charset' => 'UTF-8', 'base_template_class' => 'Twig_Template', 'strict_variables' => false, 'autoescape' => 'html', 'cache' => false, 'auto_reload' => null, 'optimizations' => -1, ), $options); $this->debug = (bool) $options['debug']; $this->charset = strtoupper($options['charset']); $this->baseTemplateClass = $options['base_template_class']; $this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload']; $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(); // 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 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 and will be removed in Twig 2.0.', E_USER_DEPRECATED); $this->bcGetCacheFilename = true; } } } /** * Gets the base template class for compiled templates. * * @return string The base template class name */ public function getBaseTemplateClass() { return $this->baseTemplateClass; } /** * Sets the base template class for compiled templates. * * @param string $class The base template class name */ public function setBaseTemplateClass($class) { $this->baseTemplateClass = $class; } /** * Enables debugging mode. */ public function enableDebug() { $this->debug = true; } /** * Disables debugging mode. */ public function disableDebug() { $this->debug = false; } /** * Checks if debug mode is enabled. * * @return bool true if debug mode is enabled, false otherwise */ public function isDebug() { return $this->debug; } /** * Enables the auto_reload option. */ public function enableAutoReload() { $this->autoReload = true; } /** * Disables the auto_reload option. */ public function disableAutoReload() { $this->autoReload = false; } /** * Checks if the auto_reload option is enabled. * * @return bool true if auto_reload is enabled, false otherwise */ public function isAutoReload() { return $this->autoReload; } /** * Enables the strict_variables option. */ public function enableStrictVariables() { $this->strictVariables = true; } /** * Disables the strict_variables option. */ public function disableStrictVariables() { $this->strictVariables = false; } /** * Checks if the strict_variables option is enabled. * * @return bool true if strict_variables is enabled, false otherwise */ public function isStrictVariables() { return $this->strictVariables; } /** * Gets the current cache implementation. * * @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 */ public function getCache($original = true) { return $original ? $this->originalCache : $this->cache; } /** * 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 */ public function setCache($cache) { if (is_string($cache)) { $this->originalCache = $cache; $this->cache = new Twig_Cache_Filesystem($cache); } elseif (false === $cache) { $this->originalCache = $cache; $this->cache = new Twig_Cache_Null(); } elseif ($cache instanceof Twig_CacheInterface) { $this->originalCache = $this->cache = $cache; } else { throw new LogicException(sprintf('Cache can only be a string, false, or a Twig_CacheInterface implementation.')); } } /** * Gets the cache filename for a given template. * * @param string $name The template name * * @return string|false The cache file name or false when caching is disabled * * @deprecated since 1.22 (to be removed in 2.0) */ public function getCacheFilename($name) { @trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); $key = $this->cache->generateKey($name, $this->getTemplateClass($name)); return !$key ? false : $key; } /** * Gets the template class associated with the given string. * * @param string $name The name for which to calculate the template class name * @param int $index The index if it is an embedded template * * @return string The template class name */ public function getTemplateClass($name, $index = null) { $key = $this->getLoader()->getCacheKey($name).'__'.implode('__', array_keys($this->extensions)); return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '_'.$index); } /** * Gets the template class prefix. * * @return string The template class prefix * * @deprecated since 1.22 (to be removed in 2.0) */ public function getTemplateClassPrefix() { @trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); return $this->templateClassPrefix; } /** * Renders a template. * * @param string $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 */ public function render($name, array $context = array()) { return $this->loadTemplate($name)->render($context); } /** * Displays a template. * * @param string $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 */ public function display($name, array $context = array()) { $this->loadTemplate($name)->display($context); } /** * Loads a template by name. * * @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 * * @throws Twig_Error_Loader When the template cannot be found * @throws Twig_Error_Syntax When an error occurred during compilation */ public function loadTemplate($name, $index = null) { $cls = $this->getTemplateClass($name, $index); if (isset($this->loadedTemplates[$cls])) { return $this->loadedTemplates[$cls]; } if (!class_exists($cls, false)) { if ($this->bcGetCacheFilename) { $key = $this->getCacheFilename($name); } else { $key = $this->cache->generateKey($name, $cls); } if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) { $this->cache->load($key); } if (!class_exists($cls, false)) { $content = $this->compileSource($this->getLoader()->getSource($name), $name); if ($this->bcWriteCacheFile) { $this->writeCacheFile($key, $content); } else { $this->cache->write($key, $content); } eval('?>'.$content); } } if (!$this->runtimeInitialized) { $this->initRuntime(); } return $this->loadedTemplates[$cls] = new $cls($this); } /** * Creates a template from source. * * This method should not be used as a generic way to load templates. * * @param string $template The template name * * @return Twig_Template 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 */ public function createTemplate($template) { $name = sprintf('__string_template__%s', hash('sha256', uniqid(mt_rand(), true), false)); $loader = new Twig_Loader_Chain(array( new Twig_Loader_Array(array($name => $template)), $current = $this->getLoader(), )); $this->setLoader($loader); try { $template = $this->loadTemplate($name); } catch (Exception $e) { $this->setLoader($current); throw $e; } $this->setLoader($current); return $template; } /** * Returns true if the template is still fresh. * * Besides checking the loader for freshness information, * this method also checks if the enabled extensions have * not changed. * * @param string $name The template name * @param int $time The last modification time of the cached template * * @return bool true if the template is fresh, false otherwise */ public function isTemplateFresh($name, $time) { foreach ($this->extensions as $extension) { $r = new ReflectionObject($extension); if (filemtime($r->getFileName()) > $time) { return false; } } return $this->getLoader()->isFresh($name, $time); } /** * 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. * * @param string|Twig_Template|array $names A template or an array of templates to try consecutively * * @return Twig_Template * * @throws Twig_Error_Loader When none of the templates can be found * @throws Twig_Error_Syntax When an error occurred during compilation */ public function resolveTemplate($names) { if (!is_array($names)) { $names = array($names); } foreach ($names as $name) { if ($name instanceof Twig_Template) { return $name; } try { return $this->loadTemplate($name); } catch (Twig_Error_Loader $e) { } } if (1 === count($names)) { throw $e; } throw new Twig_Error_Loader(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names))); } /** * Clears the internal template cache. * * @deprecated since 1.18.3 (to be removed in 2.0) */ public function clearTemplateCache() { @trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); $this->loadedTemplates = array(); } /** * Clears the template cache files on the filesystem. * * @deprecated since 1.22 (to be removed in 2.0) */ public function clearCacheFiles() { @trigger_error(sprintf('The %s method is deprecated 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 ($file->isFile()) { @unlink($file->getPathname()); } } } } /** * Gets the Lexer instance. * * @return Twig_LexerInterface A Twig_LexerInterface instance */ public function getLexer() { if (null === $this->lexer) { $this->lexer = new Twig_Lexer($this); } return $this->lexer; } /** * Sets the Lexer instance. * * @param Twig_LexerInterface $lexer A Twig_LexerInterface instance */ public function setLexer(Twig_LexerInterface $lexer) { $this->lexer = $lexer; } /** * Tokenizes a source code. * * @param string $source The template source code * @param string $name The template name * * @return Twig_TokenStream A Twig_TokenStream instance * * @throws Twig_Error_Syntax When the code is syntactically wrong */ public function tokenize($source, $name = null) { return $this->getLexer()->tokenize($source, $name); } /** * Gets the Parser instance. * * @return Twig_ParserInterface A Twig_ParserInterface instance */ public function getParser() { if (null === $this->parser) { $this->parser = new Twig_Parser($this); } return $this->parser; } /** * Sets the Parser instance. * * @param Twig_ParserInterface $parser A Twig_ParserInterface instance */ public function setParser(Twig_ParserInterface $parser) { $this->parser = $parser; } /** * Converts a token stream to a node tree. * * @param Twig_TokenStream $stream A token stream instance * * @return Twig_Node_Module A node tree * * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong */ public function parse(Twig_TokenStream $stream) { return $this->getParser()->parse($stream); } /** * Gets the Compiler instance. * * @return Twig_CompilerInterface A Twig_CompilerInterface instance */ public function getCompiler() { if (null === $this->compiler) { $this->compiler = new Twig_Compiler($this); } return $this->compiler; } /** * Sets the Compiler instance. * * @param Twig_CompilerInterface $compiler A Twig_CompilerInterface instance */ public function setCompiler(Twig_CompilerInterface $compiler) { $this->compiler = $compiler; } /** * Compiles a node and returns the PHP code. * * @param Twig_NodeInterface $node A Twig_NodeInterface instance * * @return string The compiled PHP source code */ public function compile(Twig_NodeInterface $node) { return $this->getCompiler()->compile($node)->getSource(); } /** * Compiles a template source code. * * @param string $source The template source code * @param string $name The template name * * @return string The compiled PHP source code * * @throws Twig_Error_Syntax When there was an error during tokenizing, parsing or compiling */ public function compileSource($source, $name = null) { try { $compiled = $this->compile($this->parse($this->tokenize($source, $name)), $source); if (isset($source[0])) { $compiled .= '/* '.str_replace(array('*/', "\r\n", "\r", "\n"), array('*//* ', "\n", "\n", "*/\n/* "), $source)."*/\n"; } return $compiled; } catch (Twig_Error $e) { $e->setTemplateFile($name); 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, $name, $e); } } /** * Sets the Loader instance. * * @param Twig_LoaderInterface $loader A Twig_LoaderInterface instance */ public function setLoader(Twig_LoaderInterface $loader) { $this->loader = $loader; } /** * Gets the Loader instance. * * @return Twig_LoaderInterface A Twig_LoaderInterface instance */ public function getLoader() { if (null === $this->loader) { throw new LogicException('You must set a loader first.'); } return $this->loader; } /** * Sets the default template charset. * * @param string $charset The default charset */ public function setCharset($charset) { $this->charset = strtoupper($charset); } /** * Gets the default template charset. * * @return string The default charset */ public function getCharset() { return $this->charset; } /** * Initializes the runtime environment. */ public function initRuntime() { $this->runtimeInitialized = true; foreach ($this->getExtensions() as $extension) { $extension->initRuntime($this); } } /** * Returns true if the given extension is registered. * * @param string $name The extension name * * @return bool Whether the extension is registered or not */ public function hasExtension($name) { return isset($this->extensions[$name]); } /** * Gets an extension by name. * * @param string $name The extension name * * @return Twig_ExtensionInterface A Twig_ExtensionInterface instance */ public function getExtension($name) { if (!isset($this->extensions[$name])) { throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $name)); } return $this->extensions[$name]; } /** * Registers an extension. * * @param Twig_ExtensionInterface $extension A Twig_ExtensionInterface instance */ public function addExtension(Twig_ExtensionInterface $extension) { if ($this->extensionInitialized) { throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName())); } $this->extensions[$extension->getName()] = $extension; } /** * Removes an extension by name. * * This method is deprecated and you should not use it. * * @param string $name The extension name * * @deprecated since 1.12 (to be removed in 2.0) */ public function removeExtension($name) { @trigger_error(sprintf('The %s method is deprecated 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)); } unset($this->extensions[$name]); } /** * Registers an array of extensions. * * @param array $extensions An array of extensions */ public function setExtensions(array $extensions) { foreach ($extensions as $extension) { $this->addExtension($extension); } } /** * Returns all registered extensions. * * @return array An array of extensions */ public function getExtensions() { return $this->extensions; } /** * Registers a Token Parser. * * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance */ public function addTokenParser(Twig_TokenParserInterface $parser) { if ($this->extensionInitialized) { throw new LogicException('Unable to add a token parser as extensions have already been initialized.'); } $this->staging->addTokenParser($parser); } /** * Gets the registered Token Parsers. * * @return Twig_TokenParserBrokerInterface A broker containing token parsers */ public function getTokenParsers() { if (!$this->extensionInitialized) { $this->initExtensions(); } return $this->parsers; } /** * Gets registered tags. * * Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes. * * @return Twig_TokenParserInterface[] An array of Twig_TokenParserInterface instances */ public function getTags() { $tags = array(); foreach ($this->getTokenParsers()->getParsers() as $parser) { if ($parser instanceof Twig_TokenParserInterface) { $tags[$parser->getTag()] = $parser; } } return $tags; } /** * Registers a Node Visitor. * * @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance */ public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) { if ($this->extensionInitialized) { throw new LogicException('Unable to add a node visitor as extensions have already been initialized.'); } $this->staging->addNodeVisitor($visitor); } /** * Gets the registered Node Visitors. * * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances */ public function getNodeVisitors() { if (!$this->extensionInitialized) { $this->initExtensions(); } return $this->visitors; } /** * Registers a Filter. * * @param string|Twig_SimpleFilter $name The filter name or a Twig_SimpleFilter instance * @param Twig_FilterInterface|Twig_SimpleFilter $filter A Twig_FilterInterface instance or a Twig_SimpleFilter instance */ 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 Twig_SimpleFilter) { $filter = $name; $name = $filter->getName(); } else { @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleFilter" instead when defining filter "%s".', __METHOD__, $name), E_USER_DEPRECATED); } if ($this->extensionInitialized) { throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name)); } $this->staging->addFilter($name, $filter); } /** * Get a filter by name. * * Subclasses may override this method and load filters differently; * so no list of filters is available. * * @param string $name The filter name * * @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exist */ public function getFilter($name) { if (!$this->extensionInitialized) { $this->initExtensions(); } if (isset($this->filters[$name])) { return $this->filters[$name]; } foreach ($this->filters as $pattern => $filter) { $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); if ($count) { if (preg_match('#^'.$pattern.'$#', $name, $matches)) { array_shift($matches); $filter->setArguments($matches); return $filter; } } } foreach ($this->filterCallbacks as $callback) { if (false !== $filter = call_user_func($callback, $name)) { return $filter; } } return false; } public function registerUndefinedFilterCallback($callable) { $this->filterCallbacks[] = $callable; } /** * Gets the registered Filters. * * Be warned that this method cannot return filters defined with registerUndefinedFunctionCallback. * * @return Twig_FilterInterface[] An array of Twig_FilterInterface instances * * @see registerUndefinedFilterCallback */ public function getFilters() { if (!$this->extensionInitialized) { $this->initExtensions(); } return $this->filters; } /** * 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 */ 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 Twig_SimpleTest) { $test = $name; $name = $test->getName(); } else { @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleTest" instead when defining test "%s".', __METHOD__, $name), E_USER_DEPRECATED); } if ($this->extensionInitialized) { throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name)); } $this->staging->addTest($name, $test); } /** * Gets the registered Tests. * * @return Twig_TestInterface[] An array of Twig_TestInterface instances */ public function getTests() { if (!$this->extensionInitialized) { $this->initExtensions(); } return $this->tests; } /** * Gets a test by name. * * @param string $name The test name * * @return Twig_Test|false A Twig_Test instance or false if the test does not exist */ public function getTest($name) { if (!$this->extensionInitialized) { $this->initExtensions(); } if (isset($this->tests[$name])) { return $this->tests[$name]; } return false; } /** * Registers a Function. * * @param string|Twig_SimpleFunction $name The function name or a Twig_SimpleFunction instance * @param Twig_FunctionInterface|Twig_SimpleFunction $function A Twig_FunctionInterface instance or a Twig_SimpleFunction instance */ 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 Twig_SimpleFunction) { $function = $name; $name = $function->getName(); } else { @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleFunction" instead when defining function "%s".', __METHOD__, $name), E_USER_DEPRECATED); } if ($this->extensionInitialized) { throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name)); } $this->staging->addFunction($name, $function); } /** * Get a function by name. * * Subclasses may override this method and load functions differently; * so no list of functions is available. * * @param string $name function name * * @return Twig_Function|false A Twig_Function instance or false if the function does not exist */ public function getFunction($name) { if (!$this->extensionInitialized) { $this->initExtensions(); } if (isset($this->functions[$name])) { return $this->functions[$name]; } foreach ($this->functions as $pattern => $function) { $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); if ($count) { if (preg_match('#^'.$pattern.'$#', $name, $matches)) { array_shift($matches); $function->setArguments($matches); return $function; } } } foreach ($this->functionCallbacks as $callback) { if (false !== $function = call_user_func($callback, $name)) { return $function; } } return false; } public function registerUndefinedFunctionCallback($callable) { $this->functionCallbacks[] = $callable; } /** * Gets registered functions. * * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback. * * @return Twig_FunctionInterface[] An array of Twig_FunctionInterface instances * * @see registerUndefinedFunctionCallback */ public function getFunctions() { if (!$this->extensionInitialized) { $this->initExtensions(); } return $this->functions; } /** * Registers a Global. * * New globals can be added before compiling or rendering a template; * but after, you can only update existing globals. * * @param string $name The global name * @param mixed $value The global value */ public function addGlobal($name, $value) { if ($this->extensionInitialized || $this->runtimeInitialized) { if (null === $this->globals) { $this->globals = $this->initGlobals(); } 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.', $name), E_USER_DEPRECATED); //throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name)); } } if ($this->extensionInitialized || $this->runtimeInitialized) { // update the value $this->globals[$name] = $value; } else { $this->staging->addGlobal($name, $value); } } /** * Gets the registered Globals. * * @return array An array of globals */ public function getGlobals() { if (!$this->runtimeInitialized && !$this->extensionInitialized) { return $this->initGlobals(); } if (null === $this->globals) { $this->globals = $this->initGlobals(); } return $this->globals; } /** * Merges a context with the defined globals. * * @param array $context An array representing the context * * @return array The context merged with the globals */ public function mergeGlobals(array $context) { // 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)) { $context[$key] = $value; } } return $context; } /** * Gets the registered unary Operators. * * @return array An array of unary operators */ public function getUnaryOperators() { if (!$this->extensionInitialized) { $this->initExtensions(); } return $this->unaryOperators; } /** * Gets the registered binary Operators. * * @return array An array of binary operators */ public function getBinaryOperators() { if (!$this->extensionInitialized) { $this->initExtensions(); } return $this->binaryOperators; } public function computeAlternatives($name, $items) { $alternatives = array(); foreach ($items as $item) { $lev = levenshtein($name, $item); if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { $alternatives[$item] = $lev; } } asort($alternatives); return array_keys($alternatives); } protected function initGlobals() { $globals = array(); foreach ($this->extensions as $extension) { $extGlob = $extension->getGlobals(); if (!is_array($extGlob)) { throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension))); } $globals[] = $extGlob; } $globals[] = $this->staging->getGlobals(); return call_user_func_array('array_merge', $globals); } protected function initExtensions() { if ($this->extensionInitialized) { return; } $this->extensionInitialized = true; $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(); foreach ($this->extensions as $extension) { $this->initExtension($extension); } $this->initExtension($this->staging); } protected function initExtension(Twig_ExtensionInterface $extension) { // filters foreach ($extension->getFilters() as $name => $filter) { if ($filter instanceof Twig_SimpleFilter) { $name = $filter->getName(); } else { @trigger_error(sprintf('Using an instance of "%s" for filter "%s" is deprecated. Use Twig_SimpleFilter instead.', get_class($filter), $name), E_USER_DEPRECATED); } $this->filters[$name] = $filter; } // functions foreach ($extension->getFunctions() as $name => $function) { if ($function instanceof Twig_SimpleFunction) { $name = $function->getName(); } else { @trigger_error(sprintf('Using an instance of "%s" for function "%s" is deprecated. Use Twig_SimpleFunction instead.', get_class($function), $name), E_USER_DEPRECATED); } $this->functions[$name] = $function; } // tests foreach ($extension->getTests() as $name => $test) { if ($test instanceof Twig_SimpleTest) { $name = $test->getName(); } else { @trigger_error(sprintf('Using an instance of "%s" for test "%s" is deprecated. Use Twig_SimpleTest instead.', get_class($test), $name), E_USER_DEPRECATED); } $this->tests[$name] = $test; } // token parsers foreach ($extension->getTokenParsers() as $parser) { if ($parser instanceof Twig_TokenParserInterface) { $this->parsers->addTokenParser($parser); } elseif ($parser instanceof Twig_TokenParserBrokerInterface) { @trigger_error('Registering a Twig_TokenParserBrokerInterface instance is deprecated.', E_USER_DEPRECATED); $this->parsers->addTokenParserBroker($parser); } else { throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances'); } } // node visitors foreach ($extension->getNodeVisitors() as $visitor) { $this->visitors[] = $visitor; } // operators if ($operators = $extension->getOperators()) { if (2 !== count($operators)) { throw new InvalidArgumentException(sprintf('"%s::getOperators()" does not return a valid operators array.', get_class($extension))); } $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]); $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]); } } /** * @deprecated since 1.22 (to be removed in 2.0) */ protected function writeCacheFile($file, $content) { $this->cache->write($file, $content); } } * * @deprecated since 1.12 (to be removed in 2.0) */ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface { protected $options; protected $arguments = array(); public function __construct(array $options = array()) { $this->options = array_merge(array( 'needs_environment' => false, 'needs_context' => false, 'pre_escape' => null, 'preserves_safety' => null, 'callable' => null, ), $options); } public function setArguments($arguments) { $this->arguments = $arguments; } public function getArguments() { return $this->arguments; } public function needsEnvironment() { return $this->options['needs_environment']; } public function needsContext() { return $this->options['needs_context']; } public function getSafe(Twig_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); } } public function getPreservesSafety() { return $this->options['preserves_safety']; } public function getPreEscape() { return $this->options['pre_escape']; } public function getCallable() { return $this->options['callable']; } } */ class Twig_TokenStream { protected $tokens; protected $current = 0; protected $filename; /** * Constructor. * * @param array $tokens An array of tokens * @param string $filename The name of the filename which tokens are associated with */ public function __construct(array $tokens, $filename = null) { $this->tokens = $tokens; $this->filename = $filename; } /** * Returns a string representation of the token stream. * * @return string */ public function __toString() { return implode("\n", $this->tokens); } public function injectTokens(array $tokens) { $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 */ 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->filename); } return $this->tokens[$this->current - 1]; } /** * 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 */ public function nextIf($primary, $secondary = null) { if ($this->tokens[$this->current]->test($primary, $secondary)) { return $this->next(); } } /** * Tests a token and returns it or throws a syntax error. * * @return Twig_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)', $message ? $message.'. ' : '', Twig_Token::typeToEnglish($token->getType()), $token->getValue(), Twig_Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''), $line, $this->filename ); } $this->next(); return $token; } /** * Looks at the next token. * * @param int $number * * @return Twig_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->filename); } return $this->tokens[$this->current + $number]; } /** * Tests the current token. * * @return bool */ public function test($primary, $secondary = null) { return $this->tokens[$this->current]->test($primary, $secondary); } /** * Checks if end of stream was reached. * * @return bool */ public function isEOF() { return $this->tokens[$this->current]->getType() === Twig_Token::EOF_TYPE; } /** * Gets the current token. * * @return Twig_Token */ public function getCurrent() { return $this->tokens[$this->current]; } /** * Gets the filename associated with this stream. * * @return string */ public function getFilename() { return $this->filename; } } */ interface Twig_Sandbox_SecurityPolicyInterface { public function checkSecurity($tags, $filters, $functions); public function checkMethodAllowed($obj, $method); public function checkPropertyAllowed($obj, $method); } */ class Twig_Sandbox_SecurityNotAllowedTagError extends Twig_Sandbox_SecurityError { private $tagName; public function __construct($message, $tagName, $lineno = -1, $filename = null, Exception $previous = null) { parent::__construct($message, $lineno, $filename, $previous); $this->tagName = $tagName; } public function getTagName() { return $this->tagName; } } */ class Twig_Sandbox_SecurityNotAllowedFunctionError extends Twig_Sandbox_SecurityError { private $functionName; public function __construct($message, $functionName, $lineno = -1, $filename = null, Exception $previous = null) { parent::__construct($message, $lineno, $filename, $previous); $this->functionName = $functionName; } public function getFunctionName() { return $this->functionName; } } */ class Twig_Sandbox_SecurityNotAllowedFilterError extends Twig_Sandbox_SecurityError { private $filterName; public function __construct($message, $functionName, $lineno = -1, $filename = null, Exception $previous = null) { parent::__construct($message, $lineno, $filename, $previous); $this->filterName = $functionName; } public function getFilterName() { return $this->filterName; } } */ class Twig_Sandbox_SecurityError extends Twig_Error { } */ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterface { protected $allowedTags; protected $allowedFilters; protected $allowedMethods; protected $allowedProperties; protected $allowedFunctions; public function __construct(array $allowedTags = array(), array $allowedFilters = array(), array $allowedMethods = array(), array $allowedProperties = array(), array $allowedFunctions = array()) { $this->allowedTags = $allowedTags; $this->allowedFilters = $allowedFilters; $this->setAllowedMethods($allowedMethods); $this->allowedProperties = $allowedProperties; $this->allowedFunctions = $allowedFunctions; } public function setAllowedTags(array $tags) { $this->allowedTags = $tags; } public function setAllowedFilters(array $filters) { $this->allowedFilters = $filters; } public function setAllowedMethods(array $methods) { $this->allowedMethods = array(); foreach ($methods as $class => $m) { $this->allowedMethods[$class] = array_map('strtolower', is_array($m) ? $m : array($m)); } } public function setAllowedProperties(array $properties) { $this->allowedProperties = $properties; } public function setAllowedFunctions(array $functions) { $this->allowedFunctions = $functions; } 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); } } foreach ($filters as $filter) { if (!in_array($filter, $this->allowedFilters)) { throw new Twig_Sandbox_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); } } } public function checkMethodAllowed($obj, $method) { if ($obj instanceof Twig_TemplateInterface || $obj instanceof Twig_Markup) { return true; } $allowed = false; $method = strtolower($method); foreach ($this->allowedMethods as $class => $methods) { if ($obj instanceof $class) { $allowed = in_array($method, $methods); break; } } if (!$allowed) { throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj))); } } public function checkPropertyAllowed($obj, $property) { $allowed = false; foreach ($this->allowedProperties as $class => $properties) { if ($obj instanceof $class) { $allowed = in_array($property, is_array($properties) ? $properties : array($properties)); break; } } if (!$allowed) { throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, get_class($obj))); } } } */ class Twig_Node implements Twig_NodeInterface { protected $nodes; protected $attributes; protected $lineno; protected $tag; /** * 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) { $this->nodes = $nodes; $this->attributes = $attributes; $this->lineno = $lineno; $this->tag = $tag; } public function __toString() { $attributes = array(); 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)); if (count($this->nodes)) { foreach ($this->nodes as $name => $node) { $len = strlen($name) + 4; $noderepr = array(); foreach (explode("\n", (string) $node) as $line) { $noderepr[] = str_repeat(' ', $len).$line; } $repr[] = sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr))); } $repr[] = ')'; } else { $repr[0] .= ')'; } return implode("\n", $repr); } /** * @deprecated since 1.16.1 (to be removed in 2.0) */ public function toXml($asDom = false) { @trigger_error(sprintf('%s is deprecated.', __METHOD__), E_USER_DEPRECATED); $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)); foreach ($this->attributes as $name => $value) { $node->appendChild($attribute = $dom->createElement('attribute')); $attribute->setAttribute('name', $name); $attribute->appendChild($dom->createTextNode($value)); } foreach ($this->nodes as $name => $n) { if (null === $n) { continue; } $child = $n->toXml(true)->getElementsByTagName('node')->item(0); $child = $dom->importNode($child, true); $child->setAttribute('name', $name); $node->appendChild($child); } return $asDom ? $dom : $dom->saveXml(); } public function compile(Twig_Compiler $compiler) { foreach ($this->nodes as $node) { $node->compile($compiler); } } public function getLine() { return $this->lineno; } public function getNodeTag() { return $this->tag; } /** * Returns true if the attribute is defined. * * @param string $name The attribute name * * @return bool true if the attribute is defined, false otherwise */ public function hasAttribute($name) { return array_key_exists($name, $this->attributes); } /** * Gets an attribute value by name. * * @param string $name * * @return mixed */ 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))); } return $this->attributes[$name]; } /** * Sets an attribute by name to a value. * * @param string $name * @param mixed $value */ public function setAttribute($name, $value) { $this->attributes[$name] = $value; } /** * Removes an attribute by name. * * @param string $name */ public function removeAttribute($name) { unset($this->attributes[$name]); } /** * Returns true if the node with the given name exists. * * @param string $name * * @return bool */ public function hasNode($name) { return array_key_exists($name, $this->nodes); } /** * Gets a node by name. * * @param string $name * * @return Twig_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))); } return $this->nodes[$name]; } /** * Sets a node. * * @param string $name * @param Twig_Node $node */ public function setNode($name, $node = null) { $this->nodes[$name] = $node; } /** * Removes a node by name. * * @param string $name */ public function removeNode($name) { unset($this->nodes[$name]); } public function count() { return count($this->nodes); } public function getIterator() { return new ArrayIterator($this->nodes); } } */ class Twig_Token { protected $value; protected $type; protected $lineno; const EOF_TYPE = -1; const TEXT_TYPE = 0; const BLOCK_START_TYPE = 1; const VAR_START_TYPE = 2; const BLOCK_END_TYPE = 3; const VAR_END_TYPE = 4; const NAME_TYPE = 5; const NUMBER_TYPE = 6; const STRING_TYPE = 7; const OPERATOR_TYPE = 8; const PUNCTUATION_TYPE = 9; const INTERPOLATION_START_TYPE = 10; const INTERPOLATION_END_TYPE = 11; /** * Constructor. * * @param int $type The type of the token * @param string $value The token value * @param int $lineno The line position in the source */ public function __construct($type, $value, $lineno) { $this->type = $type; $this->value = $value; $this->lineno = $lineno; } /** * Returns a string representation of the token. * * @return string A string representation of the token */ public function __toString() { return sprintf('%s(%s)', self::typeToString($this->type, true), $this->value); } /** * Tests the current token for a type and/or a value. * * Parameters may be: * * just type * * 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|null $values The token value * * @return bool */ public function test($type, $values = null) { 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)) || $this->value == $values ); } /** * Gets the line. * * @return int The source line */ public function getLine() { return $this->lineno; } /** * Gets the token type. * * @return int The token type */ public function getType() { return $this->type; } /** * Gets the token value. * * @return string The token value */ public function getValue() { return $this->value; } /** * Returns the constant representation (internal) of a given type. * * @param int $type The type as an integer * @param bool $short Whether to return a short representation or not * * @return string The string representation */ public static function typeToString($type, $short = false) { switch ($type) { case self::EOF_TYPE: $name = 'EOF_TYPE'; break; case self::TEXT_TYPE: $name = 'TEXT_TYPE'; break; case self::BLOCK_START_TYPE: $name = 'BLOCK_START_TYPE'; break; case self::VAR_START_TYPE: $name = 'VAR_START_TYPE'; break; case self::BLOCK_END_TYPE: $name = 'BLOCK_END_TYPE'; break; case self::VAR_END_TYPE: $name = 'VAR_END_TYPE'; break; case self::NAME_TYPE: $name = 'NAME_TYPE'; break; case self::NUMBER_TYPE: $name = 'NUMBER_TYPE'; break; case self::STRING_TYPE: $name = 'STRING_TYPE'; break; case self::OPERATOR_TYPE: $name = 'OPERATOR_TYPE'; break; case self::PUNCTUATION_TYPE: $name = 'PUNCTUATION_TYPE'; break; case self::INTERPOLATION_START_TYPE: $name = 'INTERPOLATION_START_TYPE'; break; case self::INTERPOLATION_END_TYPE: $name = 'INTERPOLATION_END_TYPE'; break; default: throw new LogicException(sprintf('Token of type "%s" does not exist.', $type)); } return $short ? $name : 'Twig_Token::'.$name; } /** * Returns the english representation of a given type. * * @param int $type The type as an integer * * @return string The string representation */ public static function typeToEnglish($type) { switch ($type) { case self::EOF_TYPE: return 'end of template'; case self::TEXT_TYPE: return 'text'; case self::BLOCK_START_TYPE: return 'begin of statement block'; case self::VAR_START_TYPE: return 'begin of print statement'; case self::BLOCK_END_TYPE: return 'end of statement block'; case self::VAR_END_TYPE: return 'end of print statement'; case self::NAME_TYPE: return 'name'; case self::NUMBER_TYPE: return 'number'; case self::STRING_TYPE: return 'string'; case self::OPERATOR_TYPE: return 'operator'; case self::PUNCTUATION_TYPE: return 'punctuation'; case self::INTERPOLATION_START_TYPE: return 'begin of string interpolation'; case self::INTERPOLATION_END_TYPE: return 'end of string interpolation'; default: throw new LogicException(sprintf('Token of type "%s" does not exist.', $type)); } } } */ interface Twig_NodeOutputInterface { } */ class Twig_FileExtensionEscapingStrategy { /** * Guesses the best autoescaping strategy based on the file name. * * @param string $filename The template file name * * @return string|false The escaping strategy name to use or false to disable */ public static function guess($filename) { if (in_array(substr($filename, -1), array('/', '\\'))) { return 'html'; // return html for directories } if ('.twig' === substr($filename, -5)) { $filename = substr($filename, 0, -5); } $extension = pathinfo($filename, PATHINFO_EXTENSION); switch ($extension) { case 'js': return 'js'; case 'css': return 'css'; case 'txt': return false; default: return 'html'; } } } * * @deprecated since 1.12 (to be removed in 2.0) */ interface Twig_FunctionInterface { /** * Compiles a function. * * @return string The PHP code for the function */ public function compile(); public function needsEnvironment(); public function needsContext(); public function getSafe(Twig_Node $filterArgs); public function setArguments($arguments); public function getArguments(); } * * @deprecated since 1.12 (to be removed in 2.0) */ interface Twig_FilterInterface { /** * Compiles a filter. * * @return string The PHP code for the filter */ public function compile(); public function needsEnvironment(); public function needsContext(); public function getSafe(Twig_Node $filterArgs); public function getPreservesSafety(); public function getPreEscape(); public function setArguments($arguments); public function getArguments(); } */ class Twig_Cache_Filesystem implements Twig_CacheInterface { const FORCE_BYTECODE_INVALIDATION = 1; private $directory; private $options; /** * @param $directory string The root cache directory * @param $options int A set of options */ public function __construct($directory, $options = 0) { $this->directory = $directory; $this->options = $options; } /** * {@inheritdoc} */ public function generateKey($name, $className) { $hash = hash('sha256', $className); return $this->directory.'/'.$hash[0].'/'.$hash[1].'/'.$hash.'.php'; } /** * {@inheritdoc} */ public function load($key) { @include_once $key; } /** * {@inheritdoc} */ public function write($key, $content) { $dir = dirname($key); if (!is_dir($dir)) { if (false === @mkdir($dir, 0777, true) && !is_dir($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)); } $tmpFile = tempnam($dir, basename($key)); if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $key)) { @chmod($key, 0666 & ~umask()); 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')) { apc_compile_file($key); } } return; } throw new RuntimeException(sprintf('Failed to write cache file "%s".', $key)); } /** * {@inheritdoc} */ public function getTimestamp($key) { return (int) @filemtime($key); } } */ class Twig_Cache_Null implements Twig_CacheInterface { /** * {@inheritdoc} */ public function generateKey($name, $className) { return ''; } /** * {@inheritdoc} */ public function write($key, $content) { } /** * {@inheritdoc} */ public function load($key) { } /** * {@inheritdoc} */ public function getTimestamp($key) { return 0; } } * * @deprecated since 1.12 (to be removed in 3.0) */ interface Twig_LexerInterface { /** * Tokenizes a source code. * * @param string $code The source code * @param string $filename A unique identifier for the source code * * @return Twig_TokenStream A token stream instance * * @throws Twig_Error_Syntax When the code is syntactically wrong */ public function tokenize($code, $filename = null); } * * @deprecated since 1.12 (to be removed in 2.0) */ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface { protected $parser; protected $parsers = array(); protected $brokers = array(); /** * Constructor. * * @param array|Traversable $parsers A Traversable of Twig_TokenParserInterface instances * @param array|Traversable $brokers A Traversable of Twig_TokenParserBrokerInterface instances */ public function __construct($parsers = array(), $brokers = array(), $triggerDeprecationError = true) { if ($triggerDeprecationError) { @trigger_error('The '.__CLASS__.' class is deprecated since version 1.12 and will be removed in 2.0.', E_USER_DEPRECATED); } foreach ($parsers as $parser) { if (!$parser instanceof Twig_TokenParserInterface) { throw new LogicException('$parsers must a an array of Twig_TokenParserInterface'); } $this->parsers[$parser->getTag()] = $parser; } foreach ($brokers as $broker) { if (!$broker instanceof Twig_TokenParserBrokerInterface) { throw new LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface'); } $this->brokers[] = $broker; } } /** * Adds a TokenParser. * * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance */ public function addTokenParser(Twig_TokenParserInterface $parser) { $this->parsers[$parser->getTag()] = $parser; } /** * Removes a TokenParser. * * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance */ public function removeTokenParser(Twig_TokenParserInterface $parser) { $name = $parser->getTag(); if (isset($this->parsers[$name]) && $parser === $this->parsers[$name]) { unset($this->parsers[$name]); } } /** * Adds a TokenParserBroker. * * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance */ public function addTokenParserBroker(Twig_TokenParserBroker $broker) { $this->brokers[] = $broker; } /** * Removes a TokenParserBroker. * * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance */ public function removeTokenParserBroker(Twig_TokenParserBroker $broker) { if (false !== $pos = array_search($broker, $this->brokers)) { unset($this->brokers[$pos]); } } /** * Gets a suitable TokenParser for a tag. * * First looks in parsers, then in brokers. * * @param string $tag A tag name * * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found */ public function getTokenParser($tag) { if (isset($this->parsers[$tag])) { return $this->parsers[$tag]; } $broker = end($this->brokers); while (false !== $broker) { $parser = $broker->getTokenParser($tag); if (null !== $parser) { return $parser; } $broker = prev($this->brokers); } } public function getParsers() { return $this->parsers; } public function getParser() { return $this->parser; } public function setParser(Twig_ParserInterface $parser) { $this->parser = $parser; foreach ($this->parsers as $tokenParser) { $tokenParser->setParser($parser); } foreach ($this->brokers as $broker) { $broker->setParser($parser); } } } */ interface Twig_NodeVisitorInterface { /** * Called before child nodes are visited. * * @param Twig_NodeInterface $node The node to visit * @param Twig_Environment $env The Twig environment instance * * @return Twig_NodeInterface The modified node */ public function enterNode(Twig_NodeInterface $node, Twig_Environment $env); /** * Called after child nodes are visited. * * @param Twig_NodeInterface $node The node to visit * @param Twig_Environment $env The Twig environment instance * * @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(); } * * @deprecated since 1.12 (to be removed in 3.0) */ interface Twig_TemplateInterface { const ANY_CALL = 'any'; const ARRAY_CALL = 'array'; const METHOD_CALL = 'method'; /** * Renders the template with the given context and returns it as string. * * @param array $context An array of parameters to pass to the template * * @return string The rendered template */ public function render(array $context); /** * Displays the template with the given context. * * @param array $context An array of parameters to pass to the template * @param array $blocks An array of blocks to pass to the template */ public function display(array $context, array $blocks = array()); /** * Returns the bound environment for this template. * * @return Twig_Environment The current environment */ public function getEnvironment(); } */ abstract class Twig_TokenParser implements Twig_TokenParserInterface { /** * @var Twig_Parser */ protected $parser; /** * Sets the parser associated with this token parser. * * @param Twig_Parser $parser A Twig_Parser instance */ public function setParser(Twig_Parser $parser) { $this->parser = $parser; } } */ class Twig_SimpleTest { protected $name; protected $callable; protected $options; public function __construct($name, $callable, array $options = array()) { $this->name = $name; $this->callable = $callable; $this->options = array_merge(array( 'is_variadic' => false, 'node_class' => 'Twig_Node_Expression_Test', 'deprecated' => false, 'alternative' => null, ), $options); } public function getName() { return $this->name; } public function getCallable() { return $this->callable; } public function getNodeClass() { return $this->options['node_class']; } public function isVariadic() { return $this->options['is_variadic']; } public function isDeprecated() { return $this->options['deprecated']; } public function getAlternative() { return $this->options['alternative']; } } * * @deprecated since 1.12 (to be removed in 2.0) */ class Twig_Function_Function extends Twig_Function { protected $function; public function __construct($function, array $options = array()) { $options['callable'] = $function; parent::__construct($options); $this->function = $function; } public function compile() { return $this->function; } } * * @deprecated since 1.12 (to be removed in 2.0) */ class Twig_Function_Method extends Twig_Function { protected $extension; protected $method; public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) { $options['callable'] = array($extension, $method); parent::__construct($options); $this->extension = $extension; $this->method = $method; } public function compile() { return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method); } } * * @deprecated since 1.12 (to be removed in 2.0) */ class Twig_Function_Node extends Twig_Function { protected $class; public function __construct($class, array $options = array()) { parent::__construct($options); $this->class = $class; } public function getClass() { return $this->class; } public function compile() { } } */ class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface { /** * {@inheritdoc} */ public function getSource($name) { return $name; } /** * {@inheritdoc} */ public function exists($name) { return true; } /** * {@inheritdoc} */ public function getCacheKey($name) { return $name; } /** * {@inheritdoc} */ public function isFresh($name, $time) { return true; } } */ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface { protected $templates = array(); /** * Constructor. * * @param array $templates An array of templates (keys are the names, and values are the source code) */ public function __construct(array $templates) { $this->templates = $templates; } /** * Adds or overrides a template. * * @param string $name The template name * @param string $template The template source */ public function setTemplate($name, $template) { $this->templates[(string) $name] = $template; } /** * {@inheritdoc} */ public function getSource($name) { $name = (string) $name; if (!isset($this->templates[$name])) { throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); } return $this->templates[$name]; } /** * {@inheritdoc} */ public function exists($name) { return isset($this->templates[(string) $name]); } /** * {@inheritdoc} */ public function getCacheKey($name) { $name = (string) $name; if (!isset($this->templates[$name])) { throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); } return $this->templates[$name]; } /** * {@inheritdoc} */ public function isFresh($name, $time) { $name = (string) $name; if (!isset($this->templates[$name])) { throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); } return true; } } */ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface { private $hasSourceCache = array(); protected $loaders = array(); /** * Constructor. * * @param Twig_LoaderInterface[] $loaders An array of loader instances */ public function __construct(array $loaders = array()) { foreach ($loaders as $loader) { $this->addLoader($loader); } } /** * Adds a loader instance. * * @param Twig_LoaderInterface $loader A Loader instance */ public function addLoader(Twig_LoaderInterface $loader) { $this->loaders[] = $loader; $this->hasSourceCache = array(); } /** * {@inheritdoc} */ public function getSource($name) { $exceptions = array(); foreach ($this->loaders as $loader) { if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { continue; } try { return $loader->getSource($name); } catch (Twig_Error_Loader $e) { $exceptions[] = $e->getMessage(); } } throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } /** * {@inheritdoc} */ public function exists($name) { $name = (string) $name; if (isset($this->hasSourceCache[$name])) { return $this->hasSourceCache[$name]; } foreach ($this->loaders as $loader) { if ($loader instanceof Twig_ExistsLoaderInterface) { if ($loader->exists($name)) { return $this->hasSourceCache[$name] = true; } continue; } try { $loader->getSource($name); return $this->hasSourceCache[$name] = true; } catch (Twig_Error_Loader $e) { } } return $this->hasSourceCache[$name] = false; } /** * {@inheritdoc} */ public function getCacheKey($name) { $exceptions = array(); foreach ($this->loaders as $loader) { if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { continue; } try { return $loader->getCacheKey($name); } catch (Twig_Error_Loader $e) { $exceptions[] = get_class($loader).': '.$e->getMessage(); } } throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } /** * {@inheritdoc} */ public function isFresh($name, $time) { $exceptions = array(); foreach ($this->loaders as $loader) { if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { continue; } try { return $loader->isFresh($name, $time); } catch (Twig_Error_Loader $e) { $exceptions[] = get_class($loader).': '.$e->getMessage(); } } throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } } */ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface { /** Identifier of the main namespace. */ const MAIN_NAMESPACE = '__main__'; protected $paths = array(); protected $cache = array(); protected $errorCache = array(); /** * Constructor. * * @param string|array $paths A path or an array of paths where to look for templates */ public function __construct($paths = array()) { if ($paths) { $this->setPaths($paths); } } /** * Returns the paths to the templates. * * @param string $namespace A path namespace * * @return array The array of paths where to look for templates */ public function getPaths($namespace = self::MAIN_NAMESPACE) { return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array(); } /** * Returns the path namespaces. * * The main namespace is always defined. * * @return array The array of defined namespaces */ public function getNamespaces() { return array_keys($this->paths); } /** * Sets the paths where templates are stored. * * @param string|array $paths A path or an array of paths where to look for templates * @param string $namespace A path namespace */ public function setPaths($paths, $namespace = self::MAIN_NAMESPACE) { if (!is_array($paths)) { $paths = array($paths); } $this->paths[$namespace] = array(); foreach ($paths as $path) { $this->addPath($path, $namespace); } } /** * Adds a path where templates are stored. * * @param string $path A path where to look for templates * @param string $namespace A path name * * @throws Twig_Error_Loader */ public function addPath($path, $namespace = self::MAIN_NAMESPACE) { // invalidate the cache $this->cache = $this->errorCache = array(); if (!is_dir($path)) { throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path)); } $this->paths[$namespace][] = rtrim($path, '/\\'); } /** * Prepends a path where templates are stored. * * @param string $path A path where to look for templates * @param string $namespace A path name * * @throws Twig_Error_Loader */ public function prependPath($path, $namespace = self::MAIN_NAMESPACE) { // invalidate the cache $this->cache = $this->errorCache = array(); if (!is_dir($path)) { throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path)); } $path = rtrim($path, '/\\'); if (!isset($this->paths[$namespace])) { $this->paths[$namespace][] = $path; } else { array_unshift($this->paths[$namespace], $path); } } /** * {@inheritdoc} */ public function getSource($name) { return file_get_contents($this->findTemplate($name)); } /** * {@inheritdoc} */ public function getCacheKey($name) { return $this->findTemplate($name); } /** * {@inheritdoc} */ public function exists($name) { $name = $this->normalizeName($name); if (isset($this->cache[$name])) { return true; } try { return false !== $this->findTemplate($name, false); } catch (Twig_Error_Loader $exception) { return false; } } /** * {@inheritdoc} */ public function isFresh($name, $time) { return filemtime($this->findTemplate($name)) <= $time; } protected function findTemplate($name) { $throw = func_num_args() > 1 ? func_get_arg(1) : true; $name = $this->normalizeName($name); if (isset($this->cache[$name])) { return $this->cache[$name]; } if (isset($this->errorCache[$name])) { if (!$throw) { return false; } throw new Twig_Error_Loader($this->errorCache[$name]); } $this->validateName($name); list($namespace, $shortname) = $this->parseName($name); if (!isset($this->paths[$namespace])) { $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace); if (!$throw) { return false; } throw new Twig_Error_Loader($this->errorCache[$name]); } foreach ($this->paths[$namespace] as $path) { if (is_file($path.'/'.$shortname)) { if (false !== $realpath = realpath($path.'/'.$shortname)) { return $this->cache[$name] = $realpath; } return $this->cache[$name] = $path.'/'.$shortname; } } $this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])); if (!$throw) { return false; } throw new Twig_Error_Loader($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)); } $namespace = substr($name, 1, $pos - 1); $shortname = substr($name, $pos + 1); return array($namespace, $shortname); } return array($default, $name); } protected function normalizeName($name) { return preg_replace('#/{2,}#', '/', str_replace('\\', '/', (string) $name)); } protected function validateName($name) { if (false !== strpos($name, "\0")) { throw new Twig_Error_Loader('A template name cannot contain NUL bytes.'); } $name = ltrim($name, '/'); $parts = explode('/', $name); $level = 0; foreach ($parts as $part) { if ('..' === $part) { --$level; } elseif ('.' !== $part) { ++$level; } if ($level < 0) { throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); } } } } * * @deprecated since 1.12 (to be removed in 3.0) */ interface Twig_NodeInterface extends Countable, IteratorAggregate { /** * Compiles the node to PHP. * * @param Twig_Compiler $compiler A Twig_Compiler instance */ public function compile(Twig_Compiler $compiler); public function getLine(); public function getNodeTag(); } */ class Twig_Profiler_Node_EnterProfile extends Twig_Node { public function __construct($extensionName, $type, $name, $varName) { parent::__construct(array(), array('extension_name' => $extensionName, 'name' => $name, 'type' => $type, 'var_name' => $varName)); } /** * {@inheritdoc} */ public function compile(Twig_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')) ->repr($this->getAttribute('type')) ->raw(', ') ->repr($this->getAttribute('name')) ->raw("));\n\n") ; } } */ class Twig_Profiler_Node_LeaveProfile extends Twig_Node { public function __construct($varName) { parent::__construct(array(), array('var_name' => $varName)); } /** * {@inheritdoc} */ public function compile(Twig_Compiler $compiler) { $compiler ->write("\n") ->write(sprintf("\$%s->leave(\$%s);\n\n", $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) ; } } */ class Twig_Profiler_NodeVisitor_Profiler extends Twig_BaseNodeVisitor { private $extensionName; public function __construct($extensionName) { $this->extensionName = $extensionName; } /** * {@inheritdoc} */ protected function doEnterNode(Twig_Node $node, Twig_Environment $env) { return $node; } /** * {@inheritdoc} */ 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->getAttribute('filename'), $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)); } /** * {@inheritdoc} */ public function getPriority() { return 0; } } */ class Twig_Profiler_Dumper_Html extends Twig_Profiler_Dumper_Text { private static $colors = array( 'block' => '#dfd', 'macro' => '#ddf', 'template' => '#ffd', 'big' => '#d44', ); public function dump(Twig_Profiler_Profile $profile) { return '
'.parent::dump($profile).'
'; } protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix) { return sprintf('%s└ %s', $prefix, self::$colors['template'], $profile->getTemplate()); } protected function formatNonTemplate(Twig_Profiler_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) { return sprintf('%.2fms/%.0f%%', $percent > 20 ? self::$colors['big'] : 'auto', $profile->getDuration() * 1000, $percent); } } */ class Twig_Profiler_Dumper_Text { private $root; public function dump(Twig_Profiler_Profile $profile) { return $this->dumpProfile($profile); } protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix) { return sprintf('%s└ %s', $prefix, $profile->getTemplate()); } protected function formatNonTemplate(Twig_Profiler_Profile $profile, $prefix) { return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName()); } protected function formatTime(Twig_Profiler_Profile $profile, $percent) { return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent); } private function dumpProfile(Twig_Profiler_Profile $profile, $prefix = '', $sibling = false) { if ($profile->isRoot()) { $this->root = $profile->getDuration(); $start = $profile->getName(); } else { if ($profile->isTemplate()) { $start = $this->formatTemplate($profile, $prefix); } else { $start = $this->formatNonTemplate($profile, $prefix); } $prefix .= $sibling ? '│ ' : ' '; } $percent = $this->root ? $profile->getDuration() / $this->root * 100 : 0; if ($profile->getDuration() * 1000 < 1) { $str = $start."\n"; } else { $str = sprintf("%s %s\n", $start, $this->formatTime($profile, $percent)); } $nCount = count($profile->getProfiles()); foreach ($profile as $i => $p) { $str .= $this->dumpProfile($p, $prefix, $i + 1 !== $nCount); } return $str; } } */ class Twig_Profiler_Dumper_Blackfire { public function dump(Twig_Profiler_Profile $profile) { $data = array(); $this->dumpProfile('main()', $profile, $data); $this->dumpChildren('main()', $profile, $data); $start = microtime(true); $str = << $values) { $str .= "{$name}//{$values['ct']} {$values['wt']} {$values['mu']} {$values['pmu']}\n"; } return $str; } private function dumpChildren($parent, Twig_Profiler_Profile $profile, &$data) { foreach ($profile as $p) { if ($p->isTemplate()) { $name = $p->getTemplate(); } else { $name = sprintf('%s::%s(%s)', $p->getTemplate(), $p->getType(), $p->getName()); } $this->dumpProfile(sprintf('%s==>%s', $parent, $name), $p, $data); $this->dumpChildren($name, $p, $data); } } private function dumpProfile($edge, Twig_Profiler_Profile $profile, &$data) { if (isset($data[$edge])) { $data[$edge]['ct'] += 1; $data[$edge]['wt'] += floor($profile->getDuration() * 1000000); $data[$edge]['mu'] += $profile->getMemoryUsage(); $data[$edge]['pmu'] += $profile->getPeakMemoryUsage(); } else { $data[$edge] = array( 'ct' => 1, 'wt' => floor($profile->getDuration() * 1000000), 'mu' => $profile->getMemoryUsage(), 'pmu' => $profile->getPeakMemoryUsage(), ); } } } */ class Twig_Profiler_Profile implements IteratorAggregate, Serializable { const ROOT = 'ROOT'; const BLOCK = 'block'; const TEMPLATE = 'template'; const MACRO = 'macro'; private $template; private $name; private $type; private $starts = array(); private $ends = array(); private $profiles = array(); public function __construct($template = 'main', $type = self::ROOT, $name = 'main') { $this->template = $template; $this->type = $type; $this->name = 0 === strpos($name, '__internal_') ? 'INTERNAL' : $name; $this->enter(); } public function getTemplate() { return $this->template; } public function getType() { return $this->type; } public function getName() { return $this->name; } public function isRoot() { return self::ROOT === $this->type; } public function isTemplate() { return self::TEMPLATE === $this->type; } public function isBlock() { return self::BLOCK === $this->type; } public function isMacro() { return self::MACRO === $this->type; } public function getProfiles() { return $this->profiles; } public function addProfile(Twig_Profiler_Profile $profile) { $this->profiles[] = $profile; } /** * Returns the duration in microseconds. * * @return int */ public function getDuration() { if ($this->isRoot() && $this->profiles) { // for the root node with children, duration is the sum of all child durations $duration = 0; foreach ($this->profiles as $profile) { $duration += $profile->getDuration(); } return $duration; } return isset($this->ends['wt']) && isset($this->starts['wt']) ? $this->ends['wt'] - $this->starts['wt'] : 0; } /** * Returns the memory usage in bytes. * * @return int */ public function getMemoryUsage() { return isset($this->ends['mu']) && isset($this->starts['mu']) ? $this->ends['mu'] - $this->starts['mu'] : 0; } /** * Returns the peak memory usage in bytes. * * @return int */ public function getPeakMemoryUsage() { return isset($this->ends['pmu']) && isset($this->starts['pmu']) ? $this->ends['pmu'] - $this->starts['pmu'] : 0; } /** * Starts the profiling. */ public function enter() { $this->starts = array( 'wt' => microtime(true), 'mu' => memory_get_usage(), 'pmu' => memory_get_peak_usage(), ); } /** * Stops the profiling. */ public function leave() { $this->ends = array( 'wt' => microtime(true), 'mu' => memory_get_usage(), 'pmu' => memory_get_peak_usage(), ); } public function getIterator() { return new ArrayIterator($this->profiles); } public function serialize() { return serialize(array($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles)); } public function unserialize($data) { list($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles) = unserialize($data); } } */ interface Twig_ExtensionInterface { /** * Initializes the runtime environment. * * This is where you can load some file that contains filter functions for instance. * * @param Twig_Environment $environment The current Twig_Environment instance */ public function initRuntime(Twig_Environment $environment); /** * Returns the token parser instances to add to the existing list. * * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances */ public function getTokenParsers(); /** * Returns the node visitor instances to add to the existing list. * * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances */ public function getNodeVisitors(); /** * Returns a list of filters to add to the existing list. * * @return array An array of filters */ public function getFilters(); /** * Returns a list of tests to add to the existing list. * * @return array An array of tests */ public function getTests(); /** * Returns a list of functions to add to the existing list. * * @return array An array of functions */ public function getFunctions(); /** * Returns a list of operators to add to the existing list. * * @return array An array of operators */ public function getOperators(); /** * Returns a list of global variables to add to the existing list. * * @return array An array of global variables */ public function getGlobals(); /** * Returns the name of the extension. * * @return string The extension name */ public function getName(); } proxyFactory = $proxyFactory; $this->servicesMap = $servicesMap; } /** * {@inheritDoc} * * @return object|\ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */ public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback) { $initializer = function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($callback) { $proxy->setProxyInitializer(null); $wrappedInstance = call_user_func($callback); return true; }; if (isset($this->servicesMap[$requestedName])) { return $this->proxyFactory->createProxy($this->servicesMap[$requestedName], $initializer); } elseif (isset($this->servicesMap[$name])) { return $this->proxyFactory->createProxy($this->servicesMap[$name], $initializer); } throw new Exception\InvalidServiceNameException( sprintf('The requested service "%s" was not found in the provided services map', $requestedName) ); } } get('Config'); if (!isset($config['lazy_services'])) { throw new Exception\InvalidArgumentException('Missing "lazy_services" config key'); } $lazyServices = $config['lazy_services']; if (!isset($lazyServices['class_map'])) { throw new Exception\InvalidArgumentException('Missing "class_map" config key in "lazy_services"'); } $factoryConfig = new Configuration(); if (isset($lazyServices['proxies_target_dir'])) { $factoryConfig->setProxiesTargetDir($lazyServices['proxies_target_dir']); } if (!isset($lazyServices['write_proxy_files']) || ! $lazyServices['write_proxy_files']) { $factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); } if (isset($lazyServices['auto_generate_proxies'])) { $factoryConfig->setAutoGenerateProxies($lazyServices['auto_generate_proxies']); // register the proxy autoloader if the proxies already exist if (!$lazyServices['auto_generate_proxies']) { spl_autoload_register($factoryConfig->getProxyAutoloader()); $factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); } } //if (!isset($lazyServicesConfig['runtime_evaluate_proxies'])) if (isset($lazyServices['proxies_namespace'])) { $factoryConfig->setProxiesNamespace($lazyServices['proxies_namespace']); } return new LazyServiceFactory(new LazyLoadingValueHolderFactory($factoryConfig), $lazyServices['class_map']); } } config = $config; } /** * Get allow override * * @return null|bool */ public function getAllowOverride() { return (isset($this->config['allow_override'])) ? $this->config['allow_override'] : null; } /** * Get factories * * @return array */ public function getFactories() { return (isset($this->config['factories'])) ? $this->config['factories'] : array(); } /** * Get abstract factories * * @return array */ public function getAbstractFactories() { return (isset($this->config['abstract_factories'])) ? $this->config['abstract_factories'] : array(); } /** * Get invokables * * @return array */ public function getInvokables() { return (isset($this->config['invokables'])) ? $this->config['invokables'] : array(); } /** * Get services * * @return array */ public function getServices() { return (isset($this->config['services'])) ? $this->config['services'] : array(); } /** * Get aliases * * @return array */ public function getAliases() { return (isset($this->config['aliases'])) ? $this->config['aliases'] : array(); } /** * Get initializers * * @return array */ public function getInitializers() { return (isset($this->config['initializers'])) ? $this->config['initializers'] : array(); } /** * Get shared * * @return array */ public function getShared() { return (isset($this->config['shared'])) ? $this->config['shared'] : array(); } /** * Get the delegator services map, with keys being the services acting as delegates, * and values being the delegator factories names * * @return array */ public function getDelegators() { return (isset($this->config['delegators'])) ? $this->config['delegators'] : array(); } /** * Configure service manager * * @param ServiceManager $serviceManager * @return void */ public function configureServiceManager(ServiceManager $serviceManager) { if (($allowOverride = $this->getAllowOverride()) !== null) { $serviceManager->setAllowOverride($allowOverride); } foreach ($this->getFactories() as $name => $factory) { $serviceManager->setFactory($name, $factory); } foreach ($this->getAbstractFactories() as $factory) { $serviceManager->addAbstractFactory($factory); } foreach ($this->getInvokables() as $name => $invokable) { $serviceManager->setInvokableClass($name, $invokable); } foreach ($this->getServices() as $name => $service) { $serviceManager->setService($name, $service); } foreach ($this->getAliases() as $alias => $nameOrAlias) { $serviceManager->setAlias($alias, $nameOrAlias); } foreach ($this->getInitializers() as $initializer) { $serviceManager->addInitializer($initializer); } foreach ($this->getShared() as $name => $isShared) { $serviceManager->setShared($name, $isShared); } foreach ($this->getDelegators() as $originalServiceName => $delegators) { foreach ($delegators as $delegator) { $serviceManager->addDelegator($originalServiceName, $delegator); } } } } serviceLocator = $serviceLocator; return $this; } /** * Get service locator * * @return ServiceLocatorInterface */ public function getServiceLocator() { return $this->serviceLocator; } } diInstanceManager = $diInstanceManager; $this->serviceLocator = $serviceLocator; // localize state $this->aliases = &$diInstanceManager->aliases; $this->sharedInstances = &$diInstanceManager->sharedInstances; $this->sharedInstancesWithParams = &$diInstanceManager->sharedInstancesWithParams; $this->configurations = &$diInstanceManager->configurations; $this->typePreferences = &$diInstanceManager->typePreferences; } /** * Determine if we have a shared instance by class or alias * * @param $classOrAlias * @return bool */ public function hasSharedInstance($classOrAlias) { return ($this->serviceLocator->has($classOrAlias) || $this->diInstanceManager->hasSharedInstance($classOrAlias)); } /** * Get shared instance * * @param $classOrAlias * @return mixed */ public function getSharedInstance($classOrAlias) { if ($this->serviceLocator->has($classOrAlias)) { return $this->serviceLocator->get($classOrAlias); } return $this->diInstanceManager->getSharedInstance($classOrAlias); } } di = $di; $this->name = $name; $this->parameters = $parameters; if (in_array($useServiceLocator, array(self::USE_SL_BEFORE_DI, self::USE_SL_AFTER_DI, self::USE_SL_NONE))) { $this->useServiceLocator = $useServiceLocator; } // since we are using this in a proxy-fashion, localize state $this->definitions = $this->di->definitions; $this->instanceManager = $this->di->instanceManager; } /** * Create service * * @param ServiceLocatorInterface $serviceLocator * @return object */ public function createService(ServiceLocatorInterface $serviceLocator) { $this->serviceLocator = $serviceLocator; return $this->get($this->name, $this->parameters); } /** * Override, as we want it to use the functionality defined in the proxy * * @param string $name * @param array $params * @return object * @throws Exception\ServiceNotFoundException */ public function get($name, array $params = array()) { // allow this di service to get dependencies from the service locator BEFORE trying di if ($this->useServiceLocator == self::USE_SL_BEFORE_DI && $this->serviceLocator->has($name)) { return $this->serviceLocator->get($name); } try { $service = parent::get($name, $params); return $service; } catch (DiClassNotFoundException $e) { // allow this di service to get dependencies from the service locator AFTER trying di if ($this->useServiceLocator == self::USE_SL_AFTER_DI && $this->serviceLocator->has($name)) { return $this->serviceLocator->get($name); } else { throw new Exception\ServiceNotFoundException( sprintf('Service %s was not found in this DI instance', $name), null, $e ); } } } } di = $di; if (in_array($useServiceLocator, array(self::USE_SL_BEFORE_DI, self::USE_SL_AFTER_DI, self::USE_SL_NONE))) { $this->useServiceLocator = $useServiceLocator; } // since we are using this in a proxy-fashion, localize state $this->definitions = $this->di->definitions; $this->instanceManager = $this->di->instanceManager; } /** * {@inheritDoc} */ public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName) { $this->serviceLocator = $serviceLocator; if ($requestedName) { return $this->get($requestedName, array()); } return $this->get($serviceName, array()); } /** * {@inheritDoc} */ public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName) { return $this->instanceManager->hasSharedInstance($requestedName) || $this->instanceManager->hasAlias($requestedName) || $this->instanceManager->hasConfig($requestedName) || $this->instanceManager->hasTypePreferences($requestedName) || $this->definitions->hasClass($requestedName); } } di = $di; $this->serviceLocator = $serviceLocator; $this->diInstanceManagerProxy = ($diImProxy) ?: new DiInstanceManagerProxy($di->instanceManager(), $serviceLocator); } /** * Initialize * * @param $instance * @param ServiceLocatorInterface $serviceLocator * @throws \Exception */ public function initialize($instance, ServiceLocatorInterface $serviceLocator) { $instanceManager = $this->di->instanceManager; $this->di->instanceManager = $this->diInstanceManagerProxy; try { $this->di->injectDependencies($instance); $this->di->instanceManager = $instanceManager; } catch (\Exception $e) { $this->di->instanceManager = $instanceManager; throw $e; } } } '', '_' => '', ' ' => '', '\\' => '', '/' => ''); /** * Constructor * * @param ConfigInterface $config */ public function __construct(ConfigInterface $config = null) { if ($config) { $config->configureServiceManager($this); } } /** * Set allow override * * @param $allowOverride * @return ServiceManager */ public function setAllowOverride($allowOverride) { $this->allowOverride = (bool) $allowOverride; return $this; } /** * Get allow override * * @return bool */ public function getAllowOverride() { return $this->allowOverride; } /** * Set flag indicating whether services are shared by default * * @param bool $shareByDefault * @return ServiceManager * @throws Exception\RuntimeException if allowOverride is false */ public function setShareByDefault($shareByDefault) { if ($this->allowOverride === false) { throw new Exception\RuntimeException(sprintf( '%s: cannot alter default shared service setting; container is marked immutable (allow_override is false)', get_class($this) . '::' . __FUNCTION__ )); } $this->shareByDefault = (bool) $shareByDefault; return $this; } /** * Are services shared by default? * * @return bool */ public function shareByDefault() { return $this->shareByDefault; } /** * Set throw exceptions in create * * @param bool $throwExceptionInCreate * @return ServiceManager */ public function setThrowExceptionInCreate($throwExceptionInCreate) { $this->throwExceptionInCreate = $throwExceptionInCreate; return $this; } /** * Get throw exceptions in create * * @return bool */ public function getThrowExceptionInCreate() { return $this->throwExceptionInCreate; } /** * Set flag indicating whether to pull from peering manager before attempting creation * * @param bool $retrieveFromPeeringManagerFirst * @return ServiceManager */ public function setRetrieveFromPeeringManagerFirst($retrieveFromPeeringManagerFirst = true) { $this->retrieveFromPeeringManagerFirst = (bool) $retrieveFromPeeringManagerFirst; return $this; } /** * Should we retrieve from the peering manager prior to attempting to create a service? * * @return bool */ public function retrieveFromPeeringManagerFirst() { return $this->retrieveFromPeeringManagerFirst; } /** * Set invokable class * * @param string $name * @param string $invokableClass * @param bool $shared * @return ServiceManager * @throws Exception\InvalidServiceNameException */ public function setInvokableClass($name, $invokableClass, $shared = null) { $cName = $this->canonicalizeName($name); if ($this->has(array($cName, $name), false)) { if ($this->allowOverride === false) { throw new Exception\InvalidServiceNameException(sprintf( 'A service by the name or alias "%s" already exists and cannot be overridden; please use an alternate name', $name )); } $this->unregisterService($cName); } if ($shared === null) { $shared = $this->shareByDefault; } $this->invokableClasses[$cName] = $invokableClass; $this->shared[$cName] = (bool) $shared; return $this; } /** * Set factory * * @param string $name * @param string|FactoryInterface|callable $factory * @param bool $shared * @return ServiceManager * @throws Exception\InvalidArgumentException * @throws Exception\InvalidServiceNameException */ public function setFactory($name, $factory, $shared = null) { $cName = $this->canonicalizeName($name); if (!($factory instanceof FactoryInterface || is_string($factory) || is_callable($factory))) { throw new Exception\InvalidArgumentException( 'Provided abstract factory must be the class name of an abstract factory or an instance of an AbstractFactoryInterface.' ); } if ($this->has(array($cName, $name), false)) { if ($this->allowOverride === false) { throw new Exception\InvalidServiceNameException(sprintf( 'A service by the name or alias "%s" already exists and cannot be overridden, please use an alternate name', $name )); } $this->unregisterService($cName); } if ($shared === null) { $shared = $this->shareByDefault; } $this->factories[$cName] = $factory; $this->shared[$cName] = (bool) $shared; return $this; } /** * Add abstract factory * * @param AbstractFactoryInterface|string $factory * @param bool $topOfStack * @return ServiceManager * @throws Exception\InvalidArgumentException if the abstract factory is invalid */ public function addAbstractFactory($factory, $topOfStack = true) { if (!$factory instanceof AbstractFactoryInterface && is_string($factory)) { $factory = new $factory(); } if (!$factory instanceof AbstractFactoryInterface) { throw new Exception\InvalidArgumentException( 'Provided abstract factory must be the class name of an abstract' . ' factory or an instance of an AbstractFactoryInterface.' ); } if ($topOfStack) { array_unshift($this->abstractFactories, $factory); } else { array_push($this->abstractFactories, $factory); } return $this; } /** * Sets the given service name as to be handled by a delegator factory * * @param string $serviceName name of the service being the delegate * @param string $delegatorFactoryName name of the service being the delegator factory * * @return ServiceManager */ public function addDelegator($serviceName, $delegatorFactoryName) { $cName = $this->canonicalizeName($serviceName); if (!isset($this->delegators[$cName])) { $this->delegators[$cName] = array(); } $this->delegators[$cName][] = $delegatorFactoryName; return $this; } /** * Add initializer * * @param callable|InitializerInterface $initializer * @param bool $topOfStack * @return ServiceManager * @throws Exception\InvalidArgumentException */ public function addInitializer($initializer, $topOfStack = true) { if (!($initializer instanceof InitializerInterface || is_callable($initializer))) { if (is_string($initializer)) { $initializer = new $initializer; } if (!($initializer instanceof InitializerInterface || is_callable($initializer))) { throw new Exception\InvalidArgumentException('$initializer should be callable.'); } } if ($topOfStack) { array_unshift($this->initializers, $initializer); } else { array_push($this->initializers, $initializer); } return $this; } /** * Register a service with the locator * * @param string $name * @param mixed $service * @return ServiceManager * @throws Exception\InvalidServiceNameException */ public function setService($name, $service) { $cName = $this->canonicalizeName($name); if ($this->has($cName, false)) { if ($this->allowOverride === false) { throw new Exception\InvalidServiceNameException(sprintf( '%s: A service by the name "%s" or alias already exists and cannot be overridden, please use an alternate name.', get_class($this) . '::' . __FUNCTION__, $name )); } $this->unregisterService($cName); } $this->instances[$cName] = $service; return $this; } /** * @param string $name * @param bool $isShared * @return ServiceManager * @throws Exception\ServiceNotFoundException */ public function setShared($name, $isShared) { $cName = $this->canonicalizeName($name); if ( !isset($this->invokableClasses[$cName]) && !isset($this->factories[$cName]) && !$this->canCreateFromAbstractFactory($cName, $name) ) { throw new Exception\ServiceNotFoundException(sprintf( '%s: A service by the name "%s" was not found and could not be marked as shared', get_class($this) . '::' . __FUNCTION__, $name )); } $this->shared[$cName] = (bool) $isShared; return $this; } /** * Resolve the alias for the given canonical name * * @param string $cName The canonical name to resolve * @return string The resolved canonical name */ protected function resolveAlias($cName) { $stack = array(); while ($this->hasAlias($cName)) { if (isset($stack[$cName])) { throw new Exception\CircularReferenceException(sprintf( 'Circular alias reference: %s -> %s', implode(' -> ', $stack), $cName )); } $stack[$cName] = $cName; $cName = $this->aliases[$cName]; } return $cName; } /** * Retrieve a registered instance * * @param string $name * @param bool $usePeeringServiceManagers * @throws Exception\ServiceNotFoundException * @return object|array */ public function get($name, $usePeeringServiceManagers = true) { // inlined code from ServiceManager::canonicalizeName for performance if (isset($this->canonicalNames[$name])) { $cName = $this->canonicalNames[$name]; } else { $cName = $this->canonicalizeName($name); } $isAlias = false; if ($this->hasAlias($cName)) { $isAlias = true; $cName = $this->resolveAlias($cName); } $instance = null; if ($usePeeringServiceManagers && $this->retrieveFromPeeringManagerFirst) { $instance = $this->retrieveFromPeeringManager($name); if (null !== $instance) { return $instance; } } if (isset($this->instances[$cName])) { return $this->instances[$cName]; } if (!$instance) { if ( isset($this->invokableClasses[$cName]) || isset($this->factories[$cName]) || isset($this->aliases[$cName]) || $this->canCreateFromAbstractFactory($cName, $name) ) { $instance = $this->create(array($cName, $name)); } elseif ($isAlias && $this->canCreateFromAbstractFactory($name, $cName)) { /* * case of an alias leading to an abstract factory : * 'my-alias' => 'my-abstract-defined-service' * $name = 'my-alias' * $cName = 'my-abstract-defined-service' */ $instance = $this->create(array($name, $cName)); } elseif ($usePeeringServiceManagers && !$this->retrieveFromPeeringManagerFirst) { $instance = $this->retrieveFromPeeringManager($name); } } // Still no instance? raise an exception if ($instance === null) { if ($isAlias) { throw new Exception\ServiceNotFoundException(sprintf( 'An alias "%s" was requested but no service could be found.', $name )); } throw new Exception\ServiceNotFoundException(sprintf( '%s was unable to fetch or create an instance for %s', get_class($this) . '::' . __FUNCTION__, $name )); } if ( ($this->shareByDefault && !isset($this->shared[$cName])) || (isset($this->shared[$cName]) && $this->shared[$cName] === true) ) { $this->instances[$cName] = $instance; } return $instance; } /** * Create an instance of the requested service * * @param string|array $name * * @return bool|object */ public function create($name) { if (is_array($name)) { list($cName, $rName) = $name; } else { $rName = $name; // inlined code from ServiceManager::canonicalizeName for performance if (isset($this->canonicalNames[$rName])) { $cName = $this->canonicalNames[$name]; } else { $cName = $this->canonicalizeName($name); } } if (isset($this->delegators[$cName])) { return $this->createDelegatorFromFactory($cName, $rName); } return $this->doCreate($rName, $cName); } /** * Creates a callback that uses a delegator to create a service * * @param DelegatorFactoryInterface|callable $delegatorFactory the delegator factory * @param string $rName requested service name * @param string $cName canonical service name * @param callable $creationCallback callback for instantiating the real service * * @return callable */ private function createDelegatorCallback($delegatorFactory, $rName, $cName, $creationCallback) { $serviceManager = $this; return function () use ($serviceManager, $delegatorFactory, $rName, $cName, $creationCallback) { return $delegatorFactory instanceof DelegatorFactoryInterface ? $delegatorFactory->createDelegatorWithName($serviceManager, $cName, $rName, $creationCallback) : $delegatorFactory($serviceManager, $cName, $rName, $creationCallback); }; } /** * Actually creates the service * * @param string $rName real service name * @param string $cName canonicalized service name * * @return bool|mixed|null|object * @throws Exception\ServiceNotFoundException * * @internal this method is internal because of PHP 5.3 compatibility - do not explicitly use it */ public function doCreate($rName, $cName) { $instance = null; if (isset($this->factories[$cName])) { $instance = $this->createFromFactory($cName, $rName); } if ($instance === null && isset($this->invokableClasses[$cName])) { $instance = $this->createFromInvokable($cName, $rName); } if ($instance === null && $this->canCreateFromAbstractFactory($cName, $rName)) { $instance = $this->createFromAbstractFactory($cName, $rName); } if ($instance === null && $this->throwExceptionInCreate) { throw new Exception\ServiceNotFoundException(sprintf( 'No valid instance was found for %s%s', $cName, ($rName ? '(alias: ' . $rName . ')' : '') )); } // Do not call initializers if we do not have an instance if ($instance === null) { return $instance; } foreach ($this->initializers as $initializer) { if ($initializer instanceof InitializerInterface) { $initializer->initialize($instance, $this); } else { call_user_func($initializer, $instance, $this); } } return $instance; } /** * Determine if we can create an instance. * * @param string|array $name * @param bool $checkAbstractFactories * @return bool * * @deprecated this method is being deprecated as of zendframework 2.2, and may be removed in future major versions */ public function canCreate($name, $checkAbstractFactories = true) { if (is_array($name)) { list($cName, $rName) = $name; } else { $rName = $name; $cName = $this->canonicalizeName($rName); } return ( isset($this->invokableClasses[$cName]) || isset($this->factories[$cName]) || isset($this->aliases[$cName]) || isset($this->instances[$cName]) || ($checkAbstractFactories && $this->canCreateFromAbstractFactory($cName, $rName)) ); } /** * @param string|array $name * @param bool $checkAbstractFactories * @param bool $usePeeringServiceManagers * @return bool */ public function has($name, $checkAbstractFactories = true, $usePeeringServiceManagers = true) { if (is_array($name)) { list($cName, $rName) = $name; } else { $rName = $name; // inlined code from ServiceManager::canonicalizeName for performance if (isset($this->canonicalNames[$rName])) { $cName = $this->canonicalNames[$name]; } else { $cName = $this->canonicalizeName($name); } } if ( isset($this->invokableClasses[$cName]) || isset($this->factories[$cName]) || isset($this->aliases[$cName]) || isset($this->instances[$cName]) || ($checkAbstractFactories && $this->canCreateFromAbstractFactory($cName, $name)) ) { return true; } if ($usePeeringServiceManagers) { foreach ($this->peeringServiceManagers as $peeringServiceManager) { if ($peeringServiceManager->has($rName)) { return true; } } } return false; } /** * Determine if we can create an instance from an abstract factory. * * @param string $cName * @param string $rName * @return bool */ public function canCreateFromAbstractFactory($cName, $rName) { // check abstract factories foreach ($this->abstractFactories as $abstractFactory) { $factoryClass = get_class($abstractFactory); if ( isset($this->pendingAbstractFactoryRequests[$factoryClass]) && $this->pendingAbstractFactoryRequests[$factoryClass] == $rName ) { return false; } $objectHash = spl_object_hash($abstractFactory); if ($this->lastAbstractFactoryUsed === $objectHash && $this->lastCanonicalNameUsed === $cName) { $this->lastAbstractFactoryUsed = $this->lastCanonicalNameUsed = null; return false; } $this->lastAbstractFactoryUsed = $objectHash; $this->lastCanonicalNameUsed = $cName; if ($abstractFactory->canCreateServiceWithName($this, $cName, $rName)) { $this->lastAbstractFactoryUsed = $this->lastCanonicalNameUsed = null; return true; } } return false; } /** * Ensure the alias definition will not result in a circular reference * * @param string $alias * @param string $nameOrAlias * @throws Exception\CircularReferenceException * @return self */ protected function checkForCircularAliasReference($alias, $nameOrAlias) { $aliases = $this->aliases; $aliases[$alias] = $nameOrAlias; $stack = array(); while (isset($aliases[$alias])) { if (isset($stack[$alias])) { throw new Exception\CircularReferenceException(sprintf( 'The alias definition "%s" : "%s" results in a circular reference: "%s" -> "%s"', $alias, $nameOrAlias, implode('" -> "', $stack), $alias )); } $stack[$alias] = $alias; $alias = $aliases[$alias]; } return $this; } /** * @param string $alias * @param string $nameOrAlias * @return ServiceManager * @throws Exception\ServiceNotFoundException * @throws Exception\InvalidServiceNameException */ public function setAlias($alias, $nameOrAlias) { if (!is_string($alias) || !is_string($nameOrAlias)) { throw new Exception\InvalidServiceNameException('Service or alias names must be strings.'); } $cAlias = $this->canonicalizeName($alias); $nameOrAlias = $this->canonicalizeName($nameOrAlias); if ($alias == '' || $nameOrAlias == '') { throw new Exception\InvalidServiceNameException('Invalid service name alias'); } if ($this->allowOverride === false && $this->has(array($cAlias, $alias), false)) { throw new Exception\InvalidServiceNameException(sprintf( 'An alias by the name "%s" or "%s" already exists', $cAlias, $alias )); } if ($this->hasAlias($alias)) { $this->checkForCircularAliasReference($cAlias, $nameOrAlias); } $this->aliases[$cAlias] = $nameOrAlias; return $this; } /** * Determine if we have an alias * * @param string $alias * @return bool */ public function hasAlias($alias) { return isset($this->aliases[$this->canonicalizeName($alias)]); } /** * Create scoped service manager * * @param string $peering * @return ServiceManager */ public function createScopedServiceManager($peering = self::SCOPE_PARENT) { $scopedServiceManager = new ServiceManager(); if ($peering == self::SCOPE_PARENT) { $scopedServiceManager->peeringServiceManagers[] = $this; } if ($peering == self::SCOPE_CHILD) { $this->peeringServiceManagers[] = $scopedServiceManager; } return $scopedServiceManager; } /** * Add a peering relationship * * @param ServiceManager $manager * @param string $peering * @return ServiceManager */ public function addPeeringServiceManager(ServiceManager $manager, $peering = self::SCOPE_PARENT) { if ($peering == self::SCOPE_PARENT) { $this->peeringServiceManagers[] = $manager; } if ($peering == self::SCOPE_CHILD) { $manager->peeringServiceManagers[] = $this; } return $this; } /** * Canonicalize name * * @param string $name * @return string */ protected function canonicalizeName($name) { if (isset($this->canonicalNames[$name])) { return $this->canonicalNames[$name]; } // this is just for performance instead of using str_replace return $this->canonicalNames[$name] = strtolower(strtr($name, $this->canonicalNamesReplacements)); } /** * Create service via callback * * @param callable $callable * @param string $cName * @param string $rName * @throws Exception\ServiceNotCreatedException * @throws Exception\ServiceNotFoundException * @throws Exception\CircularDependencyFoundException * @return object */ protected function createServiceViaCallback($callable, $cName, $rName) { static $circularDependencyResolver = array(); $depKey = spl_object_hash($this) . '-' . $cName; if (isset($circularDependencyResolver[$depKey])) { $circularDependencyResolver = array(); throw new Exception\CircularDependencyFoundException('Circular dependency for LazyServiceLoader was found for instance ' . $rName); } try { $circularDependencyResolver[$depKey] = true; $instance = call_user_func($callable, $this, $cName, $rName); unset($circularDependencyResolver[$depKey]); } catch (Exception\ServiceNotFoundException $e) { unset($circularDependencyResolver[$depKey]); throw $e; } catch (\Exception $e) { unset($circularDependencyResolver[$depKey]); throw new Exception\ServiceNotCreatedException( sprintf('An exception was raised while creating "%s"; no instance returned', $rName), $e->getCode(), $e ); } if ($instance === null) { throw new Exception\ServiceNotCreatedException('The factory was called but did not return an instance.'); } return $instance; } /** * Retrieve a keyed list of all registered services. Handy for debugging! * * @return array */ public function getRegisteredServices() { return array( 'invokableClasses' => array_keys($this->invokableClasses), 'factories' => array_keys($this->factories), 'aliases' => array_keys($this->aliases), 'instances' => array_keys($this->instances), ); } /** * Retrieve a keyed list of all canonical names. Handy for debugging! * * @return array */ public function getCanonicalNames() { return $this->canonicalNames; } /** * Allows to override the canonical names lookup map with predefined * values. * * @param array $canonicalNames * @return ServiceManager */ public function setCanonicalNames($canonicalNames) { $this->canonicalNames = $canonicalNames; return $this; } /** * Attempt to retrieve an instance via a peering manager * * @param string $name * @return mixed */ protected function retrieveFromPeeringManager($name) { foreach ($this->peeringServiceManagers as $peeringServiceManager) { if ($peeringServiceManager->has($name)) { return $peeringServiceManager->get($name); } } $name = $this->canonicalizeName($name); if ($this->hasAlias($name)) { do { $name = $this->aliases[$name]; } while ($this->hasAlias($name)); } foreach ($this->peeringServiceManagers as $peeringServiceManager) { if ($peeringServiceManager->has($name)) { return $peeringServiceManager->get($name); } } return null; } /** * Attempt to create an instance via an invokable class * * @param string $canonicalName * @param string $requestedName * @return null|\stdClass * @throws Exception\ServiceNotFoundException If resolved class does not exist */ protected function createFromInvokable($canonicalName, $requestedName) { $invokable = $this->invokableClasses[$canonicalName]; if (!class_exists($invokable)) { throw new Exception\ServiceNotFoundException(sprintf( '%s: failed retrieving "%s%s" via invokable class "%s"; class does not exist', get_class($this) . '::' . __FUNCTION__, $canonicalName, ($requestedName ? '(alias: ' . $requestedName . ')' : ''), $invokable )); } $instance = new $invokable; return $instance; } /** * Attempt to create an instance via a factory * * @param string $canonicalName * @param string $requestedName * @return mixed * @throws Exception\ServiceNotCreatedException If factory is not callable */ protected function createFromFactory($canonicalName, $requestedName) { $factory = $this->factories[$canonicalName]; if (is_string($factory) && class_exists($factory, true)) { $factory = new $factory; $this->factories[$canonicalName] = $factory; } if ($factory instanceof FactoryInterface) { $instance = $this->createServiceViaCallback(array($factory, 'createService'), $canonicalName, $requestedName); } elseif (is_callable($factory)) { $instance = $this->createServiceViaCallback($factory, $canonicalName, $requestedName); } else { throw new Exception\ServiceNotCreatedException(sprintf( 'While attempting to create %s%s an invalid factory was registered for this instance type.', $canonicalName, ($requestedName ? '(alias: ' . $requestedName . ')' : '') )); } return $instance; } /** * Attempt to create an instance via an abstract factory * * @param string $canonicalName * @param string $requestedName * @return object|null * @throws Exception\ServiceNotCreatedException If abstract factory is not callable */ protected function createFromAbstractFactory($canonicalName, $requestedName) { foreach ($this->abstractFactories as $index => $abstractFactory) { // support factories as strings if (is_string($abstractFactory) && class_exists($abstractFactory, true)) { $this->abstractFactories[$index] = $abstractFactory = new $abstractFactory; } elseif (!$abstractFactory instanceof AbstractFactoryInterface) { throw new Exception\ServiceNotCreatedException(sprintf( 'While attempting to create %s%s an abstract factory could not produce a valid instance.', $canonicalName, ($requestedName ? '(alias: ' . $requestedName . ')' : '') )); } try { if ($abstractFactory->canCreateServiceWithName($this, $canonicalName, $requestedName)) { $this->pendingAbstractFactoryRequests[get_class($abstractFactory)] = $requestedName; $instance = $this->createServiceViaCallback( array($abstractFactory, 'createServiceWithName'), $canonicalName, $requestedName ); unset($this->pendingAbstractFactoryRequests[get_class($abstractFactory)]); } else { $instance = null; } } catch (\Exception $e) { unset($this->pendingAbstractFactoryRequests[get_class($abstractFactory)]); throw new Exception\ServiceNotCreatedException( sprintf( 'An abstract factory could not create an instance of %s%s.', $canonicalName, ($requestedName ? '(alias: ' . $requestedName . ')' : '') ), $e->getCode(), $e ); } if ($instance !== null) { return $instance; } } } /** * @param $canonicalName * @param $requestedName * @return mixed * @throws Exception\ServiceNotCreatedException */ protected function createDelegatorFromFactory($canonicalName, $requestedName) { $serviceManager = $this; $delegatorsCount = count($this->delegators[$canonicalName]); $creationCallback = function () use ($serviceManager, $requestedName, $canonicalName) { return $serviceManager->doCreate($requestedName, $canonicalName); }; for ($i = 0; $i < $delegatorsCount; $i += 1) { $delegatorFactory = $this->delegators[$canonicalName][$i]; if (is_string($delegatorFactory)) { $delegatorFactory = !$this->has($delegatorFactory) && class_exists($delegatorFactory, true) ? new $delegatorFactory : $this->get($delegatorFactory); $this->delegators[$canonicalName][$i] = $delegatorFactory; } if (!$delegatorFactory instanceof DelegatorFactoryInterface && !is_callable($delegatorFactory)) { throw new Exception\ServiceNotCreatedException(sprintf( 'While attempting to create %s%s an invalid factory was registered for this instance type.', $canonicalName, ($requestedName ? '(alias: ' . $requestedName . ')' : '') )); } $creationCallback = $this->createDelegatorCallback( $delegatorFactory, $requestedName, $canonicalName, $creationCallback ); } return $creationCallback($serviceManager, $canonicalName, $requestedName, $creationCallback); } /** * Checks if the object has this class as one of its parents * * @see https://bugs.php.net/bug.php?id=53727 * @see https://github.com/zendframework/zf2/pull/1807 * * @param string $className * @param string $type * @return bool * * @deprecated this method is being deprecated as of zendframework 2.2, and may be removed in future major versions */ protected static function isSubclassOf($className, $type) { if (is_subclass_of($className, $type)) { return true; } if (version_compare(PHP_VERSION, '5.3.7', '>=')) { return false; } if (!interface_exists($type)) { return false; } $r = new ReflectionClass($className); return $r->implementsInterface($type); } /** * Unregister a service * * Called when $allowOverride is true and we detect that a service being * added to the instance already exists. This will remove the duplicate * entry, and also any shared flags previously registered. * * @param string $canonical * @return void */ protected function unregisterService($canonical) { $types = array('invokableClasses', 'factories', 'aliases'); foreach ($types as $type) { if (isset($this->{$type}[$canonical])) { unset($this->{$type}[$canonical]); break; } } if (isset($this->instances[$canonical])) { unset($this->instances[$canonical]); } if (isset($this->shared[$canonical])) { unset($this->shared[$canonical]); } } } addInitializer(function ($instance) use ($self) { if ($instance instanceof ServiceLocatorAwareInterface) { $instance->setServiceLocator($self); } }); } /** * Validate the plugin * * Checks that the filter loaded is either a valid callback or an instance * of FilterInterface. * * @param mixed $plugin * @return void * @throws Exception\RuntimeException if invalid */ abstract public function validatePlugin($plugin); /** * Retrieve a service from the manager by name * * Allows passing an array of options to use when creating the instance. * createFromInvokable() will use these and pass them to the instance * constructor if not null and a non-empty array. * * @param string $name * @param array $options * @param bool $usePeeringServiceManagers * @return object */ public function get($name, $options = array(), $usePeeringServiceManagers = true) { // Allow specifying a class name directly; registers as an invokable class if (!$this->has($name) && $this->autoAddInvokableClass && class_exists($name)) { $this->setInvokableClass($name, $name); } $this->creationOptions = $options; $instance = parent::get($name, $usePeeringServiceManagers); $this->creationOptions = null; $this->validatePlugin($instance); return $instance; } /** * Register a service with the locator. * * Validates that the service object via validatePlugin() prior to * attempting to register it. * * @param string $name * @param mixed $service * @param bool $shared * @return AbstractPluginManager * @throws Exception\InvalidServiceNameException */ public function setService($name, $service, $shared = true) { if ($service) { $this->validatePlugin($service); } parent::setService($name, $service, $shared); return $this; } /** * Set the main service locator so factories can have access to it to pull deps * * @param ServiceLocatorInterface $serviceLocator * @return AbstractPluginManager */ public function setServiceLocator(ServiceLocatorInterface $serviceLocator) { $this->serviceLocator = $serviceLocator; return $this; } /** * Get the main plugin manager. Useful for fetching dependencies from within factories. * * @return ServiceLocatorInterface */ public function getServiceLocator() { return $this->serviceLocator; } /** * Attempt to create an instance via an invokable class * * Overrides parent implementation by passing $creationOptions to the * constructor, if non-null. * * @param string $canonicalName * @param string $requestedName * @return null|\stdClass * @throws Exception\ServiceNotCreatedException If resolved class does not exist */ protected function createFromInvokable($canonicalName, $requestedName) { $invokable = $this->invokableClasses[$canonicalName]; if (null === $this->creationOptions || (is_array($this->creationOptions) && empty($this->creationOptions)) ) { $instance = new $invokable(); } else { $instance = new $invokable($this->creationOptions); } return $instance; } /** * Attempt to create an instance via a factory class * * Overrides parent implementation by passing $creationOptions to the * constructor, if non-null. * * @param string $canonicalName * @param string $requestedName * @return mixed * @throws Exception\ServiceNotCreatedException If factory is not callable */ protected function createFromFactory($canonicalName, $requestedName) { $factory = $this->factories[$canonicalName]; $hasCreationOptions = !(null === $this->creationOptions || (is_array($this->creationOptions) && empty($this->creationOptions))); if (is_string($factory) && class_exists($factory, true)) { if (!$hasCreationOptions) { $factory = new $factory(); } else { $factory = new $factory($this->creationOptions); } $this->factories[$canonicalName] = $factory; } if ($factory instanceof FactoryInterface) { $instance = $this->createServiceViaCallback(array($factory, 'createService'), $canonicalName, $requestedName); } elseif (is_callable($factory)) { $instance = $this->createServiceViaCallback($factory, $canonicalName, $requestedName); } else { throw new Exception\ServiceNotCreatedException(sprintf( 'While attempting to create %s%s an invalid factory was registered for this instance type.', $canonicalName, ($requestedName ? '(alias: ' . $requestedName . ')' : '') )); } return $instance; } /** * Create service via callback * * @param callable $callable * @param string $cName * @param string $rName * @throws Exception\ServiceNotCreatedException * @throws Exception\ServiceNotFoundException * @throws Exception\CircularDependencyFoundException * @return object */ protected function createServiceViaCallback($callable, $cName, $rName) { if (is_object($callable)) { $factory = $callable; } elseif (is_array($callable)) { // reset both rewinds and returns the value of the first array element $factory = reset($callable); } if (isset($factory) && ($factory instanceof MutableCreationOptionsInterface) && is_array($this->creationOptions) && !empty($this->creationOptions) ) { $factory->setCreationOptions($this->creationOptions); } return parent::createServiceViaCallback($callable, $cName, $rName); } } metadata[$spec] = $value; return $this; } if (!is_array($spec) && !$spec instanceof Traversable) { throw new Exception\InvalidArgumentException(sprintf( 'Expected a string, array, or Traversable argument in first position; received "%s"', (is_object($spec) ? get_class($spec) : gettype($spec)) )); } foreach ($spec as $key => $value) { $this->metadata[$key] = $value; } return $this; } /** * Retrieve all metadata or a single metadatum as specified by key * * @param null|string|int $key * @param null|mixed $default * @throws Exception\InvalidArgumentException * @return mixed */ public function getMetadata($key = null, $default = null) { if (null === $key) { return $this->metadata; } if (!is_scalar($key)) { throw new Exception\InvalidArgumentException('Non-scalar argument provided for key'); } if (array_key_exists($key, $this->metadata)) { return $this->metadata[$key]; } return $default; } /** * Set message content * * @param mixed $value * @return Message */ public function setContent($value) { $this->content = $value; return $this; } /** * Get message content * * @return mixed */ public function getContent() { return $this->content; } /** * @return string */ public function toString() { $request = ''; foreach ($this->getMetadata() as $key => $value) { $request .= sprintf( "%s: %s\r\n", (string) $key, (string) $value ); } $request .= "\r\n" . $this->getContent(); return $request; } } toArray()); } /** * Unserialize * * @param string $data * @return void */ public function unserialize($data) { foreach (unserialize($data) as $item) { $this->unshift($item); } } } strategies = new ArrayObject(); $this->filterComposite = new FilterComposite(); } /** * Gets the strategy with the given name. * * @param string $name The name of the strategy to get. * @return StrategyInterface */ public function getStrategy($name) { if (isset($this->strategies[$name])) { return $this->strategies[$name]; } if (!isset($this->strategies['*'])) { throw new Exception\InvalidArgumentException(sprintf( '%s: no strategy by name of "%s", and no wildcard strategy present', __METHOD__, $name )); } return $this->strategies['*']; } /** * Checks if the strategy with the given name exists. * * @param string $name The name of the strategy to check for. * @return bool */ public function hasStrategy($name) { return array_key_exists($name, $this->strategies) || array_key_exists('*', $this->strategies); } /** * Adds the given strategy under the given name. * * @param string $name The name of the strategy to register. * @param StrategyInterface $strategy The strategy to register. * @return HydratorInterface */ public function addStrategy($name, StrategyInterface $strategy) { $this->strategies[$name] = $strategy; return $this; } /** * Removes the strategy with the given name. * * @param string $name The name of the strategy to remove. * @return HydratorInterface */ public function removeStrategy($name) { unset($this->strategies[$name]); return $this; } /** * Converts a value for extraction. If no strategy exists the plain value is returned. * * @param string $name The name of the strategy to use. * @param mixed $value The value that should be converted. * @param array $object The object is optionally provided as context. * @return mixed */ public function extractValue($name, $value, $object = null) { if ($this->hasStrategy($name)) { $strategy = $this->getStrategy($name); $value = $strategy->extract($value, $object); } return $value; } /** * Converts a value for hydration. If no strategy exists the plain value is returned. * * @param string $name The name of the strategy to use. * @param mixed $value The value that should be converted. * @param array $data The whole data is optionally provided as context. * @return mixed */ public function hydrateValue($name, $value, $data = null) { if ($this->hasStrategy($name)) { $strategy = $this->getStrategy($name); $value = $strategy->hydrate($value, $data); } return $value; } /** * Get the filter instance * * @return Filter\FilterComposite */ public function getFilter() { return $this->filterComposite; } /** * Add a new filter to take care of what needs to be hydrated. * To exclude e.g. the method getServiceLocator: * * * $composite->addFilter("servicelocator", * function ($property) { * list($class, $method) = explode('::', $property); * if ($method === 'getServiceLocator') { * return false; * } * return true; * }, FilterComposite::CONDITION_AND * ); * * * @param string $name Index in the composite * @param callable|Filter\FilterInterface $filter * @param int $condition * @return Filter\FilterComposite */ public function addFilter($name, $filter, $condition = FilterComposite::CONDITION_OR) { return $this->filterComposite->addFilter($name, $filter, $condition); } /** * Check whether a specific filter exists at key $name or not * * @param string $name Index in the composite * @return bool */ public function hasFilter($name) { return $this->filterComposite->hasFilter($name); } /** * Remove a filter from the composition. * To not extract "has" methods, you simply need to unregister it * * * $filterComposite->removeFilter('has'); * * * @param $name * @return Filter\FilterComposite */ public function removeFilter($name) { return $this->filterComposite->removeFilter($name); } } getEventManager()->attachAggregate(new HydratorListener($hydrator), $priority); } /** * {@inheritDoc} */ public function extract($object) { $event = new ExtractEvent($this, $object); $this->getEventManager()->trigger($event); return $event->getExtractedData(); } /** * {@inheritDoc} */ public function hydrate(array $data, $object) { $event = new HydrateEvent($this, $object, $data); $this->getEventManager()->trigger($event); return $event->getHydratedObject(); } /** * {@inheritDoc} */ public function setEventManager(EventManagerInterface $eventManager) { $eventManager->setIdentifiers(array(__CLASS__, get_class($this))); $this->eventManager = $eventManager; } /** * {@inheritDoc} */ public function getEventManager() { if (null === $this->eventManager) { $this->setEventManager(new EventManager()); } return $this->eventManager; } } target = $target; $this->extractionObject = $extractionObject; } /** * Retrieves the object from which data is extracted * * @return object */ public function getExtractionObject() { return $this->extractionObject; } /** * @param object $extractionObject * * @return void */ public function setExtractionObject($extractionObject) { $this->extractionObject = $extractionObject; } /** * Retrieves the data that has been extracted * * @return array */ public function getExtractedData() { return $this->extractedData; } /** * @param array $extractedData * * @return void */ public function setExtractedData(array $extractedData) { $this->extractedData = $extractedData; } /** * Merge provided data with the extracted data * * @param array $additionalData * * @return void */ public function mergeExtractedData(array $additionalData) { $this->extractedData = array_merge($this->extractedData, $additionalData); } } target = $target; $this->hydratedObject = $hydratedObject; $this->hydrationData = $hydrationData; } /** * Retrieves the object that is being hydrated * * @return object */ public function getHydratedObject() { return $this->hydratedObject; } /** * @param object $hydratedObject */ public function setHydratedObject($hydratedObject) { $this->hydratedObject = $hydratedObject; } /** * Retrieves the data that is being used for hydration * * @return array */ public function getHydrationData() { return $this->hydrationData; } /** * @param array $hydrationData */ public function setHydrationData(array $hydrationData) { $this->hydrationData = $hydrationData; } } hydrator = $hydrator; } /** * {@inheritDoc} */ public function attach(EventManagerInterface $events, $priority = 1) { $this->listeners[] = $events->attach(HydrateEvent::EVENT_HYDRATE, array($this, 'onHydrate'), $priority); $this->listeners[] = $events->attach(ExtractEvent::EVENT_EXTRACT, array($this, 'onExtract'), $priority); } /** * Callback to be used when {@see \Zend\Stdlib\Hydrator\Aggregate\HydrateEvent::EVENT_HYDRATE} is triggered * * @param \Zend\Stdlib\Hydrator\Aggregate\HydrateEvent $event * * @return object * * @internal */ public function onHydrate(HydrateEvent $event) { $object = $this->hydrator->hydrate($event->getHydrationData(), $event->getHydratedObject()); $event->setHydratedObject($object); return $object; } /** * Callback to be used when {@see \Zend\Stdlib\Hydrator\Aggregate\ExtractEvent::EVENT_EXTRACT} is triggered * * @param \Zend\Stdlib\Hydrator\Aggregate\ExtractEvent $event * * @return array * * @internal */ public function onExtract(ExtractEvent $event) { $data = $this->hydrator->extract($event->getExtractionObject()); $event->mergeExtractedData($data); return $data; } } getArrayCopy(); foreach ($data as $name => $value) { if (!$this->getFilter()->filter($name)) { unset($data[$name]); continue; } $data[$name] = $this->extractValue($name, $value); } return $data; } /** * Hydrate an object * * Hydrates an object by passing $data to either its exchangeArray() or * populate() method. * * @param array $data * @param object $object * @return object * @throws Exception\BadMethodCallException for an $object not implementing exchangeArray() or populate() */ public function hydrate(array $data, $object) { $self = $this; array_walk($data, function (&$value, $name) use ($self) { $value = $self->hydrateValue($name, $value); }); if (is_callable(array($object, 'exchangeArray'))) { $object->exchangeArray($data); } elseif (is_callable(array($object, 'populate'))) { $object->populate($data); } else { throw new Exception\BadMethodCallException(sprintf( '%s expects the provided object to implement exchangeArray() or populate()', __METHOD__ )); } return $object; } } numberOfParameters = 0; } /** * @param string $property the name of the property * @return bool * @throws InvalidArgumentException */ public function filter($property) { try { $reflectionMethod = new ReflectionMethod($property); } catch (ReflectionException $exception) { throw new InvalidArgumentException( "Method $property doesn't exist" ); } if ($reflectionMethod->getNumberOfParameters() !== $this->numberOfParameters) { return false; } return true; } } orFilter = new ArrayObject($orFilter); $this->andFilter = new ArrayObject($andFilter); } /** * Add a filter to the composite. Has to be indexed with $name in * order to identify a specific filter. * * This example will exclude all methods from the hydration, that starts with 'getService' * * $composite->addFilter('exclude', * function ($method) { * if (preg_match('/^getService/', $method) { * return false; * } * return true; * }, FilterComposite::CONDITION_AND * ); * * * @param string $name * @param callable|FilterInterface $filter * @param int $condition Can be either FilterComposite::CONDITION_OR or FilterComposite::CONDITION_AND * @throws InvalidArgumentException * @return FilterComposite */ public function addFilter($name, $filter, $condition = self::CONDITION_OR) { if (!is_callable($filter) && !($filter instanceof FilterInterface)) { throw new InvalidArgumentException( 'The value of ' . $name . ' should be either a callable or ' . 'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface' ); } if ($condition === self::CONDITION_OR) { $this->orFilter[$name] = $filter; } elseif ($condition === self::CONDITION_AND) { $this->andFilter[$name] = $filter; } return $this; } /** * Remove a filter from the composition * * @param $name string Identifier for the filter * @return FilterComposite */ public function removeFilter($name) { if (isset($this->orFilter[$name])) { unset($this->orFilter[$name]); } if (isset($this->andFilter[$name])) { unset($this->andFilter[$name]); } return $this; } /** * Check if $name has a filter registered * * @param $name string Identifier for the filter * @return bool */ public function hasFilter($name) { return isset($this->orFilter[$name]) || isset($this->andFilter[$name]); } /** * Filter the composite based on the AND and OR condition * Will return true if one from the "or conditions" and all from * the "and condition" returns true. Otherwise false * * @param $property string Parameter will be e.g. Parent\Namespace\Class::method * @return bool */ public function filter($property) { $andCount = count($this->andFilter); $orCount = count($this->orFilter); // return true if no filters are registered if ($orCount === 0 && $andCount === 0) { return true; } elseif ($orCount === 0 && $andCount !== 0) { $returnValue = true; } else { $returnValue = false; } // Check if 1 from the or filters return true foreach ($this->orFilter as $filter) { if (is_callable($filter)) { if ($filter($property) === true) { $returnValue = true; break; } continue; } else { if ($filter->filter($property) === true) { $returnValue = true; break; } } } // Check if all of the and condition return true foreach ($this->andFilter as $filter) { if (is_callable($filter)) { if ($filter($property) === false) { return false; } continue; } else { if ($filter->filter($property) === false) { return false; } } } return $returnValue; } } method = $method; $this->exclude = $exclude; } public function filter($property) { $pos = strpos($property, '::'); if ($pos !== false) { $pos += 2; } else { $pos = 0; } if (substr($property, $pos) === $this->method) { return $this->exclude ? false : true; } return $this->exclude ? true : false; } } getParameters(), function (ReflectionParameter $parameter) { return ! $parameter->isOptional(); } ); return static::$propertiesCache[$property] = empty($mandatoryParameters); } } getName(); if (!$this->filterComposite->filter($propertyName)) { continue; } $value = $property->getValue($object); $result[$propertyName] = $this->extractValue($propertyName, $value, $object); } return $result; } /** * Hydrate $object with the provided $data. * * @param array $data * @param object $object * @return object */ public function hydrate(array $data, $object) { $reflProperties = self::getReflProperties($object); foreach ($data as $key => $value) { if (isset($reflProperties[$key])) { $reflProperties[$key]->setValue($object, $this->hydrateValue($key, $value, $data)); } } return $object; } /** * Get a reflection properties from in-memory cache and lazy-load if * class has not been loaded. * * @param string|object $input * @throws Exception\InvalidArgumentException * @return array */ protected static function getReflProperties($input) { if (is_object($input)) { $input = get_class($input); } elseif (!is_string($input)) { throw new Exception\InvalidArgumentException('Input must be a string or an object.'); } if (isset(static::$reflProperties[$input])) { return static::$reflProperties[$input]; } static::$reflProperties[$input] = array(); $reflClass = new ReflectionClass($input); $reflProperties = $reflClass->getProperties(); foreach ($reflProperties as $property) { $property->setAccessible(true); static::$reflProperties[$input][$property->getName()] = $property; } return static::$reflProperties[$input]; } } setUnderscoreSeparatedKeys($underscoreSeparatedKeys); $this->callableMethodFilter = new OptionalParametersFilter(); $this->filterComposite->addFilter("is", new IsFilter()); $this->filterComposite->addFilter("has", new HasFilter()); $this->filterComposite->addFilter("get", new GetFilter()); $this->filterComposite->addFilter("parameter", new OptionalParametersFilter(), FilterComposite::CONDITION_AND); } /** * @param array|Traversable $options * @return ClassMethods * @throws Exception\InvalidArgumentException */ public function setOptions($options) { if ($options instanceof Traversable) { $options = ArrayUtils::iteratorToArray($options); } elseif (!is_array($options)) { throw new Exception\InvalidArgumentException( 'The options parameter must be an array or a Traversable' ); } if (isset($options['underscoreSeparatedKeys'])) { $this->setUnderscoreSeparatedKeys($options['underscoreSeparatedKeys']); } return $this; } /** * @param bool $underscoreSeparatedKeys * @return ClassMethods */ public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys) { $this->underscoreSeparatedKeys = $underscoreSeparatedKeys; return $this; } /** * @return bool */ public function getUnderscoreSeparatedKeys() { return $this->underscoreSeparatedKeys; } /** * Extract values from an object with class methods * * Extracts the getter/setter of the given $object. * * @param object $object * @return array * @throws Exception\BadMethodCallException for a non-object $object */ public function extract($object) { if (!is_object($object)) { throw new Exception\BadMethodCallException(sprintf( '%s expects the provided $object to be a PHP object)', __METHOD__ )); } $filter = null; if ($object instanceof FilterProviderInterface) { $filter = new FilterComposite( array($object->getFilter()), array(new MethodMatchFilter("getFilter")) ); } else { $filter = $this->filterComposite; } $transform = function ($letters) { $letter = array_shift($letters); return '_' . strtolower($letter); }; $attributes = array(); $methods = get_class_methods($object); foreach ($methods as $method) { if ( !$filter->filter( get_class($object) . '::' . $method ) ) { continue; } if (!$this->callableMethodFilter->filter(get_class($object) . '::' . $method)) { continue; } $attribute = $method; if (preg_match('/^get/', $method)) { $attribute = substr($method, 3); if (!property_exists($object, $attribute)) { $attribute = lcfirst($attribute); } } if ($this->underscoreSeparatedKeys) { $attribute = preg_replace_callback('/([A-Z])/', $transform, $attribute); } $attributes[$attribute] = $this->extractValue($attribute, $object->$method(), $object); } return $attributes; } /** * Hydrate an object by populating getter/setter methods * * Hydrates an object by getter/setter methods of the object. * * @param array $data * @param object $object * @return object * @throws Exception\BadMethodCallException for a non-object $object */ public function hydrate(array $data, $object) { if (!is_object($object)) { throw new Exception\BadMethodCallException(sprintf( '%s expects the provided $object to be a PHP object)', __METHOD__ )); } $transform = function ($letters) { $letter = substr(array_shift($letters), 1, 1); return ucfirst($letter); }; foreach ($data as $property => $value) { $method = 'set' . ucfirst($property); if ($this->underscoreSeparatedKeys) { $method = preg_replace_callback('/(_[a-z])/i', $transform, $method); } if (is_callable(array($object, $method))) { $value = $this->hydrateValue($property, $value, $data); $object->$method($value); } } return $object; } } 'Zend\Stdlib\Hydrator\ArraySerializable', 'classmethods' => 'Zend\Stdlib\Hydrator\ClassMethods', 'objectproperty' => 'Zend\Stdlib\Hydrator\ObjectProperty', 'reflection' => 'Zend\Stdlib\Hydrator\Reflection' ); /** * {@inheritDoc} */ public function validatePlugin($plugin) { if ($plugin instanceof HydratorInterface) { // we're okay return; } throw new Exception\RuntimeException(sprintf( 'Plugin of type %s is invalid; must implement Zend\Stdlib\Hydrator\HydratorInterface', (is_object($plugin) ? get_class($plugin) : gettype($plugin)) )); } } getFilter(); foreach ($data as $name => $value) { // Filter keys, removing any we don't want if (!$filter->filter($name)) { unset($data[$name]); continue; } // Extract data $data[$name] = $this->extractValue($name, $value); } return $data; } /** * Hydrate an object by populating public properties * * Hydrates an object by setting public properties of the object. * * @param array $data * @param object $object * @return object * @throws Exception\BadMethodCallException for a non-object $object */ public function hydrate(array $data, $object) { if (!is_object($object)) { throw new Exception\BadMethodCallException(sprintf( '%s expects the provided $object to be a PHP object)', __METHOD__ )); } foreach ($data as $property => $value) { $object->$property = $this->hydrateValue($property, $value, $data); } return $object; } } addStrategy('category', new ClosureStrategy( * function (Category $value) { * return (int) $value->id; * }, * function ($value) { * return new Category((int) $value); * } * )); * * @param callable $extractFunc - anonymous function, that extract values * from object * @param callable $hydrateFunc - anonymous function, that hydrate values * into object */ public function __construct($extractFunc = null, $hydrateFunc = null) { if (isset($extractFunc)) { if (!is_callable($extractFunc)) { throw new \Exception('$extractFunc must be callable'); } $this->extractFunc = $extractFunc; } else { $this->extractFunc = function ($value) { return $value; }; } if (isset($hydrateFunc)) { if (!is_callable($hydrateFunc)) { throw new \Exception('$hydrateFunc must be callable'); } $this->hydrateFunc = $hydrateFunc; } else { $this->hydrateFunc = function ($value) { return $value; }; } } /** * Converts the given value so that it can be extracted by the hydrator. * * @param mixed $value The original value. * @return mixed Returns the value that should be extracted. */ public function extract($value) { $func = $this->extractFunc; return $func($value); } /** * Converts the given value so that it can be hydrated by the hydrator. * * @param mixed $value The original value. * @return mixed Returns the value that should be hydrated. */ public function hydrate($value) { $func = $this->hydrateFunc; return $func($value); } } setSerializer($serializer); if ($serializerOptions) { $this->setSerializerOptions($serializerOptions); } } /** * Serialize the given value so that it can be extracted by the hydrator. * * @param mixed $value The original value. * @return mixed Returns the value that should be extracted. */ public function extract($value) { $serializer = $this->getSerializer(); return $serializer->serialize($value); } /** * Unserialize the given value so that it can be hydrated by the hydrator. * * @param mixed $value The original value. * @return mixed Returns the value that should be hydrated. */ public function hydrate($value) { $serializer = $this->getSerializer(); return $serializer->unserialize($value); } /** * Set serializer * * @param string|SerializerAdapter $serializer * @return SerializableStrategy */ public function setSerializer($serializer) { if (!is_string($serializer) && !$serializer instanceof SerializerAdapter) { throw new InvalidArgumentException(sprintf( '%s expects either a string serializer name or Zend\Serializer\Adapter\AdapterInterface instance; ' . 'received "%s"', __METHOD__, (is_object($serializer) ? get_class($serializer) : gettype($serializer)) )); } $this->serializer = $serializer; return $this; } /** * Get serializer * * @return SerializerAdapter */ public function getSerializer() { if (is_string($this->serializer)) { $options = $this->getSerializerOptions(); $this->setSerializer(SerializerFactory::factory($this->serializer, $options)); } elseif (null === $this->serializer) { $this->setSerializer(SerializerFactory::getDefaultAdapter()); } return $this->serializer; } /** * Set configuration options for instantiating a serializer adapter * * @param mixed $serializerOptions * @return SerializableStrategy */ public function setSerializerOptions($serializerOptions) { $this->serializerOptions = $serializerOptions; return $this; } /** * Get configuration options for instantiating a serializer adapter * * @return mixed */ public function getSerializerOptions() { return $this->serializerOptions; } } 5.3.3, we need to provide a stub for 5.3.3. This stub * simply extends the PHP ArrayObject implementation, and provides default * behavior in the constructor. */ abstract class PhpLegacyCompatibility extends PhpArrayObject { /** * Constructor * * @param array $input * @param int $flags * @param string $iteratorClass */ public function __construct($input = array(), $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator') { parent::__construct($input, $flags, $iteratorClass); } } setFlags($flags); $this->storage = $input; $this->setIteratorClass($iteratorClass); $this->protectedProperties = array_keys(get_object_vars($this)); } /** * Returns whether the requested key exists * * @param mixed $key * @return bool */ public function __isset($key) { if ($this->flag == self::ARRAY_AS_PROPS) { return $this->offsetExists($key); } if (in_array($key, $this->protectedProperties)) { throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); } return isset($this->$key); } /** * Sets the value at the specified key to value * * @param mixed $key * @param mixed $value * @return void */ public function __set($key, $value) { if ($this->flag == self::ARRAY_AS_PROPS) { return $this->offsetSet($key, $value); } if (in_array($key, $this->protectedProperties)) { throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); } $this->$key = $value; } /** * Unsets the value at the specified key * * @param mixed $key * @return void */ public function __unset($key) { if ($this->flag == self::ARRAY_AS_PROPS) { return $this->offsetUnset($key); } if (in_array($key, $this->protectedProperties)) { throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); } unset($this->$key); } /** * Returns the value at the specified key by reference * * @param mixed $key * @return mixed */ public function &__get($key) { $ret = null; if ($this->flag == self::ARRAY_AS_PROPS) { $ret =& $this->offsetGet($key); return $ret; } if (in_array($key, $this->protectedProperties)) { throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); } return $this->$key; } /** * Appends the value * * @param mixed $value * @return void */ public function append($value) { $this->storage[] = $value; } /** * Sort the entries by value * * @return void */ public function asort() { asort($this->storage); } /** * Get the number of public properties in the ArrayObject * * @return int */ public function count() { return count($this->storage); } /** * Exchange the array for another one. * * @param array|ArrayObject $data * @return array */ public function exchangeArray($data) { if (!is_array($data) && !is_object($data)) { throw new Exception\InvalidArgumentException('Passed variable is not an array or object, using empty array instead'); } if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject)) { $data = $data->getArrayCopy(); } if (!is_array($data)) { $data = (array) $data; } $storage = $this->storage; $this->storage = $data; return $storage; } /** * Creates a copy of the ArrayObject. * * @return array */ public function getArrayCopy() { return $this->storage; } /** * Gets the behavior flags. * * @return int */ public function getFlags() { return $this->flag; } /** * Create a new iterator from an ArrayObject instance * * @return \Iterator */ public function getIterator() { $class = $this->iteratorClass; return new $class($this->storage); } /** * Gets the iterator classname for the ArrayObject. * * @return string */ public function getIteratorClass() { return $this->iteratorClass; } /** * Sort the entries by key * * @return void */ public function ksort() { ksort($this->storage); } /** * Sort an array using a case insensitive "natural order" algorithm * * @return void */ public function natcasesort() { natcasesort($this->storage); } /** * Sort entries using a "natural order" algorithm * * @return void */ public function natsort() { natsort($this->storage); } /** * Returns whether the requested key exists * * @param mixed $key * @return bool */ public function offsetExists($key) { return isset($this->storage[$key]); } /** * Returns the value at the specified key * * @param mixed $key * @return mixed */ public function &offsetGet($key) { $ret = null; if (!$this->offsetExists($key)) { return $ret; } $ret =& $this->storage[$key]; return $ret; } /** * Sets the value at the specified key to value * * @param mixed $key * @param mixed $value * @return void */ public function offsetSet($key, $value) { $this->storage[$key] = $value; } /** * Unsets the value at the specified key * * @param mixed $key * @return void */ public function offsetUnset($key) { if ($this->offsetExists($key)) { unset($this->storage[$key]); } } /** * Serialize an ArrayObject * * @return string */ public function serialize() { return serialize(get_object_vars($this)); } /** * Sets the behavior flags * * @param int $flags * @return void */ public function setFlags($flags) { $this->flag = $flags; } /** * Sets the iterator classname for the ArrayObject * * @param string $class * @return void */ public function setIteratorClass($class) { if (class_exists($class)) { $this->iteratorClass = $class; return ; } if (strpos($class, '\\') === 0) { $class = '\\' . $class; if (class_exists($class)) { $this->iteratorClass = $class; return ; } } throw new Exception\InvalidArgumentException('The iterator class does not exist'); } /** * Sort the entries with a user-defined comparison function and maintain key association * * @param callable $function * @return void */ public function uasort($function) { if (is_callable($function)) { uasort($this->storage, $function); } } /** * Sort the entries by keys using a user-defined comparison function * * @param callable $function * @return void */ public function uksort($function) { if (is_callable($function)) { uksort($this->storage, $function); } } /** * Unserialize an ArrayObject * * @param string $data * @return void */ public function unserialize($data) { $ar = unserialize($data); $this->setFlags($ar['flag']); $this->exchangeArray($ar['storage']); $this->setIteratorClass($ar['iteratorClass']); foreach ($ar as $k => $v) { switch ($k) { case 'flag': $this->setFlags($v); break; case 'storage': $this->exchangeArray($v); break; case 'iteratorClass': $this->setIteratorClass($v); break; case 'protectedProperties': continue; default: $this->__set($k, $v); } } } } serial--); } parent::insert($datum, $priority); } /** * Serialize to an array * * Array will be priority => data pairs * * @return array */ public function toArray() { $array = array(); foreach (clone $this as $item) { $array[] = $item; } return $array; } /** * Serialize * * @return string */ public function serialize() { $clone = clone $this; $clone->setExtractFlags(self::EXTR_BOTH); $data = array(); foreach ($clone as $item) { $data[] = $item; } return serialize($data); } /** * Deserialize * * @param string $data * @return void */ public function unserialize($data) { foreach (unserialize($data) as $item) { $this->insert($item['data'], $item['priority']); } } } items[] = array( 'data' => $data, 'priority' => $priority, ); $this->getQueue()->insert($data, $priority); return $this; } /** * Remove an item from the queue * * This is different than {@link extract()}; its purpose is to dequeue an * item. * * This operation is potentially expensive, as it requires * re-initialization and re-population of the inner queue. * * Note: this removes the first item matching the provided item found. If * the same item has been added multiple times, it will not remove other * instances. * * @param mixed $datum * @return bool False if the item was not found, true otherwise. */ public function remove($datum) { $found = false; foreach ($this->items as $key => $item) { if ($item['data'] === $datum) { $found = true; break; } } if ($found) { unset($this->items[$key]); $this->queue = null; if (!$this->isEmpty()) { $queue = $this->getQueue(); foreach ($this->items as $item) { $queue->insert($item['data'], $item['priority']); } } return true; } return false; } /** * Is the queue empty? * * @return bool */ public function isEmpty() { return (0 === $this->count()); } /** * How many items are in the queue? * * @return int */ public function count() { return count($this->items); } /** * Peek at the top node in the queue, based on priority. * * @return mixed */ public function top() { return $this->getIterator()->top(); } /** * Extract a node from the inner queue and sift up * * @return mixed */ public function extract() { return $this->getQueue()->extract(); } /** * Retrieve the inner iterator * * SplPriorityQueue acts as a heap, which typically implies that as items * are iterated, they are also removed. This does not work for situations * where the queue may be iterated multiple times. As such, this class * aggregates the values, and also injects an SplPriorityQueue. This method * retrieves the inner queue object, and clones it for purposes of * iteration. * * @return SplPriorityQueue */ public function getIterator() { $queue = $this->getQueue(); return clone $queue; } /** * Serialize the data structure * * @return string */ public function serialize() { return serialize($this->items); } /** * Unserialize a string into a PriorityQueue object * * Serialization format is compatible with {@link Zend\Stdlib\SplPriorityQueue} * * @param string $data * @return void */ public function unserialize($data) { foreach (unserialize($data) as $item) { $this->insert($item['data'], $item['priority']); } } /** * Serialize to an array * * By default, returns only the item data, and in the order registered (not * sorted). You may provide one of the EXTR_* flags as an argument, allowing * the ability to return priorities or both data and priority. * * @param int $flag * @return array */ public function toArray($flag = self::EXTR_DATA) { switch ($flag) { case self::EXTR_BOTH: return $this->items; break; case self::EXTR_PRIORITY: return array_map(function ($item) { return $item['priority']; }, $this->items); case self::EXTR_DATA: default: return array_map(function ($item) { return $item['data']; }, $this->items); } } /** * Specify the internal queue class * * Please see {@link getIterator()} for details on the necessity of an * internal queue class. The class provided should extend SplPriorityQueue. * * @param string $class * @return PriorityQueue */ public function setInternalQueueClass($class) { $this->queueClass = (string) $class; return $this; } /** * Does the queue contain the given datum? * * @param mixed $datum * @return bool */ public function contains($datum) { foreach ($this->items as $item) { if ($item['data'] === $datum) { return true; } } return false; } /** * Does the queue have an item with the given priority? * * @param int $priority * @return bool */ public function hasPriority($priority) { foreach ($this->items as $item) { if ($item['priority'] === $priority) { return true; } } return false; } /** * Get the inner priority queue instance * * @throws Exception\DomainException * @return SplPriorityQueue */ protected function getQueue() { if (null === $this->queue) { $this->queue = new $this->queueClass(); if (!$this->queue instanceof \SplPriorityQueue) { throw new Exception\DomainException(sprintf( 'PriorityQueue expects an internal queue of type SplPriorityQueue; received "%s"', get_class($this->queue) )); } } return $this->queue; } /** * Add support for deep cloning * * @return void */ public function __clone() { if (null !== $this->queue) { $this->queue = clone $this->queue; } } } 0; } /** * Test whether an array contains one or more integer keys * * @param mixed $value * @param bool $allowEmpty Should an empty array() return true * @return bool */ public static function hasIntegerKeys($value, $allowEmpty = false) { if (!is_array($value)) { return false; } if (!$value) { return $allowEmpty; } return count(array_filter(array_keys($value), 'is_int')) > 0; } /** * Test whether an array contains one or more numeric keys. * * A numeric key can be one of the following: * - an integer 1, * - a string with a number '20' * - a string with negative number: '-1000' * - a float: 2.2120, -78.150999 * - a string with float: '4000.99999', '-10.10' * * @param mixed $value * @param bool $allowEmpty Should an empty array() return true * @return bool */ public static function hasNumericKeys($value, $allowEmpty = false) { if (!is_array($value)) { return false; } if (!$value) { return $allowEmpty; } return count(array_filter(array_keys($value), 'is_numeric')) > 0; } /** * Test whether an array is a list * * A list is a collection of values assigned to continuous integer keys * starting at 0 and ending at count() - 1. * * For example: * * $list = array('a', 'b', 'c', 'd'); * $list = array( * 0 => 'foo', * 1 => 'bar', * 2 => array('foo' => 'baz'), * ); * * * @param mixed $value * @param bool $allowEmpty Is an empty list a valid list? * @return bool */ public static function isList($value, $allowEmpty = false) { if (!is_array($value)) { return false; } if (!$value) { return $allowEmpty; } return (array_values($value) === $value); } /** * Test whether an array is a hash table. * * An array is a hash table if: * * 1. Contains one or more non-integer keys, or * 2. Integer keys are non-continuous or misaligned (not starting with 0) * * For example: * * $hash = array( * 'foo' => 15, * 'bar' => false, * ); * $hash = array( * 1995 => 'Birth of PHP', * 2009 => 'PHP 5.3.0', * 2012 => 'PHP 5.4.0', * ); * $hash = array( * 'formElement, * 'options' => array( 'debug' => true ), * ); * * * @param mixed $value * @param bool $allowEmpty Is an empty array() a valid hash table? * @return bool */ public static function isHashTable($value, $allowEmpty = false) { if (!is_array($value)) { return false; } if (!$value) { return $allowEmpty; } return (array_values($value) !== $value); } /** * Checks if a value exists in an array. * * Due to "foo" == 0 === TRUE with in_array when strict = false, an option * has been added to prevent this. When $strict = 0/false, the most secure * non-strict check is implemented. if $strict = -1, the default in_array * non-strict behaviour is used. * * @param mixed $needle * @param array $haystack * @param int|bool $strict * @return bool */ public static function inArray($needle, array $haystack, $strict = false) { if (!$strict) { if (is_int($needle) || is_float($needle)) { $needle = (string) $needle; } if (is_string($needle)) { foreach ($haystack as &$h) { if (is_int($h) || is_float($h)) { $h = (string) $h; } } } } return in_array($needle, $haystack, $strict); } /** * Convert an iterator to an array. * * Converts an iterator to an array. The $recursive flag, on by default, * hints whether or not you want to do so recursively. * * @param array|Traversable $iterator The array or Traversable object to convert * @param bool $recursive Recursively check all nested structures * @throws Exception\InvalidArgumentException if $iterator is not an array or a Traversable object * @return array */ public static function iteratorToArray($iterator, $recursive = true) { if (!is_array($iterator) && !$iterator instanceof Traversable) { throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable object'); } if (!$recursive) { if (is_array($iterator)) { return $iterator; } return iterator_to_array($iterator); } if (method_exists($iterator, 'toArray')) { return $iterator->toArray(); } $array = array(); foreach ($iterator as $key => $value) { if (is_scalar($value)) { $array[$key] = $value; continue; } if ($value instanceof Traversable) { $array[$key] = static::iteratorToArray($value, $recursive); continue; } if (is_array($value)) { $array[$key] = static::iteratorToArray($value, $recursive); continue; } $array[$key] = $value; } return $array; } /** * Merge two arrays together. * * If an integer key exists in both arrays and preserveNumericKeys is false, the value * from the second array will be appended to the first array. If both values are arrays, they * are merged together, else the value of the second array overwrites the one of the first array. * * @param array $a * @param array $b * @param bool $preserveNumericKeys * @return array */ public static function merge(array $a, array $b, $preserveNumericKeys = false) { foreach ($b as $key => $value) { if (array_key_exists($key, $a)) { if (is_int($key) && !$preserveNumericKeys) { $a[] = $value; } elseif (is_array($value) && is_array($a[$key])) { $a[$key] = static::merge($a[$key], $value, $preserveNumericKeys); } else { $a[$key] = $value; } } else { $a[$key] = $value; } } return $a; } } setFromArray($options); } } /** * Set one or more configuration properties * * @param array|Traversable|AbstractOptions $options * @throws Exception\InvalidArgumentException * @return AbstractOptions Provides fluent interface */ public function setFromArray($options) { if ($options instanceof self) { $options = $options->toArray(); } if (!is_array($options) && !$options instanceof Traversable) { throw new Exception\InvalidArgumentException(sprintf( 'Parameter provided to %s must be an %s, %s or %s', __METHOD__, 'array', 'Traversable', 'Zend\Stdlib\AbstractOptions' )); } foreach ($options as $key => $value) { $this->__set($key, $value); } return $this; } /** * Cast to array * * @return array */ public function toArray() { $array = array(); $transform = function ($letters) { $letter = array_shift($letters); return '_' . strtolower($letter); }; foreach ($this as $key => $value) { if ($key === '__strictMode__') continue; $normalizedKey = preg_replace_callback('/([A-Z])/', $transform, $key); $array[$normalizedKey] = $value; } return $array; } /** * Set a configuration property * * @see ParameterObject::__set() * @param string $key * @param mixed $value * @throws Exception\BadMethodCallException * @return void */ public function __set($key, $value) { $setter = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); if ($this->__strictMode__ && !method_exists($this, $setter)) { throw new Exception\BadMethodCallException( 'The option "' . $key . '" does not ' . 'have a matching ' . $setter . ' setter method ' . 'which must be defined' ); } elseif (!$this->__strictMode__ && !method_exists($this, $setter)) { return; } $this->{$setter}($value); } /** * Get a configuration property * * @see ParameterObject::__get() * @param string $key * @throws Exception\BadMethodCallException * @return mixed */ public function __get($key) { $getter = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); if (!method_exists($this, $getter)) { throw new Exception\BadMethodCallException( 'The option "' . $key . '" does not ' . 'have a matching ' . $getter . ' getter method ' . 'which must be defined' ); } return $this->{$getter}(); } /** * Test if a configuration property is null * @see ParameterObject::__isset() * @param string $key * @return bool */ public function __isset($key) { return null !== $this->__get($key); } /** * Set a configuration property to NULL * * @see ParameterObject::__unset() * @param string $key * @throws Exception\InvalidArgumentException * @return void */ public function __unset($key) { try { $this->__set($key, null); } catch (Exception\BadMethodCallException $e) { throw new Exception\InvalidArgumentException( 'The class property $' . $key . ' cannot be unset as' . ' NULL is an invalid value for it', 0, $e ); } } } GLOB_MARK, self::GLOB_NOSORT => GLOB_NOSORT, self::GLOB_NOCHECK => GLOB_NOCHECK, self::GLOB_NOESCAPE => GLOB_NOESCAPE, self::GLOB_BRACE => GLOB_BRACE, self::GLOB_ONLYDIR => GLOB_ONLYDIR, self::GLOB_ERR => GLOB_ERR, ); $globFlags = 0; foreach ($flagMap as $internalFlag => $globFlag) { if ($flags & $internalFlag) { $globFlags |= $globFlag; } } } else { $globFlags = 0; } ErrorHandler::start(); $res = glob($pattern, $globFlags); $err = ErrorHandler::stop(); if ($res === false) { throw new Exception\RuntimeException("glob('{$pattern}', {$globFlags}) failed", 0, $err); } return $res; } /** * Expand braces manually, then use the system glob. * * @param string $pattern * @param int $flags * @return array * @throws Exception\RuntimeException */ protected static function fallbackGlob($pattern, $flags) { if (!$flags & self::GLOB_BRACE) { return static::systemGlob($pattern, $flags); } $flags &= ~self::GLOB_BRACE; $length = strlen($pattern); $paths = array(); if ($flags & self::GLOB_NOESCAPE) { $begin = strpos($pattern, '{'); } else { $begin = 0; while (true) { if ($begin === $length) { $begin = false; break; } elseif ($pattern[$begin] === '\\' && ($begin + 1) < $length) { $begin++; } elseif ($pattern[$begin] === '{') { break; } $begin++; } } if ($begin === false) { return static::systemGlob($pattern, $flags); } $next = static::nextBraceSub($pattern, $begin + 1, $flags); if ($next === null) { return static::systemGlob($pattern, $flags); } $rest = $next; while ($pattern[$rest] !== '}') { $rest = static::nextBraceSub($pattern, $rest + 1, $flags); if ($rest === null) { return static::systemGlob($pattern, $flags); } } $p = $begin + 1; while (true) { $subPattern = substr($pattern, 0, $begin) . substr($pattern, $p, $next - $p) . substr($pattern, $rest + 1); $result = static::fallbackGlob($subPattern, $flags | self::GLOB_BRACE); if ($result) { $paths = array_merge($paths, $result); } if ($pattern[$next] === '}') { break; } $p = $next + 1; $next = static::nextBraceSub($pattern, $p, $flags); } return array_unique($paths); } /** * Find the end of the sub-pattern in a brace expression. * * @param string $pattern * @param int $begin * @param int $flags * @return int|null */ protected static function nextBraceSub($pattern, $begin, $flags) { $length = strlen($pattern); $depth = 0; $current = $begin; while ($current < $length) { if (!$flags & self::GLOB_NOESCAPE && $pattern[$current] === '\\') { if (++$current === $length) { break; } $current++; } else { if (($pattern[$current] === '}' && $depth-- === 0) || ($pattern[$current] === ',' && $depth === 0)) { break; } elseif ($pattern[$current++] === '{') { $depth++; } } } return ($current < $length ? $current : null); } } toArray()); } /** * Unserialize * * @param string $data * @return void */ public function unserialize($data) { foreach (unserialize($data) as $item) { $this->push($item); } } } metadata = $metadata; $this->registerCallback($callback); } /** * Registers the callback provided in the constructor * * @param callable $callback * @throws Exception\InvalidCallbackException * @return void */ protected function registerCallback($callback) { if (!is_callable($callback)) { throw new Exception\InvalidCallbackException('Invalid callback provided; not callable'); } $this->callback = $callback; } /** * Retrieve registered callback * * @return callable */ public function getCallback() { return $this->callback; } /** * Invoke handler * * @param array $args Arguments to pass to callback * @return mixed */ public function call(array $args = array()) { $callback = $this->getCallback(); // Minor performance tweak, if the callback gets called more than once if (!isset(static::$isPhp54)) { static::$isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>='); } $argCount = count($args); if (static::$isPhp54 && is_string($callback)) { $result = $this->validateStringCallbackFor54($callback); if ($result !== true && $argCount <= 3) { $callback = $result; // Minor performance tweak, if the callback gets called more // than once $this->callback = $result; } } // Minor performance tweak; use call_user_func() until > 3 arguments // reached switch ($argCount) { case 0: if (static::$isPhp54) { return $callback(); } return call_user_func($callback); case 1: if (static::$isPhp54) { return $callback(array_shift($args)); } return call_user_func($callback, array_shift($args)); case 2: $arg1 = array_shift($args); $arg2 = array_shift($args); if (static::$isPhp54) { return $callback($arg1, $arg2); } return call_user_func($callback, $arg1, $arg2); case 3: $arg1 = array_shift($args); $arg2 = array_shift($args); $arg3 = array_shift($args); if (static::$isPhp54) { return $callback($arg1, $arg2, $arg3); } return call_user_func($callback, $arg1, $arg2, $arg3); default: return call_user_func_array($callback, $args); } } /** * Invoke as functor * * @return mixed */ public function __invoke() { return $this->call(func_get_args()); } /** * Get all callback metadata * * @return array */ public function getMetadata() { return $this->metadata; } /** * Retrieve a single metadatum * * @param string $name * @return mixed */ public function getMetadatum($name) { if (array_key_exists($name, $this->metadata)) { return $this->metadata[$name]; } return null; } /** * Validate a static method call * * Validates that a static method call in PHP 5.4 will actually work * * @param string $callback * @return true|array * @throws Exception\InvalidCallbackException if invalid */ protected function validateStringCallbackFor54($callback) { if (!strstr($callback, '::')) { return true; } list($class, $method) = explode('::', $callback, 2); if (!class_exists($class)) { throw new Exception\InvalidCallbackException(sprintf( 'Static method call "%s" refers to a class that does not exist', $callback )); } $r = new ReflectionClass($class); if (!$r->hasMethod($method)) { throw new Exception\InvalidCallbackException(sprintf( 'Static method call "%s" refers to a method that does not exist', $callback )); } $m = $r->getMethod($method); if (!$m->isStatic()) { throw new Exception\InvalidCallbackException(sprintf( 'Static method call "%s" refers to a method that is not static', $callback )); } // returning a non boolean value may not be nice for a validate method, // but that allows the usage of a static string callback without using // the call_user_func function. return array($class, $method); } } getArrayCopy(); return new ArrayIterator(array_reverse($array)); } } exchangeArray($values); } /** * Populate from query string * * @param string $string * @return void */ public function fromString($string) { $array = array(); parse_str($string, $array); $this->fromArray($array); } /** * Serialize to native PHP array * * @return array */ public function toArray() { return $this->getArrayCopy(); } /** * Serialize to query string * * @return string */ public function toString() { return http_build_query($this); } /** * Retrieve by key * * Returns null if the key does not exist. * * @param string $name * @return mixed */ public function offsetGet($name) { if (isset($this[$name])) { return parent::offsetGet($name); } return null; } /** * @param string $name * @param mixed $default optional default value * @return mixed */ public function get($name, $default = null) { if (isset($this[$name])) { return parent::offsetGet($name); } return $default; } /** * @param string $name * @param mixed $value * @return Parameters */ public function set($name, $value) { $this[$name] = $value; return $this; } } setEncoding($encoding, $convertEncoding); return $wrapper; } } throw new Exception\RuntimeException( 'No wrapper found supporting "' . $encoding . '"' . (($convertEncoding !== null) ? ' and "' . $convertEncoding . '"' : '') ); } /** * Get a list of all known single-byte character encodings * * @return string[] */ public static function getSingleByteEncodings() { return static::$singleByteEncodings; } /** * Check if a given encoding is a known single-byte character encoding * * @param string $encoding * @return bool */ public static function isSingleByteEncoding($encoding) { return in_array(strtoupper($encoding), static::$singleByteEncodings); } /** * Check if a given string is valid UTF-8 encoded * * @param string $str * @return bool */ public static function isValidUtf8($str) { return is_string($str) && ($str === '' || preg_match('/^./su', $str) == 1); } /** * Is PCRE compiled with Unicode support? * * @return bool */ public static function hasPcreUnicodeSupport() { if (static::$hasPcreUnicodeSupport === null) { ErrorHandler::start(); static::$hasPcreUnicodeSupport = defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1; ErrorHandler::stop(); } return static::$hasPcreUnicodeSupport; } } convertEncoding = $encodingUpper; } if ($convertEncoding !== null) { if ($encodingUpper !== strtoupper($convertEncoding)) { throw new Exception\InvalidArgumentException( 'Wrapper doesn\'t support to convert between character encodings' ); } $this->convertEncoding = $encodingUpper; } else { $this->convertEncoding = null; } $this->encoding = $encodingUpper; return $this; } /** * Returns the length of the given string * * @param string $str * @return int|false */ public function strlen($str) { return strlen($str); } /** * Returns the portion of string specified by the start and length parameters * * @param string $str * @param int $offset * @param int|null $length * @return string|false */ public function substr($str, $offset = 0, $length = null) { return substr($str, $offset, $length); } /** * Find the position of the first occurrence of a substring in a string * * @param string $haystack * @param string $needle * @param int $offset * @return int|false */ public function strpos($haystack, $needle, $offset = 0) { return strpos($haystack, $needle, $offset); } } convertEncoding = $convertEncodingUpper; } else { $this->convertEncoding = null; } $this->encoding = $encodingUpper; return $this; } /** * Get the defined character encoding to work with * * @return string * @throws Exception\LogicException If no encoding was defined */ public function getEncoding() { return $this->encoding; } /** * Get the defined character encoding to convert to * * @return string|null */ public function getConvertEncoding() { return $this->convertEncoding; } /** * Convert a string from defined character encoding to the defined convert encoding * * @param string $str * @param bool $reverse * @return string|false */ public function convert($str, $reverse = false) { $encoding = $this->getEncoding(); $convertEncoding = $this->getConvertEncoding(); if ($convertEncoding === null) { throw new Exception\LogicException( 'No convert encoding defined' ); } if ($encoding === $convertEncoding) { return $str; } $from = $reverse ? $convertEncoding : $encoding; $to = $reverse ? $encoding : $convertEncoding; throw new Exception\RuntimeException(sprintf( 'Converting from "%s" to "%s" isn\'t supported by this string wrapper', $from, $to )); } /** * Wraps a string to a given number of characters * * @param string $string * @param int $width * @param string $break * @param bool $cut * @return string|false */ public function wordWrap($string, $width = 75, $break = "\n", $cut = false) { $string = (string) $string; if ($string === '') { return ''; } $break = (string) $break; if ($break === '') { throw new Exception\InvalidArgumentException('Break string cannot be empty'); } $width = (int) $width; if ($width === 0 && $cut) { throw new Exception\InvalidArgumentException('Cannot force cut when width is zero'); } if (StringUtils::isSingleByteEncoding($this->getEncoding())) { return wordwrap($string, $width, $break, $cut); } $stringWidth = $this->strlen($string); $breakWidth = $this->strlen($break); $result = ''; $lastStart = $lastSpace = 0; for ($current = 0; $current < $stringWidth; $current++) { $char = $this->substr($string, $current, 1); $possibleBreak = $char; if ($breakWidth !== 1) { $possibleBreak = $this->substr($string, $current, $breakWidth); } if ($possibleBreak === $break) { $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth); $current += $breakWidth - 1; $lastStart = $lastSpace = $current + 1; continue; } if ($char === ' ') { if ($current - $lastStart >= $width) { $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break; $lastStart = $current + 1; } $lastSpace = $current; continue; } if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) { $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break; $lastStart = $lastSpace = $current; continue; } if ($current - $lastStart >= $width && $lastStart < $lastSpace) { $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart) . $break; $lastStart = $lastSpace = $lastSpace + 1; continue; } } if ($lastStart !== $current) { $result .= $this->substr($string, $lastStart, $current - $lastStart); } return $result; } /** * Pad a string to a certain length with another string * * @param string $input * @param int $padLength * @param string $padString * @param int $padType * @return string */ public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT) { if (StringUtils::isSingleByteEncoding($this->getEncoding())) { return str_pad($input, $padLength, $padString, $padType); } $lengthOfPadding = $padLength - $this->strlen($input); if ($lengthOfPadding <= 0) { return $input; } $padStringLength = $this->strlen($padString); if ($padStringLength === 0) { return $input; } $repeatCount = floor($lengthOfPadding / $padStringLength); if ($padType === STR_PAD_BOTH) { $lastStringLeft = ''; $lastStringRight = ''; $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2; $lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength; $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2); $lastStringRightLength += $lastStringLength % 2; $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength); $lastStringRight = $this->substr($padString, 0, $lastStringRightLength); return str_repeat($padString, $repeatCountLeft) . $lastStringLeft . $input . str_repeat($padString, $repeatCountRight) . $lastStringRight; } $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength); if ($padType === STR_PAD_LEFT) { return str_repeat($padString, $repeatCount) . $lastString . $input; } return $input . str_repeat($padString, $repeatCount) . $lastString; } } getEncoding()); } /** * Returns the portion of string specified by the start and length parameters * * @param string $str * @param int $offset * @param int|null $length * @return string|false */ public function substr($str, $offset = 0, $length = null) { return mb_substr($str, $offset, $length, $this->getEncoding()); } /** * Find the position of the first occurrence of a substring in a string * * @param string $haystack * @param string $needle * @param int $offset * @return int|false */ public function strpos($haystack, $needle, $offset = 0) { return mb_strpos($haystack, $needle, $offset, $this->getEncoding()); } /** * Convert a string from defined encoding to the defined convert encoding * * @param string $str * @param bool $reverse * @return string|false */ public function convert($str, $reverse = false) { $encoding = $this->getEncoding(); $convertEncoding = $this->getConvertEncoding(); if ($convertEncoding === null) { throw new Exception\LogicException( 'No convert encoding defined' ); } if ($encoding === $convertEncoding) { return $str; } $fromEncoding = $reverse ? $convertEncoding : $encoding; $toEncoding = $reverse ? $encoding : $convertEncoding; return mb_convert_encoding($str, $toEncoding, $fromEncoding); } } getEncoding()); } /** * Returns the portion of string specified by the start and length parameters * * @param string $str * @param int $offset * @param int|null $length * @return string|false */ public function substr($str, $offset = 0, $length = null) { return iconv_substr($str, $offset, $length, $this->getEncoding()); } /** * Find the position of the first occurrence of a substring in a string * * @param string $haystack * @param string $needle * @param int $offset * @return int|false */ public function strpos($haystack, $needle, $offset = 0) { return iconv_strpos($haystack, $needle, $offset, $this->getEncoding()); } /** * Convert a string from defined encoding to the defined convert encoding * * @param string $str * @param bool $reverse * @return string|false */ public function convert($str, $reverse = false) { $encoding = $this->getEncoding(); $convertEncoding = $this->getConvertEncoding(); if ($convertEncoding === null) { throw new Exception\LogicException( 'No convert encoding defined' ); } if ($encoding === $convertEncoding) { return $str; } $fromEncoding = $reverse ? $convertEncoding : $encoding; $toEncoding = $reverse ? $encoding : $convertEncoding; // automatically add "//IGNORE" to not stop converting on invalid characters // invalid characters triggers a notice anyway return iconv($fromEncoding, $toEncoding . '//IGNORE', $str); } } setAdapter($options); } /** * Returns the name of the set adapter * * @return string */ public function getAdapter() { return $this->adapter->toString(); } /** * Sets new encryption options * * @param string|array $options (Optional) Encryption options * @return self * @throws Exception\DomainException * @throws Exception\InvalidArgumentException */ public function setAdapter($options = null) { if (is_string($options)) { $adapter = $options; } elseif (isset($options['adapter'])) { $adapter = $options['adapter']; unset($options['adapter']); } else { $adapter = 'BlockCipher'; } if (!is_array($options)) { $options = array(); } if (class_exists('Zend\Filter\Encrypt\\' . ucfirst($adapter))) { $adapter = 'Zend\Filter\Encrypt\\' . ucfirst($adapter); } elseif (!class_exists($adapter)) { throw new Exception\DomainException( sprintf('%s expects a valid registry class name; received "%s", which did not resolve', __METHOD__, $adapter )); } $this->adapter = new $adapter($options); if (!$this->adapter instanceof Encrypt\EncryptionAlgorithmInterface) { throw new Exception\InvalidArgumentException( "Encoding adapter '" . $adapter . "' does not implement Zend\\Filter\\Encrypt\\EncryptionAlgorithmInterface"); } return $this; } /** * Calls adapter methods * * @param string $method Method to call * @param string|array $options Options for this method * @return mixed * @throws Exception\BadMethodCallException */ public function __call($method, $options) { $part = substr($method, 0, 3); if ((($part != 'get') && ($part != 'set')) || !method_exists($this->adapter, $method)) { throw new Exception\BadMethodCallException("Unknown method '{$method}'"); } return call_user_func_array(array($this->adapter, $method), $options); } /** * Defined by Zend\Filter\Filter * * Encrypts the content $value with the defined settings * * @param string $value Content to encrypt * @return string The encrypted content */ public function filter($value) { return $this->adapter->encrypt($value); } } null, 'callback_params' => array() ); /** * @param callable|array|Traversable $callbackOrOptions * @param array $callbackParams */ public function __construct($callbackOrOptions, $callbackParams = array()) { if (is_callable($callbackOrOptions)) { $this->setCallback($callbackOrOptions); $this->setCallbackParams($callbackParams); } else { $this->setOptions($callbackOrOptions); } } /** * Sets a new callback for this filter * * @param callable $callback * @throws Exception\InvalidArgumentException * @return self */ public function setCallback($callback) { if (!is_callable($callback)) { throw new Exception\InvalidArgumentException( 'Invalid parameter for callback: must be callable' ); } $this->options['callback'] = $callback; return $this; } /** * Returns the set callback * * @return callable */ public function getCallback() { return $this->options['callback']; } /** * Sets parameters for the callback * * @param mixed $params * @return self */ public function setCallbackParams($params) { $this->options['callback_params'] = (array) $params; return $this; } /** * Get parameters for the callback * * @return array */ public function getCallbackParams() { return $this->options['callback_params']; } /** * Calls the filter per callback * * @param mixed $value Options for the set callable * @return mixed Result from the filter which was called */ public function filter($value) { $params = (array) $this->options['callback_params']; array_unshift($params, $value); return call_user_func_array($this->options['callback'], $params); } } encryption key string * 'key_iteration' => the number of iterations for the PBKDF2 key generation * 'algorithm => cipher algorithm to use * 'hash' => algorithm to use for the authentication * 'vector' => initialization vector * ) */ protected $encryption = array( 'key_iteration' => 5000, 'algorithm' => 'aes', 'hash' => 'sha256', ); /** * BlockCipher * * @var BlockCipher */ protected $blockCipher; /** * Internal compression * * @var array */ protected $compression; /** * Class constructor * * @param string|array|Traversable $options Encryption Options * @throws Exception\RuntimeException * @throws Exception\InvalidArgumentException */ public function __construct($options) { try { $this->blockCipher = CryptBlockCipher::factory('mcrypt', $this->encryption); } catch (SymmetricException\RuntimeException $e) { throw new Exception\RuntimeException('The BlockCipher cannot be used without the Mcrypt extension'); } if ($options instanceof Traversable) { $options = ArrayUtils::iteratorToArray($options); } elseif (is_string($options)) { $options = array('key' => $options); } elseif (!is_array($options)) { throw new Exception\InvalidArgumentException('Invalid options argument provided to filter'); } if (array_key_exists('compression', $options)) { $this->setCompression($options['compression']); unset($options['compress']); } $this->setEncryption($options); } /** * Returns the set encryption options * * @return array */ public function getEncryption() { return $this->encryption; } /** * Sets new encryption options * * @param string|array $options Encryption options * @return self * @throws Exception\InvalidArgumentException */ public function setEncryption($options) { if (is_string($options)) { $this->blockCipher->setKey($options); $this->encryption['key'] = $options; return $this; } if (!is_array($options)) { throw new Exception\InvalidArgumentException('Invalid options argument provided to filter'); } $options = $options + $this->encryption; if (isset($options['key'])) { $this->blockCipher->setKey($options['key']); } if (isset($options['algorithm'])) { try { $this->blockCipher->setCipherAlgorithm($options['algorithm']); } catch (CryptException\InvalidArgumentException $e) { throw new Exception\InvalidArgumentException("The algorithm '{$options['algorithm']}' is not supported"); } } if (isset($options['hash'])) { try { $this->blockCipher->setHashAlgorithm($options['hash']); } catch (CryptException\InvalidArgumentException $e) { throw new Exception\InvalidArgumentException("The algorithm '{$options['hash']}' is not supported"); } } if (isset($options['vector'])) { $this->setVector($options['vector']); } if (isset($options['key_iteration'])) { $this->blockCipher->setKeyIteration($options['key_iteration']); } $this->encryption = $options; return $this; } /** * Returns the initialization vector * * @return string */ public function getVector() { return $this->encryption['vector']; } /** * Set the inizialization vector * * @param string $vector * @return self * @throws Exception\InvalidArgumentException */ public function setVector($vector) { try { $this->blockCipher->setSalt($vector); } catch (CryptException\InvalidArgumentException $e) { throw new Exception\InvalidArgumentException($e->getMessage()); } $this->encryption['vector'] = $vector; return $this; } /** * Set the encryption key * * @param string $key * @return self * @throws Exception\InvalidArgumentException */ public function setKey($key) { try { $this->blockCipher->setKey($key); } catch (CryptException\InvalidArgumentException $e) { throw new Exception\InvalidArgumentException($e->getMessage()); } $this->encryption['key'] = $key; return $this; } /** * Get the encryption key * * @return string */ public function getKey() { return $this->encryption['key']; } /** * Returns the compression * * @return array */ public function getCompression() { return $this->compression; } /** * Sets a internal compression for values to encrypt * * @param string|array $compression * @return self */ public function setCompression($compression) { if (is_string($this->compression)) { $compression = array('adapter' => $compression); } $this->compression = $compression; return $this; } /** * Defined by Zend\Filter\FilterInterface * * Encrypts $value with the defined settings * * @param string $value The content to encrypt * @throws Exception\InvalidArgumentException * @return string The encrypted content */ public function encrypt($value) { // compress prior to encryption if (!empty($this->compression)) { $compress = new Compress($this->compression); $value = $compress($value); } try { $encrypted = $this->blockCipher->encrypt($value); } catch (CryptException\InvalidArgumentException $e) { throw new Exception\InvalidArgumentException($e->getMessage()); } return $encrypted; } /** * Defined by Zend\Filter\FilterInterface * * Decrypts $value with the defined settings * * @param string $value Content to decrypt * @return string The decrypted content */ public function decrypt($value) { $decrypted = $this->blockCipher->decrypt($value); // decompress after decryption if (!empty($this->compression)) { $decompress = new Decompress($this->compression); $decrypted = $decompress($decrypted); } return $decrypted; } /** * Returns the adapter name * * @return string */ public function toString() { return 'BlockCipher'; } } public keys * 'private' => private keys * 'envelope' => resulting envelope keys * ) */ protected $keys = array( 'public' => array(), 'private' => array(), 'envelope' => array(), ); /** * Internal passphrase * * @var string */ protected $passphrase; /** * Internal compression * * @var array */ protected $compression; /** * Internal create package * * @var bool */ protected $package = false; /** * Class constructor * Available options * 'public' => public key * 'private' => private key * 'envelope' => envelope key * 'passphrase' => passphrase * 'compression' => compress value with this compression adapter * 'package' => pack envelope keys into encrypted string, simplifies decryption * * @param string|array|Traversable $options Options for this adapter * @throws Exception\ExtensionNotLoadedException */ public function __construct($options = array()) { if (!extension_loaded('openssl')) { throw new Exception\ExtensionNotLoadedException('This filter needs the openssl extension'); } if ($options instanceof Traversable) { $options = ArrayUtils::iteratorToArray($options); } if (!is_array($options)) { $options = array('public' => $options); } if (array_key_exists('passphrase', $options)) { $this->setPassphrase($options['passphrase']); unset($options['passphrase']); } if (array_key_exists('compression', $options)) { $this->setCompression($options['compression']); unset($options['compress']); } if (array_key_exists('package', $options)) { $this->setPackage($options['package']); unset($options['package']); } $this->_setKeys($options); } /** * Sets the encryption keys * * @param string|array $keys Key with type association * @return self * @throws Exception\InvalidArgumentException */ protected function _setKeys($keys) { if (!is_array($keys)) { throw new Exception\InvalidArgumentException('Invalid options argument provided to filter'); } foreach ($keys as $type => $key) { if (is_file($key) and is_readable($key)) { $file = fopen($key, 'r'); $cert = fread($file, 8192); fclose($file); } else { $cert = $key; $key = count($this->keys[$type]); } switch ($type) { case 'public': $test = openssl_pkey_get_public($cert); if ($test === false) { throw new Exception\InvalidArgumentException("Public key '{$cert}' not valid"); } openssl_free_key($test); $this->keys['public'][$key] = $cert; break; case 'private': $test = openssl_pkey_get_private($cert, $this->passphrase); if ($test === false) { throw new Exception\InvalidArgumentException("Private key '{$cert}' not valid"); } openssl_free_key($test); $this->keys['private'][$key] = $cert; break; case 'envelope': $this->keys['envelope'][$key] = $cert; break; default: break; } } return $this; } /** * Returns all public keys * * @return array */ public function getPublicKey() { $key = $this->keys['public']; return $key; } /** * Sets public keys * * @param string|array $key Public keys * @return self */ public function setPublicKey($key) { if (is_array($key)) { foreach ($key as $type => $option) { if ($type !== 'public') { $key['public'] = $option; unset($key[$type]); } } } else { $key = array('public' => $key); } return $this->_setKeys($key); } /** * Returns all private keys * * @return array */ public function getPrivateKey() { $key = $this->keys['private']; return $key; } /** * Sets private keys * * @param string $key Private key * @param string $passphrase * @return self */ public function setPrivateKey($key, $passphrase = null) { if (is_array($key)) { foreach ($key as $type => $option) { if ($type !== 'private') { $key['private'] = $option; unset($key[$type]); } } } else { $key = array('private' => $key); } if ($passphrase !== null) { $this->setPassphrase($passphrase); } return $this->_setKeys($key); } /** * Returns all envelope keys * * @return array */ public function getEnvelopeKey() { $key = $this->keys['envelope']; return $key; } /** * Sets envelope keys * * @param string|array $key Envelope keys * @return self */ public function setEnvelopeKey($key) { if (is_array($key)) { foreach ($key as $type => $option) { if ($type !== 'envelope') { $key['envelope'] = $option; unset($key[$type]); } } } else { $key = array('envelope' => $key); } return $this->_setKeys($key); } /** * Returns the passphrase * * @return string */ public function getPassphrase() { return $this->passphrase; } /** * Sets a new passphrase * * @param string $passphrase * @return self */ public function setPassphrase($passphrase) { $this->passphrase = $passphrase; return $this; } /** * Returns the compression * * @return array */ public function getCompression() { return $this->compression; } /** * Sets a internal compression for values to encrypt * * @param string|array $compression * @return self */ public function setCompression($compression) { if (is_string($this->compression)) { $compression = array('adapter' => $compression); } $this->compression = $compression; return $this; } /** * Returns if header should be packaged * * @return bool */ public function getPackage() { return $this->package; } /** * Sets if the envelope keys should be included in the encrypted value * * @param bool $package * @return self */ public function setPackage($package) { $this->package = (bool) $package; return $this; } /** * Encrypts $value with the defined settings * Note that you also need the "encrypted" keys to be able to decrypt * * @param string $value Content to encrypt * @return string The encrypted content * @throws Exception\RuntimeException */ public function encrypt($value) { $encrypted = array(); $encryptedkeys = array(); if (count($this->keys['public']) == 0) { throw new Exception\RuntimeException('Openssl can not encrypt without public keys'); } $keys = array(); $fingerprints = array(); $count = -1; foreach ($this->keys['public'] as $key => $cert) { $keys[$key] = openssl_pkey_get_public($cert); if ($this->package) { $details = openssl_pkey_get_details($keys[$key]); if ($details === false) { $details = array('key' => 'ZendFramework'); } ++$count; $fingerprints[$count] = md5($details['key']); } } // compress prior to encryption if (!empty($this->compression)) { $compress = new Compress($this->compression); $value = $compress($value); } $crypt = openssl_seal($value, $encrypted, $encryptedkeys, $keys); foreach ($keys as $key) { openssl_free_key($key); } if ($crypt === false) { throw new Exception\RuntimeException('Openssl was not able to encrypt your content with the given options'); } $this->keys['envelope'] = $encryptedkeys; // Pack data and envelope keys into single string if ($this->package) { $header = pack('n', count($this->keys['envelope'])); foreach ($this->keys['envelope'] as $key => $envKey) { $header .= pack('H32n', $fingerprints[$key], strlen($envKey)) . $envKey; } $encrypted = $header . $encrypted; } return $encrypted; } /** * Defined by Zend\Filter\FilterInterface * * Decrypts $value with the defined settings * * @param string $value Content to decrypt * @return string The decrypted content * @throws Exception\RuntimeException */ public function decrypt($value) { $decrypted = ""; $envelope = current($this->getEnvelopeKey()); if (count($this->keys['private']) !== 1) { throw new Exception\RuntimeException('Please give a private key for decryption with Openssl'); } if (!$this->package && empty($envelope)) { throw new Exception\RuntimeException('Please give an envelope key for decryption with Openssl'); } foreach ($this->keys['private'] as $cert) { $keys = openssl_pkey_get_private($cert, $this->getPassphrase()); } if ($this->package) { $details = openssl_pkey_get_details($keys); if ($details !== false) { $fingerprint = md5($details['key']); } else { $fingerprint = md5("ZendFramework"); } $count = unpack('ncount', $value); $count = $count['count']; $length = 2; for ($i = $count; $i > 0; --$i) { $header = unpack('H32print/nsize', substr($value, $length, 18)); $length += 18; if ($header['print'] == $fingerprint) { $envelope = substr($value, $length, $header['size']); } $length += $header['size']; } // remainder of string is the value to decrypt $value = substr($value, $length); } $crypt = openssl_open($value, $decrypted, $envelope, $keys); openssl_free_key($keys); if ($crypt === false) { throw new Exception\RuntimeException('Openssl was not able to decrypt you content with the given options'); } // decompress after decryption if (!empty($this->compression)) { $decompress = new Decompress($this->compression); $decrypted = $decompress($decrypted); } return $decrypted; } /** * Returns the adapter name * * @return string */ public function toString() { return 'Openssl'; } } $value) { $setter = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); if (method_exists($this, $setter)) { $this->{$setter}($value); } elseif (array_key_exists($key, $this->options)) { $this->options[$key] = $value; } else { throw new Exception\InvalidArgumentException(sprintf( 'The option "%s" does not have a matching %s setter method or options[%s] array key', $key, $setter, $key )); } } return $this; } /** * Retrieve options representing object state * * @return array */ public function getOptions() { return $this->options; } /** * Invoke filter as a command * * Proxies to {@link filter()} * * @param mixed $value * @throws Exception\ExceptionInterface If filtering $value is impossible * @return mixed */ public function __invoke($value) { return $this->filter($value); } /** * @param mixed $options * @return bool */ protected static function isOptions($options) { return (is_array($options) || $options instanceof Traversable); } } 'Zend\I18n\Filter\Alnum', 'alpha' => 'Zend\I18n\Filter\Alpha', 'basename' => 'Zend\Filter\BaseName', 'boolean' => 'Zend\Filter\Boolean', 'callback' => 'Zend\Filter\Callback', 'compress' => 'Zend\Filter\Compress', 'compressbz2' => 'Zend\Filter\Compress\Bz2', 'compressgz' => 'Zend\Filter\Compress\Gz', 'compresslzf' => 'Zend\Filter\Compress\Lzf', 'compressrar' => 'Zend\Filter\Compress\Rar', 'compresssnappy' => 'Zend\Filter\Compress\Snappy', 'compresstar' => 'Zend\Filter\Compress\Tar', 'compresszip' => 'Zend\Filter\Compress\Zip', 'datetimeformatter' => 'Zend\Filter\DateTimeFormatter', 'decompress' => 'Zend\Filter\Decompress', 'decrypt' => 'Zend\Filter\Decrypt', 'digits' => 'Zend\Filter\Digits', 'dir' => 'Zend\Filter\Dir', 'encrypt' => 'Zend\Filter\Encrypt', 'encryptblockcipher' => 'Zend\Filter\Encrypt\BlockCipher', 'encryptopenssl' => 'Zend\Filter\Encrypt\Openssl', 'filedecrypt' => 'Zend\Filter\File\Decrypt', 'fileencrypt' => 'Zend\Filter\File\Encrypt', 'filelowercase' => 'Zend\Filter\File\LowerCase', 'filerename' => 'Zend\Filter\File\Rename', 'filerenameupload' => 'Zend\Filter\File\RenameUpload', 'fileuppercase' => 'Zend\Filter\File\UpperCase', 'htmlentities' => 'Zend\Filter\HtmlEntities', 'inflector' => 'Zend\Filter\Inflector', 'int' => 'Zend\Filter\Int', 'null' => 'Zend\Filter\Null', 'numberformat' => 'Zend\I18n\Filter\NumberFormat', 'pregreplace' => 'Zend\Filter\PregReplace', 'realpath' => 'Zend\Filter\RealPath', 'stringtolower' => 'Zend\Filter\StringToLower', 'stringtoupper' => 'Zend\Filter\StringToUpper', 'stringtrim' => 'Zend\Filter\StringTrim', 'stripnewlines' => 'Zend\Filter\StripNewlines', 'striptags' => 'Zend\Filter\StripTags', 'urinormalize' => 'Zend\Filter\UriNormalize', 'wordcamelcasetodash' => 'Zend\Filter\Word\CamelCaseToDash', 'wordcamelcasetoseparator' => 'Zend\Filter\Word\CamelCaseToSeparator', 'wordcamelcasetounderscore' => 'Zend\Filter\Word\CamelCaseToUnderscore', 'worddashtocamelcase' => 'Zend\Filter\Word\DashToCamelCase', 'worddashtoseparator' => 'Zend\Filter\Word\DashToSeparator', 'worddashtounderscore' => 'Zend\Filter\Word\DashToUnderscore', 'wordseparatortocamelcase' => 'Zend\Filter\Word\SeparatorToCamelCase', 'wordseparatortodash' => 'Zend\Filter\Word\SeparatorToDash', 'wordseparatortoseparator' => 'Zend\Filter\Word\SeparatorToSeparator', 'wordunderscoretocamelcase' => 'Zend\Filter\Word\UnderscoreToCamelCase', 'wordunderscoretodash' => 'Zend\Filter\Word\UnderscoreToDash', 'wordunderscoretoseparator' => 'Zend\Filter\Word\UnderscoreToSeparator', ); /** * Whether or not to share by default; default to false * * @var bool */ protected $shareByDefault = false; /** * Validate the plugin * * Checks that the filter loaded is either a valid callback or an instance * of FilterInterface. * * @param mixed $plugin * @return void * @throws Exception\RuntimeException if invalid */ public function validatePlugin($plugin) { if ($plugin instanceof FilterInterface) { // we're okay return; } if (is_callable($plugin)) { // also okay return; } throw new Exception\RuntimeException(sprintf( 'Plugin of type %s is invalid; must implement %s\FilterInterface or be callable', (is_object($plugin) ? get_class($plugin) : gettype($plugin)), __NAMESPACE__ )); } } adapter->decrypt($value); } } filters = new PriorityQueue(); if (null !== $options) { $this->setOptions($options); } } /** * @param array|Traversable $options * @return self * @throws Exception\InvalidArgumentException */ public function setOptions($options) { if (!is_array($options) && !$options instanceof \Traversable) { throw new Exception\InvalidArgumentException(sprintf( 'Expected array or Traversable; received "%s"', (is_object($options) ? get_class($options) : gettype($options)) )); } foreach ($options as $key => $value) { switch (strtolower($key)) { case 'callbacks': foreach ($value as $spec) { $callback = isset($spec['callback']) ? $spec['callback'] : false; $priority = isset($spec['priority']) ? $spec['priority'] : static::DEFAULT_PRIORITY; if ($callback) { $this->attach($callback, $priority); } } break; case 'filters': foreach ($value as $spec) { $name = isset($spec['name']) ? $spec['name'] : false; $options = isset($spec['options']) ? $spec['options'] : array(); $priority = isset($spec['priority']) ? $spec['priority'] : static::DEFAULT_PRIORITY; if ($name) { $this->attachByName($name, $options, $priority); } } break; default: // ignore other options break; } } return $this; } /** * Return the count of attached filters * * @return int */ public function count() { return count($this->filters); } /** * Get plugin manager instance * * @return FilterPluginManager */ public function getPluginManager() { if (!$this->plugins) { $this->setPluginManager(new FilterPluginManager()); } return $this->plugins; } /** * Set plugin manager instance * * @param FilterPluginManager $plugins * @return self */ public function setPluginManager(FilterPluginManager $plugins) { $this->plugins = $plugins; return $this; } /** * Retrieve a filter plugin by name * * @param mixed $name * @param array $options * @return FilterInterface */ public function plugin($name, array $options = array()) { $plugins = $this->getPluginManager(); return $plugins->get($name, $options); } /** * Attach a filter to the chain * * @param callable|FilterInterface $callback A Filter implementation or valid PHP callback * @param int $priority Priority at which to enqueue filter; defaults to 1000 (higher executes earlier) * @throws Exception\InvalidArgumentException * @return self */ public function attach($callback, $priority = self::DEFAULT_PRIORITY) { if (!is_callable($callback)) { if (!$callback instanceof FilterInterface) { throw new Exception\InvalidArgumentException(sprintf( 'Expected a valid PHP callback; received "%s"', (is_object($callback) ? get_class($callback) : gettype($callback)) )); } $callback = array($callback, 'filter'); } $this->filters->insert($callback, $priority); return $this; } /** * Attach a filter to the chain using a short name * * Retrieves the filter from the attached plugin manager, and then calls attach() * with the retrieved instance. * * @param string $name * @param mixed $options * @param int $priority Priority at which to enqueue filter; defaults to 1000 (higher executes earlier) * @return self */ public function attachByName($name, $options = array(), $priority = self::DEFAULT_PRIORITY) { if (!is_array($options)) { $options = (array) $options; } elseif (empty($options)) { $options = null; } $filter = $this->getPluginManager()->get($name, $options); return $this->attach($filter, $priority); } /** * Merge the filter chain with the one given in parameter * * @param FilterChain $filterChain * @return self */ public function merge(FilterChain $filterChain) { foreach ($filterChain->filters->toArray(PriorityQueue::EXTR_BOTH) as $item) { $this->attach($item['data'], $item['priority']); } return $this; } /** * Get all the filters * * @return PriorityQueue */ public function getFilters() { return $this->filters; } /** * Returns $value filtered through each filter in the chain * * Filters are run in the order in which they were added to the chain (FIFO) * * @param mixed $value * @return mixed */ public function filter($value) { $chain = clone $this->filters; $valueFiltered = $value; foreach ($chain as $filter) { $valueFiltered = call_user_func($filter, $valueFiltered); } return $valueFiltered; } /** * Clone filters */ public function __clone() { $this->filters = clone $this->filters; } /** * Prepare filter chain for serialization * * Plugin manager (property 'plugins') cannot * be serialized. On wakeup the property remains unset * and next invokation to getPluginManager() sets * the default plugin manager instance (FilterPluginManager). */ public function __sleep() { return array('filters'); } } null, ); /** * Sets filter options * * @param string|array|Traversable $charlistOrOptions */ public function __construct($charlistOrOptions = null) { if ($charlistOrOptions !== null) { if (!is_array($charlistOrOptions) && !$charlistOrOptions instanceof Traversable) { $this->setCharList($charlistOrOptions); } else { $this->setOptions($charlistOrOptions); } } } /** * Sets the charList option * * @param string $charList * @return self Provides a fluent interface */ public function setCharList($charList) { if (empty($charList)) { $charList = null; } $this->options['charlist'] = $charList; return $this; } /** * Returns the charList option * * @return string|null */ public function getCharList() { return $this->options['charlist']; } /** * Defined by Zend\Filter\FilterInterface * * Returns the string $value with characters stripped from the beginning and end * * @param string $value * @return string */ public function filter($value) { // Do not filter non-string values if (!is_string($value)) { return $value; } if (null === $this->options['charlist']) { return $this->unicodeTrim((string) $value); } return $this->unicodeTrim((string) $value, $this->options['charlist']); } /** * Unicode aware trim method * Fixes a PHP problem * * @param string $value * @param string $charlist * @return string */ protected function unicodeTrim($value, $charlist = '\\\\s') { $chars = preg_replace( array('/[\^\-\]\\\]/S', '/\\\{4}/S', '/\//'), array('\\\\\\0', '\\', '\/'), $charlist ); $pattern = '/^[' . $chars . ']+|[' . $chars . ']+$/usSD'; return preg_replace($pattern, '', $value); } } null, ); /** * Constructor * * @param string|array|Traversable $encodingOrOptions OPTIONAL */ public function __construct($encodingOrOptions = null) { if ($encodingOrOptions !== null) { if (!static::isOptions($encodingOrOptions)) { $this->setEncoding($encodingOrOptions); } else { $this->setOptions($encodingOrOptions); } } } /** * Defined by Zend\Filter\FilterInterface * * Returns the string $value, converting characters to uppercase as necessary * * If the value provided is non-scalar, the value will remain unfiltered * and an E_USER_WARNING will be raised indicating it's unfilterable. * * @param string $value * @return string|mixed */ public function filter($value) { if (null === $value) { return null; } if (!is_scalar($value)) { trigger_error( sprintf( '%s expects parameter to be scalar, "%s" given; cannot filter', __METHOD__, (is_object($value) ? get_class($value) : gettype($value)) ), E_USER_WARNING ); return $value; } if ($this->options['encoding'] !== null) { return mb_strtoupper((string) $value, $this->options['encoding']); } return strtoupper((string) $value); } } setOptions($options); } } /** * Set the format string accepted by date() to use when formatting a string * * @param string $format * @return self */ public function setFormat($format) { $this->format = $format; return $this; } /** * Filter a datetime string by normalizing it to the filters specified format * * @param string $value * @throws Exception\InvalidArgumentException * @return string */ public function filter($value) { try { $result = $this->normalizeDateTime($value); } catch (\Exception $e) { // DateTime threw an exception, an invalid date string was provided throw new Exception\InvalidArgumentException('Invalid date string provided', $e->getCode(), $e); } return $result; } /** * Normalize the provided value to a formatted string * * @param string|int|DateTime $value * @return string */ protected function normalizeDateTime($value) { if ($value === '' || $value === null) { return $value; } elseif (is_int($value)) { $value = new DateTime('@' . $value); } elseif (!$value instanceof DateTime) { $value = new DateTime($value); } return $value->format($this->format); } } separator, '#'); if (StringUtils::hasPcreUnicodeSupport()) { $patterns = array( '#(' . $pregQuotedSeparator.')(\p{L}{1})#u', '#(^\p{Ll}{1})#u', ); if (!extension_loaded('mbstring')) { $replacements = array( function ($matches) { return strtoupper($matches[2]); }, function ($matches) { return strtoupper($matches[1]); }, ); } else { $replacements = array( function ($matches) { return mb_strtoupper($matches[2], 'UTF-8'); }, function ($matches) { return mb_strtoupper($matches[1], 'UTF-8'); }, ); } } else { $patterns = array( '#(' . $pregQuotedSeparator.')([A-Za-z]{1})#', '#(^[A-Za-z]{1})#', ); $replacements = array( function ($matches) { return strtoupper($matches[2]); }, function ($matches) { return strtoupper($matches[1]); }, ); } $filtered = $value; foreach ($patterns as $index => $pattern) { $filtered = preg_replace_callback($pattern, $replacements[$index], $filtered); } return $filtered; } } separator . '\1', $this->separator . '\1'); } else { $pattern = array('#(?<=(?:[A-Z]))([A-Z]+)([A-Z][a-z])#', '#(?<=(?:[a-z0-9]))([A-Z])#'); $replacement = array('\1' . $this->separator . '\2', $this->separator . '\1'); } return preg_replace($pattern, $replacement, $value); } } separator, $value); } } setSeparator($separator); } /** * Sets a new separator * * @param string $separator Separator * @return self * @throws Exception\InvalidArgumentException */ public function setSeparator($separator) { if (!is_string($separator)) { throw new Exception\InvalidArgumentException('"' . $separator . '" is not a valid separator.'); } $this->separator = $separator; return $this; } /** * Returns the actual set separator * * @return string */ public function getSeparator() { return $this->separator; } } setSearchSeparator($searchSeparator); $this->setReplacementSeparator($replacementSeparator); } /** * Sets a new seperator to search for * * @param string $separator Seperator to search for * @return self */ public function setSearchSeparator($separator) { $this->searchSeparator = $separator; return $this; } /** * Returns the actual set separator to search for * * @return string */ public function getSearchSeparator() { return $this->searchSeparator; } /** * Sets a new separator which replaces the searched one * * @param string $separator Separator which replaces the searched one * @return self */ public function setReplacementSeparator($separator) { $this->replacementSeparator = $separator; return $this; } /** * Returns the actual set separator which replaces the searched one * * @return string */ public function getReplacementSeparator() { return $this->replacementSeparator; } /** * Defined by Zend\Filter\Filter * * Returns the string $value, replacing the searched separators with the defined ones * * @param string $value * @return string */ public function filter($value) { if ($this->searchSeparator == null) { throw new Exception\RuntimeException('You must provide a search separator for this filter to work.'); } $pattern = '#' . preg_quote($this->searchSeparator, '#') . '#'; return preg_replace($pattern, $this->replacementSeparator, $value); } } setOptions($options); } /** * Retrieve plugin manager * * @return FilterPluginManager */ public function getPluginManager() { if (!$this->pluginManager instanceof FilterPluginManager) { $this->setPluginManager(new FilterPluginManager()); } return $this->pluginManager; } /** * Set plugin manager * * @param FilterPluginManager $manager * @return self */ public function setPluginManager(FilterPluginManager $manager) { $this->pluginManager = $manager; return $this; } /** * Set options * * @param array|Traversable $options * @return self */ public function setOptions($options) { if ($options instanceof Traversable) { $options = ArrayUtils::iteratorToArray($options); } // Set plugin manager if (array_key_exists('pluginManager', $options)) { if (is_scalar($options['pluginManager']) && class_exists($options['pluginManager'])) { $options['pluginManager'] = new $options['pluginManager']; } $this->setPluginManager($options['pluginManager']); } if (array_key_exists('throwTargetExceptionsOn', $options)) { $this->setThrowTargetExceptionsOn($options['throwTargetExceptionsOn']); } if (array_key_exists('targetReplacementIdentifier', $options)) { $this->setTargetReplacementIdentifier($options['targetReplacementIdentifier']); } if (array_key_exists('target', $options)) { $this->setTarget($options['target']); } if (array_key_exists('rules', $options)) { $this->addRules($options['rules']); } return $this; } /** * Set Whether or not the inflector should throw an exception when a replacement * identifier is still found within an inflected target. * * @param bool $throwTargetExceptionsOn * @return self */ public function setThrowTargetExceptionsOn($throwTargetExceptionsOn) { $this->throwTargetExceptionsOn = ($throwTargetExceptionsOn == true) ? true : false; return $this; } /** * Will exceptions be thrown? * * @return bool */ public function isThrowTargetExceptionsOn() { return $this->throwTargetExceptionsOn; } /** * Set the Target Replacement Identifier, by default ':' * * @param string $targetReplacementIdentifier * @return self */ public function setTargetReplacementIdentifier($targetReplacementIdentifier) { if ($targetReplacementIdentifier) { $this->targetReplacementIdentifier = (string) $targetReplacementIdentifier; } return $this; } /** * Get Target Replacement Identifier * * @return string */ public function getTargetReplacementIdentifier() { return $this->targetReplacementIdentifier; } /** * Set a Target * ex: 'scripts/:controller/:action.:suffix' * * @param string $target * @return self */ public function setTarget($target) { $this->target = (string) $target; return $this; } /** * Retrieve target * * @return string */ public function getTarget() { return $this->target; } /** * Set Target Reference * * @param reference $target * @return self */ public function setTargetReference(&$target) { $this->target =& $target; return $this; } /** * Is the same as calling addRules() with the exception that it * clears the rules before adding them. * * @param array $rules * @return self */ public function setRules(array $rules) { $this->clearRules(); $this->addRules($rules); return $this; } /** * Multi-call to setting filter rules. * * If prefixed with a ":" (colon), a filter rule will be added. If not * prefixed, a static replacement will be added. * * ex: * array( * ':controller' => array('CamelCaseToUnderscore', 'StringToLower'), * ':action' => array('CamelCaseToUnderscore', 'StringToLower'), * 'suffix' => 'phtml' * ); * * @param array $rules * @return self */ public function addRules(array $rules) { $keys = array_keys($rules); foreach ($keys as $spec) { if ($spec[0] == ':') { $this->addFilterRule($spec, $rules[$spec]); } else { $this->setStaticRule($spec, $rules[$spec]); } } return $this; } /** * Get rules * * By default, returns all rules. If a $spec is provided, will return those * rules if found, false otherwise. * * @param string $spec * @return array|false */ public function getRules($spec = null) { if (null !== $spec) { $spec = $this->_normalizeSpec($spec); if (isset($this->rules[$spec])) { return $this->rules[$spec]; } return false; } return $this->rules; } /** * Returns a rule set by setFilterRule(), a numeric index must be provided * * @param string $spec * @param int $index * @return FilterInterface|false */ public function getRule($spec, $index) { $spec = $this->_normalizeSpec($spec); if (isset($this->rules[$spec]) && is_array($this->rules[$spec])) { if (isset($this->rules[$spec][$index])) { return $this->rules[$spec][$index]; } } return false; } /** * Clears the rules currently in the inflector * * @return self */ public function clearRules() { $this->rules = array(); return $this; } /** * Set a filtering rule for a spec. $ruleSet can be a string, Filter object * or an array of strings or filter objects. * * @param string $spec * @param array|string|\Zend\Filter\FilterInterface $ruleSet * @return self */ public function setFilterRule($spec, $ruleSet) { $spec = $this->_normalizeSpec($spec); $this->rules[$spec] = array(); return $this->addFilterRule($spec, $ruleSet); } /** * Add a filter rule for a spec * * @param mixed $spec * @param mixed $ruleSet * @return self */ public function addFilterRule($spec, $ruleSet) { $spec = $this->_normalizeSpec($spec); if (!isset($this->rules[$spec])) { $this->rules[$spec] = array(); } if (!is_array($ruleSet)) { $ruleSet = array($ruleSet); } if (is_string($this->rules[$spec])) { $temp = $this->rules[$spec]; $this->rules[$spec] = array(); $this->rules[$spec][] = $temp; } foreach ($ruleSet as $rule) { $this->rules[$spec][] = $this->_getRule($rule); } return $this; } /** * Set a static rule for a spec. This is a single string value * * @param string $name * @param string $value * @return self */ public function setStaticRule($name, $value) { $name = $this->_normalizeSpec($name); $this->rules[$name] = (string) $value; return $this; } /** * Set Static Rule Reference. * * This allows a consuming class to pass a property or variable * in to be referenced when its time to build the output string from the * target. * * @param string $name * @param mixed $reference * @return self */ public function setStaticRuleReference($name, &$reference) { $name = $this->_normalizeSpec($name); $this->rules[$name] =& $reference; return $this; } /** * Inflect * * @param string|array $source * @throws Exception\RuntimeException * @return string */ public function filter($source) { // clean source foreach ((array) $source as $sourceName => $sourceValue) { $source[ltrim($sourceName, ':')] = $sourceValue; } $pregQuotedTargetReplacementIdentifier = preg_quote($this->targetReplacementIdentifier, '#'); $processedParts = array(); foreach ($this->rules as $ruleName => $ruleValue) { if (isset($source[$ruleName])) { if (is_string($ruleValue)) { // overriding the set rule $processedParts['#' . $pregQuotedTargetReplacementIdentifier . $ruleName . '#'] = str_replace('\\', '\\\\', $source[$ruleName]); } elseif (is_array($ruleValue)) { $processedPart = $source[$ruleName]; foreach ($ruleValue as $ruleFilter) { $processedPart = $ruleFilter($processedPart); } $processedParts['#' . $pregQuotedTargetReplacementIdentifier . $ruleName . '#'] = str_replace('\\', '\\\\', $processedPart); } } elseif (is_string($ruleValue)) { $processedParts['#' . $pregQuotedTargetReplacementIdentifier . $ruleName . '#'] = str_replace('\\', '\\\\', $ruleValue); } } // all of the values of processedParts would have been str_replace('\\', '\\\\', ..)'d to disable preg_replace backreferences $inflectedTarget = preg_replace(array_keys($processedParts), array_values($processedParts), $this->target); if ($this->throwTargetExceptionsOn && (preg_match('#(?=' . $pregQuotedTargetReplacementIdentifier.'[A-Za-z]{1})#', $inflectedTarget) == true)) { throw new Exception\RuntimeException('A replacement identifier ' . $this->targetReplacementIdentifier . ' was found inside the inflected target, perhaps a rule was not satisfied with a target source? Unsatisfied inflected target: ' . $inflectedTarget); } return $inflectedTarget; } /** * Normalize spec string * * @param string $spec * @return string */ protected function _normalizeSpec($spec) { return ltrim((string) $spec, ':&'); } /** * Resolve named filters and convert them to filter objects. * * @param string $rule * @return FilterInterface */ protected function _getRule($rule) { if ($rule instanceof FilterInterface) { return $rule; } $rule = (string) $rule; return $this->getPluginManager()->get($rule); } } setShareByDefault(false); } static::$plugins = $manager; } /** * Get plugin manager for loading filter classes * * @return FilterPluginManager */ public static function getPluginManager() { if (null === static::$plugins) { static::setPluginManager(new FilterPluginManager()); } return static::$plugins; } /** * Returns a value filtered through a specified filter class, without requiring separate * instantiation of the filter object. * * The first argument of this method is a data input value, that you would have filtered. * The second argument is a string, which corresponds to the basename of the filter class, * relative to the Zend\Filter namespace. This method automatically loads the class, * creates an instance, and applies the filter() method to the data input. You can also pass * an array of constructor arguments, if they are needed for the filter class. * * @param mixed $value * @param string $classBaseName * @param array $args OPTIONAL * @return mixed * @throws Exception\ExceptionInterface */ public static function execute($value, $classBaseName, array $args = array()) { $plugins = static::getPluginManager(); $filter = $plugins->get($classBaseName, $args); return $filter->filter($value); } } setQuoteStyle($options['quotestyle']); $this->setEncoding($options['encoding']); $this->setDoubleQuote($options['doublequote']); } /** * Returns the quoteStyle option * * @return int */ public function getQuoteStyle() { return $this->quoteStyle; } /** * Sets the quoteStyle option * * @param int $quoteStyle * @return self Provides a fluent interface */ public function setQuoteStyle($quoteStyle) { $this->quoteStyle = $quoteStyle; return $this; } /** * Get encoding * * @return string */ public function getEncoding() { return $this->encoding; } /** * Set encoding * * @param string $value * @return self */ public function setEncoding($value) { $this->encoding = (string) $value; return $this; } /** * Returns the charSet option * * Proxies to {@link getEncoding()} * * @return string */ public function getCharSet() { return $this->getEncoding(); } /** * Sets the charSet option * * Proxies to {@link setEncoding()} * * @param string $charSet * @return self Provides a fluent interface */ public function setCharSet($charSet) { return $this->setEncoding($charSet); } /** * Returns the doubleQuote option * * @return bool */ public function getDoubleQuote() { return $this->doubleQuote; } /** * Sets the doubleQuote option * * @param bool $doubleQuote * @return self Provides a fluent interface */ public function setDoubleQuote($doubleQuote) { $this->doubleQuote = (bool) $doubleQuote; return $this; } /** * Defined by Zend\Filter\FilterInterface * * Returns the string $value, converting characters to their corresponding HTML entity * equivalents where they exist * * If the value provided is non-scalar, the value will remain unfiltered * and an E_USER_WARNING will be raised indicating it's unfilterable. * * @param string $value * @return string|mixed * @throws Exception\DomainException on encoding mismatches */ public function filter($value) { if (null === $value) { return null; } if (!is_scalar($value)) { trigger_error( sprintf( '%s expects parameter to be scalar, "%s" given; cannot filter', __METHOD__, (is_object($value) ? get_class($value) : gettype($value)) ), E_USER_WARNING ); return $value; } $filtered = htmlentities((string) $value, $this->getQuoteStyle(), $this->getEncoding(), $this->getDoubleQuote()); if (strlen((string) $value) && !strlen($filtered)) { if (!function_exists('iconv')) { throw new Exception\DomainException('Encoding mismatch has resulted in htmlentities errors'); } $enc = $this->getEncoding(); $value = iconv('', $this->getEncoding() . '//IGNORE', (string) $value); $filtered = htmlentities($value, $this->getQuoteStyle(), $enc, $this->getDoubleQuote()); if (!strlen($filtered)) { throw new Exception\DomainException('Encoding mismatch has resulted in htmlentities errors'); } } return $filtered; } } Tags which are allowed * 'allowAttribs' => Attributes which are allowed * 'allowComments' => Are comments allowed ? * * @param string|array|Traversable $options */ public function __construct($options = null) { if ($options instanceof Traversable) { $options = ArrayUtils::iteratorToArray($options); } if ((!is_array($options)) || (is_array($options) && !array_key_exists('allowTags', $options) && !array_key_exists('allowAttribs', $options) && !array_key_exists('allowComments', $options))) { $options = func_get_args(); $temp['allowTags'] = array_shift($options); if (!empty($options)) { $temp['allowAttribs'] = array_shift($options); } if (!empty($options)) { $temp['allowComments'] = array_shift($options); } $options = $temp; } if (array_key_exists('allowTags', $options)) { $this->setTagsAllowed($options['allowTags']); } if (array_key_exists('allowAttribs', $options)) { $this->setAttributesAllowed($options['allowAttribs']); } } /** * Returns the tagsAllowed option * * @return array */ public function getTagsAllowed() { return $this->tagsAllowed; } /** * Sets the tagsAllowed option * * @param array|string $tagsAllowed * @return self Provides a fluent interface */ public function setTagsAllowed($tagsAllowed) { if (!is_array($tagsAllowed)) { $tagsAllowed = array($tagsAllowed); } foreach ($tagsAllowed as $index => $element) { // If the tag was provided without attributes if (is_int($index) && is_string($element)) { // Canonicalize the tag name $tagName = strtolower($element); // Store the tag as allowed with no attributes $this->tagsAllowed[$tagName] = array(); } // Otherwise, if a tag was provided with attributes elseif (is_string($index) && (is_array($element) || is_string($element))) { // Canonicalize the tag name $tagName = strtolower($index); // Canonicalize the attributes if (is_string($element)) { $element = array($element); } // Store the tag as allowed with the provided attributes $this->tagsAllowed[$tagName] = array(); foreach ($element as $attribute) { if (is_string($attribute)) { // Canonicalize the attribute name $attributeName = strtolower($attribute); $this->tagsAllowed[$tagName][$attributeName] = null; } } } } return $this; } /** * Returns the attributesAllowed option * * @return array */ public function getAttributesAllowed() { return $this->attributesAllowed; } /** * Sets the attributesAllowed option * * @param array|string $attributesAllowed * @return self Provides a fluent interface */ public function setAttributesAllowed($attributesAllowed) { if (!is_array($attributesAllowed)) { $attributesAllowed = array($attributesAllowed); } // Store each attribute as allowed foreach ($attributesAllowed as $attribute) { if (is_string($attribute)) { // Canonicalize the attribute name $attributeName = strtolower($attribute); $this->attributesAllowed[$attributeName] = null; } } return $this; } /** * Defined by Zend\Filter\FilterInterface * * If the value provided is non-scalar, the value will remain unfiltered * and an E_USER_WARNING will be raised indicating it's unfilterable. * * @todo improve docblock descriptions * @param string $value * @return string|mixed */ public function filter($value) { if (null === $value) { return null; } if (!is_scalar($value)) { trigger_error( sprintf( '%s expects parameter to be scalar, "%s" given; cannot filter', __METHOD__, (is_object($value) ? get_class($value) : gettype($value)) ), E_USER_WARNING ); return $value; } $value = (string) $value; // Strip HTML comments first while (strpos($value, '|\\Z))Ss', '', $string ); return parent::tokenizeString( $string ); } /** * Filter tokens * * Method to filter tokens, after the input string ahs been tokenized. The * filter should extract additional information from tokens, which are not * generally available yet, like the depth of a title depending on the * title markup. * * @param array $tokens * @return array */ protected function filterTokens( array $tokens ) { foreach ( $tokens as $nr => $token ) { switch ( true ) { // Extract the title / indentation level from the tokens // length. case $token instanceof ezcDocumentWikiTitleToken: case $token instanceof ezcDocumentWikiParagraphIndentationToken: $token->level = strlen( trim( $token->content ) ); break; } } return $tokens; } } ?> 'width', 'height' => 'height', 'align' => 'alignement', ); /** * Construct tokenizer * * Create token array with regular repression matching the respective * token. * * @return void */ public function __construct() { $this->tokens = array( // Match tokens which require to be at the start of a line before // matching the actual newlines, because they are the indicator for // line starts. array( 'class' => 'ezcDocumentWikiTitleToken', 'match' => '(\\A\\n(?Ph[1-6].' . self::WHITESPACE_CHARS . '*))S' ), array( 'class' => 'ezcDocumentWikiParagraphIndentationToken', 'match' => '(\\A\\n(?Pbq.)' . self::WHITESPACE_CHARS . '*)S' ), array( 'class' => 'ezcDocumentWikiQuoteToken', 'match' => '(\\A\\n(?P\\{quote\\}))S' ), array( 'class' => 'ezcDocumentWikiPageBreakToken', 'match' => '(\\A(?P\\n' . self::WHITESPACE_CHARS . '*(?P-{4})' . self::WHITESPACE_CHARS . '*)\\n)S' ), array( 'class' => 'ezcDocumentWikiBulletListItemToken', 'match' => '(\\A\\n(?P[#*-]*[*-])' . self::WHITESPACE_CHARS . '+)S' ), array( 'class' => 'ezcDocumentWikiEnumeratedListItemToken', 'match' => '(\\A\\n(?P[#*-]*#)' . self::WHITESPACE_CHARS . '+)S' ), array( 'class' => 'ezcDocumentWikiTableRowToken', 'match' => '(\\A(?P\\n)(?P\\|))S' ), array( 'class' => 'ezcDocumentWikiPluginToken', 'match' => '(\\A\\n(?P\\{([a-zA-Z]+)[^}]*\\}(?:.*?\\n\\{\\2\\})?))Ss' ), // Whitespaces array( 'class' => 'ezcDocumentWikiNewLineToken', 'match' => '(\\A' . self::WHITESPACE_CHARS . '*(?P\\r\\n|\\r|\\n))S' ), array( 'class' => 'ezcDocumentWikiWhitespaceToken', 'match' => '(\\A(?P' . self::WHITESPACE_CHARS . '+))S' ), array( 'class' => 'ezcDocumentWikiEndOfFileToken', 'match' => '(\\A(?P\\x0c))S' ), // Escape character array( 'class' => 'ezcDocumentWikiEscapeCharacterToken', 'match' => '(\\A(?P(?P\\\\))[^\\\\])S' ), // Inline markup array( 'class' => 'ezcDocumentWikiBoldToken', 'match' => '(\\A(?P\\*))S' ), array( 'class' => 'ezcDocumentWikiItalicToken', 'match' => '(\\A(?P_))S' ), array( 'class' => 'ezcDocumentWikiSuperscriptToken', 'match' => '(\\A(?P\\^))S' ), array( 'class' => 'ezcDocumentWikiSubscriptToken', 'match' => '(\\A(?P~))S' ), array( 'class' => 'ezcDocumentWikiUnderlineToken', 'match' => '(\\A(?P\\+))S' ), array( 'class' => 'ezcDocumentWikiStrikeToken', 'match' => '(\\A(?P-))S' ), array( 'class' => 'ezcDocumentWikiInlineQuoteToken', 'match' => '(\\A(?P\\?\\?))S' ), array( 'class' => 'ezcDocumentWikiMonospaceToken', 'match' => '(\\A(?P\\{\\{|\\}\\}))S' ), array( 'class' => 'ezcDocumentWikiLineBreakToken', 'match' => '(\\A(?P\\\\\\\\))S' ), array( 'class' => 'ezcDocumentWikiConfluenceLinkStartToken', 'match' => '(\\A(?P\\[))S' ), array( 'class' => 'ezcDocumentWikiLinkEndToken', 'match' => '(\\A(?P\\]))S' ), array( 'class' => 'ezcDocumentWikiTableHeaderToken', 'match' => '(\\A(?P\\|\\|))S' ), array( 'class' => 'ezcDocumentWikiSeparatorToken', 'match' => '(\\A(?P\\|))S' ), array( 'class' => 'ezcDocumentWikiExternalLinkToken', 'match' => '(\\A(?P(?P[a-z]+://\\S+?|mailto:\\S+?))[,.?!:;"\']?(?:' . self::WHITESPACE_CHARS . '|\\n|\\||]|$))S' ), array( 'class' => 'ezcDocumentWikiImageStartToken', 'match' => '(\\A(?P(?P!))\S)S' ), array( 'class' => 'ezcDocumentWikiImageEndToken', 'match' => '(\\A(?P!))S' ), // Match text except array( 'class' => 'ezcDocumentWikiTextLineToken', 'match' => '(\\A(?P[^' . self::TEXT_END_CHARS . ']+))S' ), // Match all special characters, which are not valid textual chars, // but do not have been matched by any other expression. array( 'class' => 'ezcDocumentWikiSpecialCharsToken', 'match' => '(\\A(?P([' . self::SPECIAL_CHARS . '])\\2*))S' ), ); } /** * Parse plugin contents * * Plugins are totally different in each wiki component and its contents * should not be passed through the normal wiki parser. So we fetch its * contents completely and let each tokinzer extract names and parameters * from the complete token itself. * * @param ezcDocumentWikiPluginToken $plugin * @return void */ protected function parsePluginContents( ezcDocumentWikiPluginToken $plugin ) { // Match title, property string and plugin contents // {code:title=Bar.java|borderStyle=solid} ... {code} if ( preg_match( '(^{(?P[a-zA-Z]+)(?::(?P[^}]+))?}(?:(?P.*){\\1})?$)s', $plugin->content, $match ) ) { $plugin->type = $match['type']; if ( isset( $match['text'] ) ) { $plugin->text = $match['text']; } // Parse plugin parameters if ( isset( $match['params'] ) ) { $rawParams = explode( '|', $match['params'] ); $parameters = array(); foreach ( $rawParams as $content ) { if ( preg_match( '(^(?P[a-zA-Z]+)=(?P.*)$)', $content, $match ) ) { $parameters[$match['name']] = $match['value']; } else { $parameters[] = $content; } } $plugin->parameters = $parameters; } } } /** * Parse confluence image descriptors * * Parse confluence image descriptors which are completely different from * other wiki languages, so that they cannot be handled by the default * parser. * * @param ezcDocumentWikiImageStartToken $token * @param mixed $descriptor * @return void */ protected function parseImageDescriptor( ezcDocumentWikiImageStartToken $token, $descriptor ) { if ( !preg_match_all( '((?P[a-zA-Z]+)(?:=(?P[^,]+))?)', $descriptor, $matches ) ) { return; } // Set known properties on image start node, if available. foreach ( $matches['name'] as $nr => $name ) { $name = strtolower( $name ); if ( isset( $this->imageAttributeMapping[$name] ) ) { $property = $this->imageAttributeMapping[$name]; $token->$property = $matches['value'][$nr]; } } } /** * Filter tokens * * Method to filter tokens, after the input string ahs been tokenized. The * filter should extract additional information from tokens, which are not * generally available yet, like the depth of a title depending on the * title markup. * * @param array $tokens * @return array */ protected function filterTokens( array $tokens ) { $lastImageStartToken = null; $lastImageSeparator = null; foreach ( $tokens as $nr => $token ) { switch ( true ) { // Extract the title / indentation level from the tokens // length. case $token instanceof ezcDocumentWikiTitleToken: $token->level = (int) $token->content[1]; break; case $token instanceof ezcDocumentWikiParagraphIndentationToken: $token->level = 1; break; case $token instanceof ezcDocumentWikiBulletListItemToken: case $token instanceof ezcDocumentWikiEnumeratedListItemToken: $token->indentation = strlen( $token->content ); break; case $token instanceof ezcDocumentWikiPluginToken: $this->parsePluginContents( $token ); break; case $token instanceof ezcDocumentWikiImageStartToken: // Store reference to last image start token $lastImageStartToken = $token; break; case $token instanceof ezcDocumentWikiSeparatorToken: if ( $lastImageStartToken !== null ) { $lastImageSeparator = $token; } break; case $token instanceof ezcDocumentWikiImageEndToken: if ( $lastImageSeparator === null ) { // No relating start token and/or separator - we do not // need to care. continue; } // Aggregate all texts until the separator $imageTokens = array(); $i = $nr - 1; while ( ( $i > 0 ) && ( $tokens[$i] !== $lastImageSeparator ) ) { $imageTokens[] = $tokens[$i]->content; unset( $tokens[$i--] ); } unset( $tokens[$i] ); // Extract and combine image descritor string, and remove // relating tokens, so that are not used elsewhere. $descriptior = implode( '', array_reverse( $imageTokens ) ); $this->parseImageDescriptor( $lastImageStartToken, $descriptior ); // Reset image token parsing environment $lastImageStartToken = null; $lastImageSeparator = null; break; case $token instanceof ezcDocumentWikiPluginToken: $this->parsePluginContents( $token ); break; } } return array_values( $tokens ); } } ?> * array( * array( * 'class' => Class name of token, * 'match' => Regular expression to match, * ), * ... * ) *
* * The array is evaluated in the given order, until one of the regular * expressions match. The regular expression should have at least one named * match (?P ... ), with the name "value", which will be assigned to the * token, created form the given class name, as its content. The matched * contents will be removed from the beginning of the string. * Optionally a second named match, called "match", may be used inside the * regular expression. If so, only the contents inside this match will be * removed from the beginning of the string. This enables you to perform a * trivial lookahead inside the tokenizer. * * If no expression matches, an exception will be thrown. * * Token filtering * --------------- * * After all tokens are extracted from the text, they may miss some values, * which may be required by the parser, like the level of title tokens. Those * should be extracted and assigned during the filtering stage. For this the * filterTokens() method should be implemented, which may iterate over the * token stream and assign the required values. * * If the wiki markup language supports plugins you may also want to "parse" * the plugin contents to extract type, parameters and its text here. * * @package Document * @version //autogen// */ abstract class ezcDocumentWikiTokenizer { /** * List with tokens and a regular expression matching the given token. * * The tokens are matched in the given order. * * @var array */ protected $tokens = array(); /** * Construct tokenizer * * Create token array with regular repression matching the respective * token. * * @return void */ abstract public function __construct(); /** * Tokenize the given file * * The method tries to tokenize the passed files and returns an array of * ezcDocumentWikiToken struct on succes, or throws a * ezcDocumentTokenizerException, if something could not be matched by any * token. * * @param string $file * @return array */ public function tokenizeFile( $file ) { if ( !file_exists( $file ) || !is_readable( $file ) ) { throw new ezcBaseFileNotFoundException( $file ); } return $this->tokenizeString( file_get_contents( $file ) ); } /** * Convert tabs to spaces * * Convert all tabs to spaces, as defined in: * http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#whitespace * * @param ezcDocumentWikiToken $token * @return void */ protected function convertTabs( ezcDocumentWikiToken $token ) { while ( ( $position = strpos( $token->content, "\t" ) ) !== false ) { $token->content = substr( $token->content, 0, $position ) . str_repeat( ' ', 9 - ( ( $position + $token->position ) % 8 ) ) . substr( $token->content, $position + 1 ); } } /** * Filter tokens * * Method to filter tokens, after the input string ahs been tokenized. The * filter should extract additional information from tokens, which are not * generally available yet, like the depth of a title depending on the * title markup. * * @param array $tokens * @return array */ abstract protected function filterTokens( array $tokens ); /** * Tokenize the given string * * The method tries to tokenize the passed strings and returns an array of * ezcDocumentWikiToken struct on succes, or throws a * ezcDocumentTokenizerException, if something could not be matched by any * token. * * @param string $string * @return array */ public function tokenizeString( $string ) { $line = 0; $position = 1; $tokens = array(); $string = "\n" . $string; // Normalize newlines $string = preg_replace( '([\x20\\t]*(?:\\r\\n|\\r|\\n))', "\n", $string ); while ( strlen( $string ) > 0 ) { foreach ( $this->tokens as $match ) { if ( preg_match( $match['match'], $string, $matches ) ) { // If the first part of the match is a // newline, add a respective token to the // stack. if ( ( $matches[0][0] === "\n" ) && ( $match['class'] !== 'ezcDocumentWikiNewLineToken' ) ) { $tokens[] = new ezcDocumentWikiNewLineToken( $matches[0][0], $line, $position ); ++$line; $position = 0; } // A token matched, so add the matched token to the token // list and update all variables. $class = $match['class']; $newToken = new $class( ( isset( $matches['value'] ) ? $matches['value'] : null ), $line, $position ); $match = isset( $matches['match'] ) ? $matches['match'] : $matches[0]; // Removed matched stuff from input string $string = substr( $string, $length = strlen( $match ) ); // On a newline token reset the line position and increase the line value if ( $newToken instanceof ezcDocumentWikiNewLineToken ) { ++$line; $position = 0; } else { // Otherwise still update the line // value, when there is at minimum // one newline in the match. This may // lead to a false position value. if ( ( $newLines = substr_count( $match, "\n" ) ) > 0 ) { $line += $newLines; $position = 0; } } // Convert tabs to spaces for whitespace tokens if ( $newToken instanceof ezcDocumentWikiWhitespaceToken ) { $this->convertTabs( $newToken ); } // If we found an explicit EOF token, just exit the parsing process. if ( $newToken instanceof ezcDocumentWikiEndOfFileToken ) { break 2; } // Add token to extracted token list $tokens[] = $newToken; // Update position, not before converting tabs to spaces. $position += ( $newToken instanceof ezcDocumentWikiNewLineToken ) ? 1 : strlen( $newToken->content ); // Restart the while loop, because we matched a token and // can retry with shortened string. continue 2; } } // None of the token definitions matched the input string. We throw // an exception with the position of the content in the input // string and the contents we could not match. // // This should never been thrown, but it is hard to prove that // there is nothing which is not matched by the regualr expressions // above. throw new ezcDocumentWikiTokenizerException( $line, $position, $string ); } // Finally append ainother newline token and a end of file token, to // make parsing the end easier. $tokens[] = new ezcDocumentWikiNewLineToken( "\n", $line, $position ); $tokens[] = new ezcDocumentWikiNewLineToken( "\n", $line, $position ); $tokens[] = new ezcDocumentWikiEndOfFileToken( null, $line, $position ); return $this->filterTokens( $tokens ); } } ?> wiki = $document; $this->path = $path; } /** * Trigger visitor error * * Emit a vistitor error, and convert it to an exception depending on the * error reporting settings. * * @param int $level * @param string $message * @param string $file * @param int $line * @param int $position * @return void */ public function triggerError( $level, $message, $file = null, $line = null, $position = null ) { if ( $level & $this->wiki->options->errorReporting ) { throw new ezcDocumentVisitException( $level, $message, $file, $line, $position ); } else { // If the error should not been reported, we aggregate it to maybe // display it later. $this->errors[] = new ezcDocumentVisitException( $level, $message, $file, $line, $position ); } } /** * Return list of errors occured during visiting the document. * * May be an empty array, if on errors occured, or a list of * ezcDocumentVisitException objects. * * @return array */ public function getErrors() { return $this->errors; } /** * Docarate Wiki AST * * Visit the Wiki abstract syntax tree. * * @param ezcDocumentWikiDocumentNode $ast * @return mixed */ public function visit( ezcDocumentWikiDocumentNode $ast ) { $this->ast = $ast; $this->preProcessAst( $ast ); // Reset footnote counters $this->footnoteCounter = 0; } /** * Add footnote * * @param ezcDocumentWikiNode $node * @return void */ protected function addFootnote( ezcDocumentWikiNode $node ) { $number = ++$this->footnoteCounter; // Store footnote for later rendering in footnote array $node->number = $number; $this->footnotes[$number] = $node; } /** * Pre process AST * * Performs multiple preprocessing steps on the AST: * * Collect all possible reference targets in the AST to know the actual * destianation for references while decorating. The references are stored * in an internal structure and you may request the actual link by using * the getReferenceTarget() method. * * Aggregate list items into lists. In Wiki there are only list items, which * are aggregated to lists depending on their bullet type. The related list * items are aggregated into one list. * * @param ezcDocumentWikiNode $node * @return void */ protected function preProcessAst( ezcDocumentWikiNode $node ) { switch ( true ) { case $node instanceof ezcDocumentWikiFootnoteNode: $this->addFootnote( $node ); break; } // Recurse into childs to collect reference targets all over the // document. foreach ( $node->nodes as $child ) { $this->preProcessAst( $child ); } } /** * Check for internal footnote reference target * * Returns the target name, when an internal reference target exists and * sets it to used, and false otherwise. * * @param int $number * @param ezcDocumentWikiNode $node * @return ezcDocumentWikiFootnoteNode */ public function hasFootnoteTarget( $number, ezcDocumentWikiNode $node ) { if ( isset( $this->footnotes[$number] ) ) { return $this->footnotes[$number]; } return $this->triggerError( E_WARNING, "Unknown footnote reference target '{$number}'.", null, ( $node !== null ? $node->token->line : null ), ( $node !== null ? $node->token->position : null ) ); } /** * Transform a node tree into a string * * Transform a node tree, with all its subnodes into a string by only * getting the textuual contents from ezcDocumentWikiTextLineNode objects. * * @param ezcDocumentWikiNode $node * @return string */ protected function nodeToString( ezcDocumentWikiNode $node ) { $text = ''; foreach ( $node->nodes as $child ) { if ( ( $child instanceof ezcDocumentWikiTextLineNode ) || ( $child instanceof ezcDocumentWikiLiteralNode ) ) { $text .= $child->token->content; } else { $text .= $this->nodeToString( $child ); } } return $text; } /** * Node list to string * * Extract the contents of a node list and return a single string for the * array of nodes. * * @param array $nodes * @return string */ protected function nodeListToString( array $nodes ) { $text = ''; foreach ( $nodes as $node ) { $text .= $node->token->content; } return $text; } /** * Visit text node * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitText( DOMNode $root, ezcDocumentWikiNode $node ) { $root->appendChild( new DOMText( preg_replace( '(\\s+)', ' ', $node->token->content ) ) ); } /** * Visit children * * Just recurse into node and visit its children, ignoring the actual * node. * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitChildren( DOMNode $root, ezcDocumentWikiNode $node ) { foreach ( $node->nodes as $child ) { $this->visitNode( $root, $child ); } } } ?> * $document = new ezcDocumentCreoleWiki(); * $document->loadString( ' * = Example text = * * Just some exaple paragraph with a heading, some **emphasis** markup and a * [[http://ezcomponents.org|link]].' ); * * $docbook = $document->getAsDocbook(); * echo $docbook->save(); *
* * For the conversion back from docbook to wiki markup, currently only one * converter to creole markup has been implemented. This conversion can be used * like: * * * $docbook = new ezcDocumentDocbook(); * $docbook->loadFile( 'docbook.xml' ); * * $document = new ezcDocumentCreoleWiki(); * $document->createFromDocbook( $docbook ); * echo $document->save(); * * * @package Document * @version //autogen// * @mainclass */ class ezcDocumentCreoleWiki extends ezcDocumentWiki { } ?> content = $content; $this->line = $line; $this->position = $position; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { return null; } } ?> 'visitText', 'ezcDocumentWikiSeparatorNode' => 'visitText', 'ezcDocumentWikiBoldNode' => 'visitEmphasisMarkup', 'ezcDocumentWikiItalicNode' => 'visitEmphasisMarkup', 'ezcDocumentWikiUnderlineNode' => 'visitEmphasisMarkup', 'ezcDocumentWikiTitleNode' => 'visitTitle', 'ezcDocumentWikiLinkNode' => 'visitLink', 'ezcDocumentWikiExternalLinkNode' => 'visitExternalLink', 'ezcDocumentWikiInternalLinkNode' => 'visitExternalLink', 'ezcDocumentWikiInterWikiLinkNode' => 'visitExternalLink', 'ezcDocumentWikiBulletListNode' => 'visitList', 'ezcDocumentWikiEnumeratedListNode' => 'visitList', 'ezcDocumentWikiImageNode' => 'visitImages', 'ezcDocumentWikiLiteralBlockNode' => 'visitLiteralBlock', 'ezcDocumentWikiInlineLiteralNode' => 'visitLiteral', 'ezcDocumentWikiTableRowNode' => 'visitTableRow', 'ezcDocumentWikiTableCellNode' => 'visitTableCell', 'ezcDocumentWikiLineBreakNode' => 'visitLineBreak', 'ezcDocumentWikiParagraphNode' => 'visitParagraph', 'ezcDocumentWikiBlockquoteNode' => 'visitBlockquote', 'ezcDocumentWikiFootnoteNode' => 'visitFootnote', 'ezcDocumentWikiPluginNode' => 'visitPlugin', // Node markup is ignored, because there is no equivalent in docbook 'ezcDocumentWikiDeletedNode' => 'visitChildren', ); /** * Direct mapping of AST node class names to docbook element names. * * @var array */ protected $simpleVisitMapping = array( 'ezcDocumentWikiSectionNode' => 'section', 'ezcDocumentWikiInlineQuoteNode' => 'quote', 'ezcDocumentWikiSuperscriptNode' => 'superscript', 'ezcDocumentWikiSubscriptNode' => 'subscript', 'ezcDocumentWikiMonospaceNode' => 'literal', 'ezcDocumentWikiBulletListItemNode' => 'listitem', 'ezcDocumentWikiEnumeratedListItemNode' => 'listitem', 'ezcDocumentWikiPageBreakNode' => 'beginpage', 'ezcDocumentWikiTableNode' => 'table', ); /** * Array with nodes, which can be ignored during the transformation * process, they only provide additional information during preprocessing. * * @var array */ protected $skipNodes = array(); /** * DOM document * * @var DOMDocument */ protected $document; /** * Docarate Wiki AST * * Visit the Wiki abstract syntax tree. * * @param ezcDocumentWikiDocumentNode $ast * @return mixed */ public function visit( ezcDocumentWikiDocumentNode $ast ) { parent::visit( $ast ); // Create article from AST $imp = new DOMImplementation(); $dtd = $imp->createDocumentType( 'article', '-//OASIS//DTD DocBook XML V4.5//EN', 'http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd' ); $this->document = $imp->createDocument( 'http://docbook.org/ns/docbook', '', $dtd ); $this->document->formatOutput = true; // $root = $this->document->createElement( 'article' ); $root = $this->document->createElementNs( 'http://docbook.org/ns/docbook', 'article' ); $this->document->appendChild( $root ); // Visit all childs of the AST root node. foreach ( $ast->nodes as $node ) { $this->visitNode( $root, $node ); } return $this->document; } /** * Visit single AST node * * Visit a single AST node, may be called for each node found anywhere * as child. The current position in the DOMDocument is passed by a * reference to the current DOMNode, which is operated on. * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitNode( DOMNode $root, ezcDocumentWikiNode $node ) { // Iterate over available visitors and use them to visit the nodes. foreach ( $this->complexVisitMapping as $class => $method ) { if ( $node instanceof $class ) { return $this->$method( $root, $node ); } } // Check if we have a simple class to element name mapping foreach ( $this->simpleVisitMapping as $class => $elementName ) { if ( $node instanceof $class ) { $element = $this->document->createElement( $elementName ); $root->appendChild( $element ); foreach ( $node->nodes as $child ) { $this->visitNode( $element, $child ); } return; } } // Check if you should just ignore the node for rendering foreach ( $this->skipNodes as $class ) { if ( $node instanceof $class ) { return; } } // We could not find any valid visitor. throw new ezcDocumentMissingVisitorException( get_class( $node ), $node->token->line, $node->token->position ); } /** * Visit emphasis markup * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitEmphasisMarkup( DOMNode $root, ezcDocumentWikiNode $node ) { $markup = $this->document->createElement( 'emphasis' ); if ( $node instanceof ezcDocumentWikiBoldNode ) { $markup->setAttribute( 'Role', 'strong' ); } $root->appendChild( $markup ); foreach ( $node->nodes as $child ) { $this->visitNode( $markup, $child ); } } /** * Visit section titles * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitTitle( DOMNode $root, ezcDocumentWikiNode $node ) { $title = $this->document->createElement( 'title' ); $root->appendChild( $title ); foreach ( $node->nodes as $child ) { $this->visitNode( $title, $child ); } } /** * Visit external link node * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitExternalLink( DOMNode $root, ezcDocumentWikiNode $node ) { $link = $this->document->createElement( 'ulink' ); $link->setAttribute( 'url', $node->token->content ); $link->appendChild( new DOMText( $node->token->content ) ); $root->appendChild( $link ); } /** * Visit link node * * Docbook has no support for description of links, so that the description * elements in the AST are omitted. * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitLink( DOMNode $root, ezcDocumentWikiNode $node ) { $link = $this->document->createElement( 'ulink' ); $link->setAttribute( 'url', $linkUrl = $this->nodeListToString( $node->link ) ); $root->appendChild( $link ); if ( $node->nodes === array() ) { $link->appendChild( new DOMText( $linkUrl ) ); } else { foreach ( $node->nodes as $child ) { $this->visitNode( $link, $child ); } } } /** * Visit list * * Ensure stacked lists are created inside another list item. * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitList( DOMNode $root, ezcDocumentWikiNode $node ) { if ( ( $root->tagName === 'itemizedlist' ) || ( $root->tagName === 'orderedlist' ) ) { $listitem = $this->document->createElement( 'listitem' ); $root->appendChild( $listitem ); $root = $listitem; } $list = $this->document->createElement( $node instanceof ezcDocumentWikiBulletListNode ? 'itemizedlist' : 'orderedlist' ); $root->appendChild( $list ); foreach ( $node->nodes as $child ) { $this->visitNode( $list, $child ); } } /** * Is inline node? * * Check if contents of the current node are a inline node * * @param DOMNode $node * @return bool */ protected function isInlineNode( DOMNode $node ) { return in_array( $node->tagName, array( 'para', 'acronym', 'anchor', 'author', 'citation', 'email', 'emphasis', 'footnote', 'footnoteref', 'inlinemediaobject', 'literal', 'quote', 'subscript', 'superscript', 'link', 'ulink', ) ); } /** * Visit images * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitImages( DOMNode $root, ezcDocumentWikiNode $node ) { $media = $this->document->createElement( $this->isInlineNode( $root ) ? 'inlinemediaobject' : 'mediaobject' ); $root->appendChild( $media ); $imageObject = $this->document->createElement( 'imageobject' ); $media->appendChild( $imageObject ); $image = $this->document->createElement( 'imagedata' ); $image->setAttribute( 'fileref', $this->nodeListToString( $node->resource ) ); $imageObject->appendChild( $image ); // Handle optional settings on images if ( $node->title !== array() ) { $text = $this->document->createElement( 'textobject' ); $media->appendChild( $text ); foreach ( $node->title as $child ) { $this->visitNode( $text, $child ); } } if ( $node->width ) { $image->setAttribute( 'width', (int) $node->width ); } if ( $node->height ) { $image->setAttribute( 'depth', (int) $node->height ); } if ( $node->alignement ) { $image->setAttribute( 'align', $node->alignement ); } foreach ( $node->nodes as $child ) { $this->visitNode( $list, $child ); } } /** * Visit literal block * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitLiteralBlock( DOMNode $root, ezcDocumentWikiNode $node ) { $literal = $this->document->createElement( 'literallayout', htmlspecialchars( $node->token->content ) ); $root->appendChild( $literal ); } /** * Visit literal * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitLiteral( DOMNode $root, ezcDocumentWikiNode $node ) { $literal = $this->document->createElement( 'literal', htmlspecialchars( $node->token->content ) ); $root->appendChild( $literal ); } /** * Visit table row * * Visit a table row and decide if it belongs into a tbody or a thead * section. * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitTableRow( DOMNode $root, ezcDocumentWikiNode $node ) { $header = true; foreach ( $node->nodes as $cell ) { $header = $header && $cell->header; } // Get last child element in table if ( !( $last = $root->lastChild ) || ( $last->nodeType !== XML_ELEMENT_NODE ) ) { $last = false; } $type = $header ? 'thead' : 'tbody'; if ( ( $last === false ) || ( $last->tagName !== $type ) ) { $wrapper = $this->document->createElement( $type ); $root->appendChild( $wrapper ); $root = $wrapper; } else { $root = $last; } $row = $this->document->createElement( 'row' ); $root->appendChild( $row ); foreach ( $node->nodes as $child ) { $this->visitNode( $row, $child ); } } /** * Visit table cell * * Visit a table cell and additionally always create an inner paragraph. * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitTableCell( DOMNode $root, ezcDocumentWikiNode $node ) { $cell = $this->document->createElement( 'entry' ); $root->appendChild( $cell ); $this->visitParagraph( $cell, $node ); } /** * Visit line break * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitLineBreak( DOMNode $root, ezcDocumentWikiNode $node ) { $root->appendChild( new DOMText( "\n" ) ); // Mark paragraph, so it will be converted into a literallayout // element. if ( $root->tagName === 'para' ) { $root->setAttribute( 'type', 'literallayout' ); } else { $this->triggerError( E_NOTICE, 'Intentional line break outside of paragraph ignored.', null, $node->token->line, $node->token->position ); } } /** * Visit paragraph * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitParagraph( DOMNode $root, ezcDocumentWikiNode $node ) { $para = $this->document->createElement( 'para' ); $root->appendChild( $para ); foreach ( $node->nodes as $child ) { $this->visitNode( $para, $child ); } // Check if paragraph should be converted into a literalayout section, // because it contains intentional line breaks. This marker is set by // the visitLineBreak() method. if ( $para->hasAttribute( 'type' ) && ( $para->getAttribute( 'type' ) === 'literallayout' ) ) { // Change paragraph into a literallayout section $newPara = $this->document->createElement( 'literallayout' ); $newPara->setAttribute( 'class', 'normal' ); $root->appendChild( $newPara ); // Move all childs to new paragraph foreach ( $para->childNodes as $child ) { $newPara->appendChild( $child->cloneNode( true ) ); } // Remove old paragraph $root->removeChild( $para ); } } /** * Visit blockquote * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitBlockquote( DOMNode $root, ezcDocumentWikiNode $node ) { $blockquote = $this->document->createElement( 'blockquote' ); $root->appendChild( $blockquote ); $para = $this->document->createElement( 'para' ); $blockquote->appendChild( $para ); foreach ( $node->nodes as $child ) { $this->visitNode( $para, $child ); } } /** * Visit footnote * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitFootnote( DOMNode $root, ezcDocumentWikiNode $node ) { $footnote = $this->document->createElement( 'footnote' ); $root->appendChild( $footnote ); $para = $this->document->createElement( 'para' ); $footnote->appendChild( $para ); foreach ( $node->nodes as $child ) { $this->visitNode( $para, $child ); } } /** * Visit plugin * * @param DOMNode $root * @param ezcDocumentWikiNode $node * @return void */ protected function visitPlugin( DOMNode $root, ezcDocumentWikiNode $node ) { $handlerClass = $this->wiki->getPluginHandler( $node->type ); $pluginHandler = new $handlerClass( $this->ast, $this->path, $node ); $pluginHandler->toDocbook( $this->document, $root ); } } ?> line = $token->line; $this->position = $token->position; $this->token = $token; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { return null; } } ?> * $document = new ezcDocumentDokuwikiWiki(); * $document->loadString( ' * = Example text = * * Just some exaple paragraph with a heading, some **emphasis** markup and a * [[http://ezcomponents.org|link]].' ); * * $docbook = $document->getAsDocbook(); * echo $docbook->save(); * * * A converter for the conversion from docbook back to dokuwiki wiki markup * has not yet been implemented. * * @package Document * @version //autogen// * @mainclass */ class ezcDocumentDokuwikiWiki extends ezcDocumentWiki { /** * Construct RST document. * * @ignore * @param ezcDocumentWikiOptions $options * @return void */ public function __construct( ezcDocumentWikiOptions $options = null ) { parent::__construct( $options === null ? new ezcDocumentWikiOptions() : $options ); $this->options->tokenizer = new ezcDocumentWikiDokuwikiTokenizer(); } /** * Create document from docbook document * * A document of the docbook format is provided and the internal document * structure should be created out of this. * * This method is required for all formats to have one central format, so * that each format can be compiled into each other format using docbook as * an intermediate format. * * You may of course just call an existing converter for this conversion. * * @param ezcDocumentDocbook $document * @return void */ public function createFromDocbook( ezcDocumentDocbook $document ) { throw new ezcDocumentMissingVisitorException( get_class( $document ) ); } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> level = $properties['level']; return $token; } } ?> type = $properties['type']; $token->parameters = $properties['parameters']; $token->text = $properties['text']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> indentation = $properties['indentation']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> level = $properties['level']; return $token; } } ?> indentation = $properties['indentation']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> indentation = $properties['indentation']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> width = $properties['width']; $token->height = $properties['height']; $token->alignement = $properties['alignement']; return $token; } } ?> value = $properties['value']; return $token; } } ?> * $document = new ezcDocumentConfluenceWiki(); * $document->loadString( ' * = Example text = * * Just some exaple paragraph with a heading, some **emphasis** markup and a * [[http://ezcomponents.org|link]].' ); * * $docbook = $document->getAsDocbook(); * echo $docbook->save(); * * * A converter for the conversion from docbook back to confluence wiki markup * has not yet been implemented. * * @package Document * @version //autogen// * @mainclass */ class ezcDocumentConfluenceWiki extends ezcDocumentWiki { /** * Construct RST document. * * @ignore * @param ezcDocumentWikiOptions $options * @return void */ public function __construct( ezcDocumentWikiOptions $options = null ) { parent::__construct( $options === null ? new ezcDocumentWikiOptions() : $options ); $this->options->tokenizer = new ezcDocumentWikiConfluenceTokenizer(); } /** * Create document from docbook document * * A document of the docbook format is provided and the internal document * structure should be created out of this. * * This method is required for all formats to have one central format, so * that each format can be compiled into each other format using docbook as * an intermediate format. * * You may of course just call an existing converter for this conversion. * * @param ezcDocumentDocbook $document * @return void */ public function createFromDocbook( ezcDocumentDocbook $document ) { throw new ezcDocumentMissingVisitorException( get_class( $document ) ); } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> level = $token->level; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { $nodeClass = __CLASS__; $node = new $nodeClass( $properties['token'] ); $node->nodes = $properties['nodes']; return $node; } } ?> type = $token->type; $this->parameters = $token->parameters; $this->text = $token->text; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { $nodeClass = __CLASS__; $node = new $nodeClass( $properties['token'] ); $node->nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> level = $token->indentation; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { $nodeClass = __CLASS__; $node = new $nodeClass( $properties['token'] ); $node->nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; $node->resource = $properties['resource']; $node->title = $properties['title']; $node->alignement = $properties['alignement']; $node->width = $properties['width']; $node->height = $properties['height']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> level = $token instanceof ezcDocumentWikiTitleToken ? $token->level : 0; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { $nodeClass = __CLASS__; $node = new $nodeClass( $properties['token'] ); $node->nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> header = $token instanceof ezcDocumentWikiTableHeaderToken; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { $nodeClass = __CLASS__; $node = new $nodeClass( $properties['token'] ); $node->nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> level = $token->indentation; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { $nodeClass = __CLASS__; $node = new $nodeClass( $properties['token'] ); $node->nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; $node->link = $properties['link']; $node->title = $properties['title']; $node->description = $properties['description']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> level = $token->indentation; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { $nodeClass = __CLASS__; $node = new $nodeClass( $properties['token'] ); $node->nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> level = $token->level; } } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { $nodeClass = __CLASS__; $node = new $nodeClass( $properties['token'] ); $node->nodes = $properties['nodes']; return $node; } } ?> level = $token->indentation; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { $nodeClass = __CLASS__; $node = new $nodeClass( $properties['token'] ); $node->nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> plugins[strtolower( $name )] = (string) $class; } /** * Get plugin handler * * Get plugin handler class name for the specified name. * * @param string $name * @return string */ public function getPluginHandler( $name ) { $name = strtolower( $name ); if ( !isset( $this->plugins[$name] ) ) { throw new ezcDocumentBBCodeMissingPluginHandlerException( $name ); } return $this->plugins[$name]; } /** * Create document from input string * * Create a document of the current type handler class and parse it into a * usable internal structure. * * @param string $string * @return void */ public function loadString( $string ) { $this->contents = $string; } /** * Return document compiled to the docbook format * * The internal document structure is compiled to the docbook format and * the resulting docbook document is returned. * * This method is required for all formats to have one central format, so * that each format can be compiled into each other format using docbook as * an intermediate format. * * You may of course just call an existing converter for this conversion. * * @return ezcDocumentDocbook */ public function getAsDocbook() { $tokenizer = new ezcDocumentBBCodeTokenizer(); $parser = new ezcDocumentBBCodeParser(); $parser->options->errorReporting = $this->options->errorReporting; $this->ast = $parser->parse( $tokenizer->tokenizeString( $this->contents ) ); $document = new ezcDocumentDocbook(); $visitor = new ezcDocumentBBCodeDocbookVisitor( $this, $this->path ); $document->setDomDocument( $visitor->visit( $this->ast, $this->path ) ); $document->setPath( $this->path ); // Merge errors from converter $this->errors = array_merge( $this->errors, $parser->getErrors(), $visitor->getErrors() ); return $document; } /** * Create document from docbook document * * A document of the docbook format is provided and the internal document * structure should be created out of this. * * This method is required for all formats to have one central format, so * that each format can be compiled into each other format using docbook as * an intermediate format. * * You may of course just call an existing converter for this conversion. * * @param ezcDocumentDocbook $document * @return void */ public function createFromDocbook( ezcDocumentDocbook $document ) { if ( $this->options->validate && $document->validateString( $document ) !== true ) { $this->triggerError( E_WARNING, "You try to convert an invalid docbook document. This may lead to invalid output." ); } $this->path = $document->getPath(); $converter = new ezcDocumentDocbookToBBCodeConverter(); $converter->options->errorReporting = $this->options->errorReporting; $this->contents = $converter->convert( $document )->save(); } /** * Validate the input file * * Validate the input file against the specification of the current * document format. * * Returns true, if the validation succeded, and an array with * ezcDocumentValidationError objects otherwise. * * @param string $file * @return mixed */ public function validateFile( $file ) { return $this->validateString( file_get_contents( $file ) ); } /** * Validate the input string * * Validate the input string against the specification of the current * document format. * * Returns true, if the validation succeded, and an array with * ezcDocumentValidationError objects otherwise. * * @param string $string * @return mixed */ public function validateString( $string ) { $tokenizer = new ezcDocumentBBCodeTokenizer(); $parser = new ezcDocumentBBCodeParser(); // Only halt on parse errors, and collect all other errors. $parser->options->errorReporting = E_PARSE; $errors = array(); $ast = null; try { // Try to parse the document and keep the parse tree for evetual // checking for decoration errors $ast = $parser->parse( $tokenizer->tokenizeString( $string ) ); } catch ( ezcDocumentParserException $e ) { $errors[] = $e; } // Get errors and notices from parsed document $errors = array_merge( $errors, $parser->errors ); // If we had no parse error until now, we also try to decorate the // document, which may leed to another class of errors. if ( $ast !== null ) { $oldErrorReporting = $this->options->errorReporting; $this->options->errorReporting = E_PARSE; try { $visitor = new ezcDocumentBBCodeDocbookVisitor( $this, $this->path ); $visitor->visit( $ast, $this->path ); // Get errors and notices from parsed document $errors = array_merge( $errors, $visitor->getErrors() ); } catch ( ezcDocumentVisitException $e ) { $errors[] = $e; } // Reset error reporting $this->options->errorReporting = $oldErrorReporting; } if ( count( $errors ) === 0 ) { // If no problem could be found, jsut return true return true; } else { // Transform aggregated errors into validation errors foreach ( $errors as $nr => $error ) { $errors[$nr] = ezcDocumentValidationError::createFromException( $error ); } return $errors; } } /** * Return document as string * * Serialize the document to a string an return it. * * @return string */ public function save() { return $this->contents; } } ?> * array( * WHITESPACE => array( * reductionMethod, * ... * ), * ... * ) * * * [1] http://en.bbcodepedia.org/bbcode/Pumping_lemma_for_context-free_languages * * @var array */ protected $shifts = array( 'ezcDocumentBBCodeTagOpenToken' => 'shiftOpeningToken', 'ezcDocumentBBCodeTagCloseToken' => 'shiftClosingToken', 'ezcDocumentBBCodeListItemToken' => 'shiftListItemToken', 'ezcDocumentBBCodeWhitespaceToken' => 'shiftWhitespaceToken', 'ezcDocumentBBCodeTextLineToken' => 'shiftTextToken', 'ezcDocumentBBCodeLiteralBlockToken' => 'shiftLiteralBlockToken', 'ezcDocumentBBCodeNewLineToken' => 'shiftNewLineToken', 'ezcDocumentBBCodeEndOfFileToken' => 'shiftEndOfFileToken', ); /** * Array containing simplified reduce ruleset. * * We cannot express the BBCode syntax as a usual grammar using a BNF. This * structure implements a pseudo grammar by assigning a number of callbacks * for internal methods implementing reduction rules for a detected syntax * element. * * * array( * ezcDocumentBBCodeNode::DOCUMENT => 'reduceDocument' * ... * ) * * * @var array */ protected $reductions = array( 'ezcDocumentBBCodeClosingTagNode' => array( 'reduceTags', ), 'ezcDocumentBBCodeParagraphNode' => array( 'reduceParagraph', ), 'ezcDocumentBBCodeDocumentNode' => array( 'reduceDocument', ), 'ezcDocumentBBCodeListItemNode' => array( 'reduceListItem', ), 'ezcDocumentBBCodeListEndNode' => array( 'reduceList', ), ); /** * Contains a list of detected syntax elements. * * At the end of a successfull parsing process this should only contain one * document syntax element. During the process it may contain a list of * elements, which are up to reduction. * * Each element in the stack has to be an object extending from * ezcDocumentRstNode, which may again contain any amount such objects. * This way an abstract syntax tree is constructed. * * @var array */ protected $documentStack = array(); /** * Parse token stream. * * Parse an array of ezcDocumentBBCodeToken objects into a bbcode abstract * syntax tree. * * @param array $tokens * @return ezcDocumentBBCodeDocumentNode */ public function parse( array $tokens ) { /* DEBUG echo "\n\nStart parser\n============\n\n"; // /DEBUG */ while ( ( $token = array_shift( $tokens ) ) !== null ) { /* DEBUG echo "[T] ({$token->line}:{$token->position}) Token: " . get_class( $token ) . " at {$token->line}:{$token->position}.\n"; // /DEBUG */ // First shift given token by the defined reduction methods $node = false; foreach ( $this->shifts as $class => $method ) { if ( $token instanceof $class ) { /* DEBUG echo " - Handle token with ->$method\n"; // /DEBUG */ // Try to shift the token with current method if ( ( $node = $this->$method( $token, $tokens ) ) !== false ) { break; } } } // If the node is still null there was not matching shift rule. if ( $node === false ) { return $this->triggerError( E_PARSE, "Could not find shift rule for token '" . get_class( $token ) . "'.", $token->line, $token->position ); } // Token did not result in any node, it should just be ignored. if ( $node === null ) { continue; } /* DEBUG echo "[N] Node: " . get_class( $node ) . " at {$node->token->line}:{$node->token->position}.\n"; // /DEBUG */ // Apply reductions to shifted node do { foreach ( $this->reductions as $class => $methods ) { if ( $node instanceof $class ) { foreach ( $methods as $method ) { /* DEBUG echo " - Handle node with ->$method\n"; // /DEBUG */ if ( ( $node = $this->$method( $node ) ) === null ) { /* DEBUG echo " - Reduced.\n"; // /DEBUG */ // The node has been handled, exit loop. break 3; } // Check if the node class has changed and rehandle // node in this case. if ( !$node instanceof $class ) { /* DEBUG echo " - Try subsequent reductions...\n"; // /DEBUG */ continue 2; } } } } } while ( false ); // Check if reductions have been applied, but still returned a // node, just add to document stack in this case. if ( $node !== null ) { /* DEBUG echo " => Prepend " . get_class( $node ) . " to document stack.\n"; // /DEBUG */ array_unshift( $this->documentStack, $node ); } } // Check if we successfully reduced the document stack if ( ( count( $this->documentStack ) !== 1 ) || ( !( $document = reset( $this->documentStack ) ) instanceof ezcDocumentBBCodeDocumentNode ) ) { $node = isset( $document ) ? $document : reset( $this->documentStack ); $this->triggerError( E_PARSE, 'Expected end of file, got: ' . get_class( $this->documentStack[1] ) . ".", $this->documentStack[1]->token->line, $this->documentStack[1]->token->position ); } return $document; } /** * Shift list item token * * List item tokens indicate a new list item. Just put them on the stack, * they will be aggregated later. * * @param ezcDocumentBBCodeToken $token * @param array $tokens * @return mixed */ protected function shiftListItemToken( ezcDocumentBBCodeToken $token, array &$tokens ) { /* DEBUG echo " - Shift list item.\n"; // /DEBUG */ return new ezcDocumentBBCodeListItemNode( $token ); } /** * Shift tag opening token * * Opening tags mean that the following contents will be aggregated, once a * matching closing tag is found. Is just shifted to the document stack. * * @param ezcDocumentBBCodeToken $token * @param array $tokens * @return mixed */ protected function shiftOpeningToken( ezcDocumentBBCodeToken $token, array &$tokens ) { if ( $token->content !== 'list' ) { /* DEBUG echo " - Shift opening token {$token->content}.\n"; // /DEBUG */ return new ezcDocumentBBCodeTagNode( $token ); } switch ( true ) { case $token->parameters === null: /* DEBUG echo " - Shift bullet list.\n"; // /DEBUG */ return new ezcDocumentBBCodeBulletListNode( $token ); default: /* DEBUG echo " - Shift enumerated list.\n"; // /DEBUG */ return new ezcDocumentBBCodeEnumeratedListNode( $token ); } } /** * Shift tag clsoing token * * Closing tags mean that the preceeding contents will be aggregated, once a * matching opening tag is found. Is just shifted to the document stack, * and the appropriate reduce call will follow right away. * * @param ezcDocumentBBCodeToken $token * @param array $tokens * @return mixed */ protected function shiftClosingToken( ezcDocumentBBCodeToken $token, array &$tokens ) { if ( $token->content === 'list' ) { /* DEBUG echo " - Shift list end node.\n"; // /DEBUG */ return new ezcDocumentBBCodeListEndNode( $token ); } /* DEBUG echo " - Shift closing token {$token->content}.\n"; // /DEBUG */ return new ezcDocumentBBCodeClosingTagNode( $token ); } /** * Shift whitespace token. * * Shift whitespace tokens. Whitespaces are only considered significant, if * the prior token was not a block level element. * * @param ezcDocumentBBCodeToken $token * @param array $tokens * @return mixed */ protected function shiftWhitespaceToken( ezcDocumentBBCodeToken $token, array &$tokens ) { if ( isset( $this->documentStack[0] ) && ( !$this->documentStack[0] instanceof ezcDocumentBBCodeBlockLevelNode ) ) { /* DEBUG echo " - Shift whitespace text node.\n"; // /DEBUG */ return new ezcDocumentBBCodeTextNode( $token ); } /* DEBUG echo " - Ignore whitespace node.\n"; // /DEBUG */ return null; } /** * Shift text token. * * @param ezcDocumentBBCodeToken $token * @param array $tokens * @return mixed */ protected function shiftTextToken( ezcDocumentBBCodeToken $token, array &$tokens ) { /* DEBUG echo " - Shift text node.\n"; // /DEBUG */ return new ezcDocumentBBCodeTextNode( $token ); } /** * Shift literal block token * * Literal blocks are just a chunk of code or similar, where the token can * jsut be converted into an apropriate node. * * @param ezcDocumentBBCodeToken $token * @param array $tokens * @return mixed */ protected function shiftLiteralBlockToken( ezcDocumentBBCodeToken $token, array &$tokens ) { if ( isset( $this->documentStack[0] ) && ( $this->documentStack[0] instanceof ezcDocumentBBCodeParagraphNode ) && isset( $tokens[0] ) && ( $tokens[0] instanceof ezcDocumentBBCodeNewLineToken ) ) { // Remove following new line tokens. do { array_shift( $tokens ); } while ( isset( $tokens[0] ) && ( ( $tokens[0] instanceof ezcDocumentBBCodeNewlineToken ) || ( $tokens[0] instanceof ezcDocumentBBCodeWhitespaceToken ) ) ); /* DEBUG echo " - Shift literal block node.\n"; // /DEBUG */ return new ezcDocumentBBCodeLiteralBlockNode( $token ); } else { /* DEBUG echo " - Shift inline literal node.\n"; // /DEBUG */ return new ezcDocumentBBCodeInlineLiteralNode( $token ); } } /** * Shift new line token. * * Double new lines are considered as paragraphs. All other new lines are * just shifted as single whitespace text nodes. * * @param ezcDocumentBBCodeToken $token * @param array $tokens * @return mixed */ protected function shiftNewLineToken( ezcDocumentBBCodeToken $token, array &$tokens ) { while ( isset( $tokens[0] ) && ( $tokens[0] instanceof ezcDocumentBBCodeWhitespaceToken ) ) { array_shift( $tokens ); } if ( isset( $tokens[0] ) && ( $tokens[0] instanceof ezcDocumentBBCodeNewlineToken ) ) { do { array_shift( $tokens ); } while ( isset( $tokens[0] ) && ( ( $tokens[0] instanceof ezcDocumentBBCodeNewlineToken ) || ( $tokens[0] instanceof ezcDocumentBBCodeWhitespaceToken ) ) ); /* DEBUG echo " - Shift paragraph node.\n"; // /DEBUG */ return new ezcDocumentBBCodeParagraphNode( $token ); } elseif ( isset( $this->documentStack[0] ) && ( !$this->documentStack[0] instanceof ezcDocumentBBCodeBlockLevelNode ) ) { /* DEBUG echo " - Shift newline as whitespace node.\n"; // /DEBUG */ return new ezcDocumentBBCodeTextNode( $token ); } /* DEBUG echo " - Ignore whitespace node.\n"; // /DEBUG */ return null; } /** * Shift EOF token. * * Shift End-Of-File token. We reached the end of the document, and * therefore shift a document node onto the stack. * * @param ezcDocumentBBCodeToken $token * @param array $tokens * @return mixed */ protected function shiftEndOfFileToken( ezcDocumentBBCodeToken $token, array &$tokens ) { /* DEBUG echo " - Shift document node.\n"; // /DEBUG */ return new ezcDocumentBBCodeDocumentNode( $token ); } /** * Reduce tags. * * Locates the matching opening tag for a closing tag and reduces the * contents found on the way back. * * @param ezcDocumentBBCodeClosingTagNode $node * @return mixed */ protected function reduceTags( ezcDocumentBBCodeClosingTagNode $node ) { $nodes = array(); while ( isset( $this->documentStack[0] ) && ( ( !$this->documentStack[0] instanceof ezcDocumentBBCodeTagNode ) || ( $this->documentStack[0]->token->content !== $node->token->content ) ) ) { $nodes[] = $child = array_shift( $this->documentStack ); if ( ( $child instanceof ezcDocumentBBCodeTagNode ) && ( !count( $child->nodes ) ) ) { return $this->triggerError( E_PARSE, "Opening tag, without matching closing tag found: '" . $child->token->content . "'.", $child->token->line, $child->token->position ); } if ( $child instanceof ezcDocumentBBCodeClosingTagNode ) { return $this->triggerError( E_PARSE, "Closing tag, without matching opening tag found: '" . $child->token->content . "'.", $child->token->line, $child->token->position ); } } if ( ( !$this->documentStack[0] instanceof ezcDocumentBBCodeTagNode ) || ( $this->documentStack[0]->token->content !== $node->token->content ) ) { return $this->triggerError( E_PARSE, "Closing tag, without matching opening tag found: '" . $node->token->content . "'.", $node->token->line, $node->token->position ); } $node = array_shift( $this->documentStack ); $node->nodes = array_reverse( $nodes ); return $node; } /** * Reduce list items. * * Aggregates list items and puts them into a found list. * * @param ezcDocumentBBCodeParagraphNode $node * @return mixed */ protected function reduceListItem( ezcDocumentBBCodeNode $node ) { $nodes = array(); while ( isset( $this->documentStack[0] ) && ( !$this->documentStack[0] instanceof ezcDocumentBBCodeListItemNode ) && ( ( !$this->documentStack[0] instanceof ezcDocumentBBCodeListNode ) || ( ( $this->documentStack[0] instanceof ezcDocumentBBCodeListNode ) && ( count( $this->documentStack[0]->nodes ) ) ) ) ) { $nodes[] = $child = array_shift( $this->documentStack ); if ( ( $child instanceof ezcDocumentBBCodeTagNode ) && ( !count( $child->nodes ) ) ) { return $this->triggerError( E_PARSE, "Opening tag, without matching closing tag found: '" . $child->token->content . "'.", $child->token->line, $child->token->position ); } if ( $child instanceof ezcDocumentBBCodeClosingTagNode ) { return $this->triggerError( E_PARSE, "Closing tag, without matching opening tag found: '" . $child->token->content . "'.", $child->token->line, $child->token->position ); } } if ( !isset( $this->documentStack[0] ) ) { return $this->triggerError( E_PARSE, "Missing list item node.", $child->token->line, $child->token->position ); } // Wrap non-block-level nodes into paragraphs $wrapped = array(); $temp = array(); foreach ( $nodes as $child ) { if ( !$child instanceof ezcDocumentBBCodeBlockLevelNode ) { $temp[] = $child; } elseif ( count( $temp ) ) { $wrapped[] = $para = new ezcDocumentBBCodeParagraphNode( $temp[0]->token ); $para->nodes = array_reverse( $temp ); $temp = array(); $wrapped[] = $child; } else { $wrapped[] = $child; } } if ( count( $temp ) ) { $wrapped[] = $para = new ezcDocumentBBCodeParagraphNode( $temp[0]->token ); $para->nodes = array_reverse( $temp ); } if ( $this->documentStack[0] instanceof ezcDocumentBBCodeListItemNode ) { $this->documentStack[0]->nodes = array_reverse( $wrapped ); } return $node; } /** * Reduce list. * * Aggregates list items and puts them into a found list. * * @param ezcDocumentBBCodeParagraphNode $node * @return mixed */ protected function reduceList( ezcDocumentBBCodeNode $node ) { $this->reduceListItem( $node ); $nodes = array(); while ( isset( $this->documentStack[0] ) && ( $this->documentStack[0] instanceof ezcDocumentBBCodeListItemNode ) ) { $nodes[] = array_shift( $this->documentStack ); } if ( !isset( $this->documentStack[0] ) || ( !$this->documentStack[0] instanceof ezcDocumentBBCodeListNode ) ) { return $this->triggerError( E_PARSE, "Missing list start node.", $child->token->line, $child->token->position ); } $this->documentStack[0]->nodes = array_reverse( $nodes ); return null; } /** * Reduce paragraph. * * Paragraphs are reduce with all inline tokens, which have been added to * the document stack before. If there are no inline nodes, the paragraph * will be ommitted. * * @param ezcDocumentBBCodeParagraphNode $node * @return mixed */ protected function reduceParagraph( ezcDocumentBBCodeParagraphNode $node ) { $nodes = array(); while ( isset( $this->documentStack[0] ) && ( !$this->documentStack[0] instanceof ezcDocumentBBCodeParagraphNode ) && ( !$this->documentStack[0] instanceof ezcDocumentBBCodeListNode ) && ( !$this->documentStack[0] instanceof ezcDocumentBBCodeLiteralBlockNode ) ) { $nodes[] = $child = array_shift( $this->documentStack ); if ( ( $child instanceof ezcDocumentBBCodeTagNode ) && ( !count( $child->nodes ) ) ) { return $this->triggerError( E_PARSE, "Opening tag, without matching closing tag found: '" . $child->token->content . "'.", $child->token->line, $child->token->position ); } if ( $child instanceof ezcDocumentBBCodeClosingTagNode ) { return $this->triggerError( E_PARSE, "Closing tag, without matching opening tag found: '" . $child->token->content . "'.", $child->token->line, $child->token->position ); } } // Omit empty paragraphs if ( !count( $nodes ) ) { return null; } $node->nodes = array_reverse( $nodes ); return $node; } /** * Reduce prior sections, if a new section has been found. * * If a new section has been found all sections with a higher depth level * can be closed, and all items fitting into sections may be aggregated by * the respective sections as well. * * @param ezcDocumentBBCodeDocumentNode $node */ protected function reduceDocument( ezcDocumentBBCodeDocumentNode $node ) { $nodes = array(); while ( isset( $this->documentStack[0] ) && ( ( $this->documentStack[0] instanceof ezcDocumentBBCodeParagraphNode ) || ( $this->documentStack[0] instanceof ezcDocumentBBCodeListNode ) || ( $this->documentStack[0] instanceof ezcDocumentBBCodeLiteralBlockNode ) ) ) { $nodes[] = array_shift( $this->documentStack ); } $node->nodes = array_reverse( $nodes ); return $node; } } ?> nodes as $child ) { if ( $child instanceof ezcDocumentBBCodeTextNode ) { $text .= $child->token->content; } elseif ( is_array( $child->nodes ) ) { $text .= $this->getText( $child ); } } return $text; } } ?> * array( * array( * 'class' => Class name of token, * 'match' => Regular expression to match, * ), * ... * ) * * * The array is evaluated in the given order, until one of the regular * expressions match. The regular expression should have at least one named * match (?P ... ), with the name "value", which will be assigned to the * token, created form the given class name, as its content. The matched * contents will be removed from the beginning of the string. * Optionally a second named match, called "match", may be used inside the * regular expression. If so, only the contents inside this match will be * removed from the beginning of the string. This enables you to perform a * trivial lookahead inside the tokenizer. * * If no expression matches, an exception will be thrown. * * @package Document * @version //autogen// */ class ezcDocumentBBCodeTokenizer { /** * List with tokens and a regular expression matching the given token. * * The tokens are matched in the given order. * * @var array */ protected $tokens = array(); /** * Common whitespace characters. The vertical tab is excluded, because it * causes strange problems with PCRE. */ const WHITESPACE_CHARS = '[\\x20\\t]'; /** * Characters ending a pure text section. */ const TEXT_END_CHARS = '\\[\\]\\r\\n'; /** * Special characters, which do have some special meaaning and though may * not have been matched otherwise. */ const SPECIAL_CHARS = '\\[\\]'; /** * Construct tokenizer * * Create token array with regular repression matching the respective * token. * * @return void */ public function __construct() { $this->tokens = array( // Match tokens which require to be at the start of a line before // matching the actual newlines, because they are the indicator for // line starts. array( 'class' => 'ezcDocumentBBCodeLiteralBlockToken', 'match' => '(\\A(?P\\[code(?:=[^\\]]+)?\\](?P.+)\\[/code\\]))SUs' ), array( 'class' => 'ezcDocumentBBCodeListItemToken', 'match' => '(\\A(?P\\[\\*\\]))SUs' ), array( 'class' => 'ezcDocumentBBCodeTagOpenToken', 'match' => '(\\A(?P\\[(?P[A-Za-z]+(?:=[^\\]]+)?)\\]))SUs' ), array( 'class' => 'ezcDocumentBBCodeTagCloseToken', 'match' => '(\\A(?P\\[/(?P[A-Za-z]+)\\]))SUs' ), // Whitespaces array( 'class' => 'ezcDocumentBBCodeNewLineToken', 'match' => '(\\A' . self::WHITESPACE_CHARS . '*(?P\\r\\n|\\r|\\n))S' ), array( 'class' => 'ezcDocumentBBCodeWhitespaceToken', 'match' => '(\\A(?P' . self::WHITESPACE_CHARS . '+))S' ), array( 'class' => 'ezcDocumentBBCodeEndOfFileToken', 'match' => '(\\A(?P\\x0c))S' ), // Escape character array( 'class' => 'ezcDocumentBBCodeEscapeCharacterToken', 'match' => '(\\A(?P~))S' ), // Match text except array( 'class' => 'ezcDocumentBBCodeTextLineToken', 'match' => '(\\A(?P[^' . self::TEXT_END_CHARS . ']+))S' ), // Match all special characters, which are not valid textual chars, // but do not have been matched by any other expression. array( 'class' => 'ezcDocumentBBCodeSpecialCharsToken', 'match' => '(\\A(?P([' . self::SPECIAL_CHARS . '])\\2*))S' ), ); } /** * Tokenize the given file * * The method tries to tokenize the passed files and returns an array of * ezcDocumentBBCodeToken struct on succes, or throws a * ezcDocumentTokenizerException, if something could not be matched by any * token. * * @param string $file * @return array */ public function tokenizeFile( $file ) { if ( !file_exists( $file ) || !is_readable( $file ) ) { throw new ezcBaseFileNotFoundException( $file ); } return $this->tokenizeString( file_get_contents( $file ) ); } /** * Convert tabs to spaces * * Convert all tabs to spaces, as defined in: * http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#whitespace * * @param ezcDocumentBBCodeToken $token * @return void */ protected function convertTabs( ezcDocumentBBCodeToken $token ) { while ( ( $position = strpos( $token->content, "\t" ) ) !== false ) { $token->content = substr( $token->content, 0, $position ) . str_repeat( ' ', 9 - ( ( $position + $token->position ) % 8 ) ) . substr( $token->content, $position + 1 ); } } /** * Tokenize the given string * * The method tries to tokenize the passed strings and returns an array of * ezcDocumentBBCodeToken struct on succes, or throws a * ezcDocumentTokenizerException, if something could not be matched by any * token. * * @param string $string * @return array */ public function tokenizeString( $string ) { $line = 1; $position = 1; $tokens = array(); // Normalize newlines $string = preg_replace( '([\x20\\t]*(?:\\r\\n|\\r|\\n))', "\n", $string ); while ( strlen( $string ) > 0 ) { foreach ( $this->tokens as $match ) { if ( preg_match( $match['match'], $string, $matches ) ) { // If the first part of the match is a // newline, add a respective token to the // stack. if ( ( $matches[0][0] === "\n" ) && ( $match['class'] !== 'ezcDocumentBBCodeNewLineToken' ) ) { $tokens[] = new ezcDocumentBBCodeNewLineToken( $matches[0][0], $line, $position ); ++$line; $position = 0; } // A token matched, so add the matched token to the token // list and update all variables. $class = $match['class']; $newToken = new $class( ( isset( $matches['value'] ) ? $matches['value'] : null ), $line, $position ); $match = isset( $matches['match'] ) ? $matches['match'] : $matches[0]; // Removed matched stuff from input string $string = substr( $string, $length = strlen( $match ) ); // On a newline token reset the line position and increase the line value if ( $newToken instanceof ezcDocumentBBCodeNewLineToken ) { ++$line; $position = 0; } else { // Otherwise still update the line // value, when there is at minimum // one newline in the match. This may // lead to a false position value. if ( ( $newLines = substr_count( $match, "\n" ) ) > 0 ) { $line += $newLines; $position = 0; } } // Convert tabs to spaces for whitespace tokens if ( $newToken instanceof ezcDocumentBBCodeWhitespaceToken ) { $this->convertTabs( $newToken ); } // If we found an explicit EOF token, just exit the parsing process. if ( $newToken instanceof ezcDocumentBBCodeEndOfFileToken ) { break 2; } // Add token to extracted token list $tokens[] = $newToken; // Update position, not before converting tabs to spaces. $position += ( $newToken instanceof ezcDocumentBBCodeNewLineToken ) ? 1 : strlen( $newToken->content ); // Restart the while loop, because we matched a token and // can retry with shortened string. continue 2; } } // None of the token definitions matched the input string. We throw // an exception with the position of the content in the input // string and the contents we could not match. // // This should never been thrown, but it is hard to prove that // there is nothing which is not matched by the regualr expressions // above. throw new ezcDocumentBBCodeTokenizerException( $line, $position, $string ); } // Finally append ainother newline token and a end of file token, to // make parsing the end easier. $tokens[] = new ezcDocumentBBCodeNewLineToken( "\n", $line, $position ); $tokens[] = new ezcDocumentBBCodeNewLineToken( "\n", $line, $position ); $tokens[] = new ezcDocumentBBCodeEndOfFileToken( null, $line, $position ); return $tokens; } } ?> nodes as $child ) { $visitor->visitNode( $root, $child ); } } } ?> ownerDocument->createElement( 'inlinemediaobject' ); $root->appendChild( $object ); $image = $root->ownerDocument->createElement( 'imageobject' ); $object->appendChild( $image ); $data = $root->ownerDocument->createElement( 'imagedata' ); $data->setAttribute( 'fileref', $this->getText( $node ) ); $image->appendChild( $data ); } } ?> token->parameters !== null ) { // The actual URL is a parameter $url = $root->ownerDocument->createElement( 'ulink' ); $url->setAttribute( 'url', 'mailto:' . $node->token->parameters ); $root->appendChild( $url ); foreach ( $node->nodes as $child ) { $visitor->visitNode( $url, $child ); } } else { // The URL is the contained text of the link $url = $root->ownerDocument->createElement( 'ulink' ); $root->appendChild( $url ); foreach ( $node->nodes as $child ) { $visitor->visitNode( $url, $child ); } $url->setAttribute( 'url', 'mailto:' . $url->textContent ); } } } ?> ownerDocument->createElement( 'blockquote' ); $root->appendChild( $quote ); $attribution = null; if ( !empty( $node->token->parameters ) ) { if ( !preg_match( '(^"(?P.*)$")', $node->token->parameters, $match ) ) { $visitor->triggerError( E_NOTICE, 'Attribution is required to be set in quotes.', $node->token->line, $node->token->position ); $attribution = $node->token->parameters; } else { $attribution = $match['attribution']; } } if ( $attribution ) { $attribution = $root->ownerDocument->createElement( 'attribution', htmlspecialchars( $attribution ) ); $quote->appendChild( $attribution ); } $para = $root->ownerDocument->createElement( 'para' ); $quote->appendChild( $para ); foreach ( $node->nodes as $child ) { $visitor->visitNode( $para, $child ); } } } ?> ownerDocument->createElement( 'emphasis' ); if ( strtolower( $node->token->content ) === 'b' ) { $markup->setAttribute( 'Role', 'strong' ); } $root->appendChild( $markup ); foreach ( $node->nodes as $child ) { $visitor->visitNode( $markup, $child ); } } } ?> token->parameters !== null ) { // The actual URL is a parameter $url = $root->ownerDocument->createElement( 'ulink' ); $url->setAttribute( 'url', $node->token->parameters ); $root->appendChild( $url ); foreach ( $node->nodes as $child ) { $visitor->visitNode( $url, $child ); } } else { // The URL is the contained text of the link $url = $root->ownerDocument->createElement( 'ulink' ); $root->appendChild( $url ); foreach ( $node->nodes as $child ) { $visitor->visitNode( $url, $child ); } $url->setAttribute( 'url', $url->textContent ); } } } ?> bbcode = $document; $this->path = $path; } /** * Trigger visitor error * * Emit a vistitor error, and convert it to an exception depending on the * error reporting settings. * * @param int $level * @param string $message * @param string $file * @param int $line * @param int $position * @return void */ public function triggerError( $level, $message, $file = null, $line = null, $position = null ) { if ( $level & $this->bbcode->options->errorReporting ) { throw new ezcDocumentVisitException( $level, $message, $file, $line, $position ); } else { // If the error should not been reported, we aggregate it to maybe // display it later. $this->errors[] = new ezcDocumentVisitException( $level, $message, $file, $line, $position ); } } /** * Return list of errors occured during visiting the document. * * May be an empty array, if on errors occured, or a list of * ezcDocumentVisitException objects. * * @return array */ public function getErrors() { return $this->errors; } /** * Docarate BBCode AST * * Visit the BBCode abstract syntax tree. * * @param ezcDocumentBBCodeDocumentNode $ast * @return mixed */ public function visit( ezcDocumentBBCodeDocumentNode $ast ) { $this->ast = $ast; } /** * Visit text node * * @param DOMNode $root * @param ezcDocumentBBCodeNode $node * @return void */ protected function visitText( DOMNode $root, ezcDocumentBBCodeNode $node ) { $root->appendChild( new DOMText( preg_replace( '(\\s+)', ' ', $node->token->content ) ) ); } } ?> content = $content; $this->line = $line; $this->position = $position; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { return null; } } ?> 'visitParagraph', 'ezcDocumentBBCodeTextNode' => 'visitText', 'ezcDocumentBBCodeTagNode' => 'visitTag', 'ezcDocumentBBCodeInlineLiteralNode' => 'visitInlineLiteral', 'ezcDocumentBBCodeLiteralBlockNode' => 'visitLiteralBlock', 'ezcDocumentBBCodeBulletListNode' => 'visitBulletList', 'ezcDocumentBBCodeEnumeratedListNode' => 'visitEnumeratedList', ); /** * DOM document * * @var DOMDocument */ protected $document; /** * Docarate BBCode AST * * Visit the BBCode abstract syntax tree. * * @param ezcDocumentBBCodeDocumentNode $ast * @return mixed */ public function visit( ezcDocumentBBCodeDocumentNode $ast ) { // Create article from AST $imp = new DOMImplementation(); $dtd = $imp->createDocumentType( 'article', '-//OASIS//DTD DocBook XML V4.5//EN', 'http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd' ); $this->document = $imp->createDocument( 'http://docbook.org/ns/docbook', '', $dtd ); $this->document->formatOutput = true; // $root = $this->document->createElement( 'article' ); $root = $this->document->createElementNs( 'http://docbook.org/ns/docbook', 'article' ); $this->document->appendChild( $root ); // Visit all childs of the AST root node. foreach ( $ast->nodes as $node ) { $this->visitNode( $root, $node ); } return $this->document; } /** * Visit single AST node * * Visit a single AST node, may be called for each node found anywhere * as child. The current position in the DOMDocument is passed by a * reference to the current DOMNode, which is operated on. * * @param DOMNode $root * @param ezcDocumentBBCodeNode $node * @return void */ public function visitNode( DOMNode $root, ezcDocumentBBCodeNode $node ) { // Iterate over available visitors and use them to visit the nodes. foreach ( $this->visitMapping as $class => $method ) { if ( $node instanceof $class ) { return $this->$method( $root, $node ); } } // We could not find any valid visitor. throw new ezcDocumentMissingVisitorException( get_class( $node ), $node->token->line, $node->token->position ); } /** * Visit paragraph markup * * @param DOMNode $root * @param ezcDocumentBBCodeNode $node * @return void */ protected function visitParagraph( DOMNode $root, ezcDocumentBBCodeNode $node ) { $para = $this->document->createElement( 'para' ); $root->appendChild( $para ); foreach ( $node->nodes as $child ) { $this->visitNode( $para, $child ); } } /** * Visit simple BBCode tag * * @param DOMNode $root * @param ezcDocumentBBCodeNode $node * @return void */ protected function visitTag( DOMNode $root, ezcDocumentBBCodeNode $node ) { if ( !isset( $this->bbcode->options->tags[$node->token->content] ) ) { $this->triggerError( E_WARNING, "Missing plugin for tag [{$node->token->content}].", $node->token->line, $node->token->position ); } else { $this->bbcode->options->tags[$node->token->content]->toDocbook( $this, $root, $node ); } } /** * Visit inlien literal markup * * @param DOMNode $root * @param ezcDocumentBBCodeNode $node * @return void */ protected function visitInlineLiteral( DOMNode $root, ezcDocumentBBCodeNode $node ) { $literal = $this->document->createElement( 'literal', htmlspecialchars( $node->token->content ) ); $root->appendChild( $literal ); } /** * Visit literal block markup * * @param DOMNode $root * @param ezcDocumentBBCodeNode $node * @return void */ protected function visitLiteralBlock( DOMNode $root, ezcDocumentBBCodeNode $node ) { $literal = $this->document->createElement( 'literallayout', htmlspecialchars( $node->token->content ) ); $root->appendChild( $literal ); } /** * Visit list items in a list * * @param DOMNode $list * @param ezcDocumentBBCodeListNode $node * @return void */ protected function visitListItems( DOMNode $list, ezcDocumentBBCodeListNode $node ) { foreach ( $node->nodes as $child ) { if ( !$child instanceof ezcDocumentBBCodeListItemNode ) { continue; } $item = $this->document->createElement( 'listitem' ); $list->appendChild( $item ); foreach ( $child->nodes as $grandChild ) { $this->visitNode( $item, $grandChild ); } } } /** * Visit bullet list * * @param DOMNode $root * @param ezcDocumentBBCodeNode $node * @return void */ protected function visitBulletList( DOMNode $root, ezcDocumentBBCodeNode $node ) { $list = $this->document->createElement( 'itemizedlist' ); $root->appendChild( $list ); $this->visitListItems( $list, $node ); } /** * Visit enumerated list * * @param DOMNode $root * @param ezcDocumentBBCodeNode $node * @return void */ protected function visitEnumeratedList( DOMNode $root, ezcDocumentBBCodeNode $node ) { $list = $this->document->createElement( 'orderedlist' ); $root->appendChild( $list ); switch ( $node->token->parameters ) { case 'a': $list->setAttribute( 'numeration', 'loweralpha' ); break; case '1': $list->setAttribute( 'numeration', 'arabic' ); break; } $this->visitListItems( $list, $node ); } } ?> line = $token->line; $this->position = $token->position; $this->token = $token; } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { return null; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> parameters = $parameters; } parent::__construct( $content, $line, $position ); } /** * Set state after var_export * * @param array $properties * @return void * @ignore */ public static function __set_state( $properties ) { $tokenClass = __CLASS__; $token = new $tokenClass( $properties['content'], $properties['line'], $properties['position'] ); // Set additional token values $token->parameters = $properties['parameters']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> value = $properties['value']; return $token; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> nodes = $properties['nodes']; return $node; } } ?> string) */ protected $docBookCharMap = array( 'circle' => '⚪', 'circ' => '⚪', 'square' => '◼', 'dics' => '⚫', 'skull' => '☠', 'smiley' => '☺', 'arrow' => '→', ); /** * Returns a UTF-8 bullet character for the given $mark. * * $mark can be a single character, in which case this character is * returned. Otherwise, the given $mark string is tried to be interpreted * and an according UTF-8 char is returned, if found. If this match fails, * the $default is returned. * * @param string $mark * @param string $default * @return string */ public function markToChar( $mark, $default = '⚫' ) { if ( iconv_strlen( $mark, 'UTF-8' ) === 1 ) { return $mark; } $mark = strtolower( $mark ); if ( isset( $this->docBookCharMap[$mark] ) ) { return $this->docBookCharMap[$mark]; } return $default; } } ?> localName} was invalid: $message" ); } } ?> localName} was invalid: $message" ); } } ?> errors = $errors; parent::__construct( "Errors occured while parsing the XML." ); } /** * Return array with XML errors. * * @return array */ public function getXmlErrors() { return $this->errors; } } ?> 'Notice', E_WARNING => 'Warning', E_ERROR => 'Error', E_PARSE => 'Fatal error', ); parent::__construct( sprintf( "Visitor error: %s: '%s' in line %d at position %d.", $levelMapping[$level], $message, $line, $position ) ); } } ?> 'Notice', E_WARNING => 'Warning', E_ERROR => 'Error', E_PARSE => 'Fatal error', ); /** * Error string * * String describing the general type of this error * * @var string */ protected $errorString = 'Conversion error'; /** * Original exception message * * @var string */ public $parseError; /** * Construct exception from errnous string and current position * * @param int $level * @param string $message * @param string $file * @param int $line * @param int $position * @param Exception $exception * @return void */ public function __construct( $level, $message, $file = null, $line = null, $position = null, Exception $exception = null ) { $this->parseError = $message; $message = "{$this->errorString}: {$this->levelMapping[$level]}: '$message'"; if ( $file !== null ) { $message .= " in file '$file'"; } if ( $line !== null ) { $message .= " in line $line at position $position"; } parent::__construct( $message . '.', 0, $exception ); } } ?> type}' are already set." ); } } ?> 'Warning', LIBXML_ERR_ERROR => 'Error', LIBXML_ERR_FATAL => 'Fatal error', ); /** * Create validation error object * * @param string $message * @param mixed $error * @return void */ protected function __construct( $message, $error = null ) { $this->message = $message; $this->error = $error; } /** * Get original error object * * @return mixed */ public function getOriginalError() { return $this->error; } /** * Convert libXML error to string * * @return void */ public function __toString() { return $this->message; } /** * Create from LibXmlError * * Create a validation error object from a LibXmlError error object. * * @param LibXMLError $error * @return ezcDocumentValidationError */ public static function createFromLibXmlError( LibXMLError $error ) { return new ezcDocumentValidationError( sprintf( "%s in %d:%d: %s.", self::$errorTypes[$error->level], $error->line, $error->column, trim( $error->message ) ), $error ); } /** * Create validation error from Exception * * @param Exception $e * @return ezcDocumentValidationError */ public static function createFromException( Exception $e ) { return new ezcDocumentValidationError( $e->getMessage(), $e ); } } ?> 'Document/exceptions/exception.php', 'ezcDocumentConversionException' => 'Document/exceptions/conversion.php', 'ezcDocumentErroneousXmlException' => 'Document/exceptions/erroneous_xml.php', 'ezcDocumentInvalidDocbookException' => 'Document/exceptions/invalid_docbook.php', 'ezcDocumentInvalidFontException' => 'Document/exceptions/unknown_font.php', 'ezcDocumentInvalidOdtException' => 'Document/exceptions/invalid_odt.php', 'ezcDocumentMissingVisitorException' => 'Document/exceptions/missing_visitor.php', 'ezcDocumentOdtFormattingPropertiesExistException' => 'Document/exceptions/odt/formatting_properties_exist.php', 'ezcDocumentParserException' => 'Document/exceptions/parser.php', 'ezcDocumentRstMissingDirectiveHandlerException' => 'Document/exceptions/missing_directive_handler.php', 'ezcDocumentRstMissingTextRoleHandlerException' => 'Document/exceptions/missing_text_role_handler.php', 'ezcDocumentRstTokenizerException' => 'Document/exceptions/rst_tokenizer.php', 'ezcDocumentVisitException' => 'Document/exceptions/visitor.php', 'ezcDocumentWikiMissingPluginHandlerException' => 'Document/exceptions/missing_plugin_handler.php', 'ezcDocumentWikiTokenizerException' => 'Document/exceptions/wiki_tokenizer.php', 'ezcDocumentPdfRenderer' => 'Document/document/pdf/renderer.php', 'ezcDocumentBBCodeNode' => 'Document/document/bbcode/node.php', 'ezcDocumentElementVisitorHandler' => 'Document/converters/element_visitor_handler.php', 'ezcDocumentErrorReporting' => 'Document/interfaces/error_reporting.php', 'ezcDocumentPdfBlockRenderer' => 'Document/document/pdf/renderer/block.php', 'ezcDocumentWikiNode' => 'Document/document/wiki/node.php', 'ezcDocumentWikiToken' => 'Document/document/wiki/token.php', 'ezcDocument' => 'Document/interfaces/document.php', 'ezcDocumentBBCodeBlockLevelNode' => 'Document/document/bbcode/nodes/block.php', 'ezcDocumentConverter' => 'Document/interfaces/converter.php', 'ezcDocumentConverterOptions' => 'Document/options/converter.php', 'ezcDocumentDocbookToRstBaseHandler' => 'Document/converters/element_visitor/docbook/rst/handler.php', 'ezcDocumentDocbookToWikiBaseHandler' => 'Document/converters/element_visitor/docbook/wiki/handler.php', 'ezcDocumentListItemGenerator' => 'Document/document/pdf/item_generator.php', 'ezcDocumentOptions' => 'Document/options/document.php', 'ezcDocumentPcssStyleValue' => 'Document/pcss/style/value.php', 'ezcDocumentPdfPart' => 'Document/document/pdf/part.php', 'ezcDocumentPdfTextBoxRenderer' => 'Document/document/pdf/renderer/text_box.php', 'ezcDocumentRstDirective' => 'Document/document/rst/directive.php', 'ezcDocumentRstNode' => 'Document/document/rst/node.php', 'ezcDocumentRstVisitor' => 'Document/document/rst/visitor.php', 'ezcDocumentRstXhtmlDirective' => 'Document/interfaces/rst_xhtml_directive.php', 'ezcDocumentValidation' => 'Document/interfaces/validation.php', 'ezcDocumentWikiBlockLevelNode' => 'Document/document/wiki/nodes/block.php', 'ezcDocumentWikiBlockMarkupToken' => 'Document/document/wiki/token/block_markup.php', 'ezcDocumentWikiInlineMarkupToken' => 'Document/document/wiki/token/inline_markup.php', 'ezcDocumentWikiInlineNode' => 'Document/document/wiki/nodes/inline.php', 'ezcDocumentAlnumListItemGenerator' => 'Document/document/pdf/item_generator/alnum.php', 'ezcDocumentBBCodeListNode' => 'Document/document/bbcode/nodes/list.php', 'ezcDocumentBBCodePlugin' => 'Document/document/bbcode/plugin.php', 'ezcDocumentBBCodeToken' => 'Document/document/bbcode/token.php', 'ezcDocumentBBCodeVisitor' => 'Document/document/bbcode/visitor.php', 'ezcDocumentDocbookToHtmlBaseHandler' => 'Document/converters/element_visitor/docbook/xhtml/handler.php', 'ezcDocumentDocbookToOdtBaseHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/handler.php', 'ezcDocumentDocbookToRstMediaObjectHandler' => 'Document/converters/element_visitor/docbook/rst/mediaobject.php', 'ezcDocumentDocbookToWikiMediaObjectHandler' => 'Document/converters/element_visitor/docbook/wiki/mediaobject.php', 'ezcDocumentElementVisitorConverter' => 'Document/converters/element_visitor.php', 'ezcDocumentEzXmlLinkConverter' => 'Document/interfaces/ezxml_link_converter.php', 'ezcDocumentEzXmlLinkProvider' => 'Document/interfaces/ezxml_link_provider.php', 'ezcDocumentHtmlConverterOptions' => 'Document/options/html_rendering.php', 'ezcDocumentLocateable' => 'Document/interfaces/locateable.php', 'ezcDocumentOdtBaseFilter' => 'Document/document/xml/odt/filter/base.php', 'ezcDocumentOdtElementBaseFilter' => 'Document/document/xml/odt/filter/element/base.php', 'ezcDocumentOdtListLevelStyle' => 'Document/document/xml/odt/list_level_style.php', 'ezcDocumentOdtPcssConverter' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter.php', 'ezcDocumentOdtStyleFilterRule' => 'Document/document/xml/odt/filter/style/rule.php', 'ezcDocumentOdtStyleGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/generator.php', 'ezcDocumentOdtStylePropertyGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/property_generator.php', 'ezcDocumentOdtStyler' => 'Document/converters/element_visitor/docbook/odt/styler.php', 'ezcDocumentParser' => 'Document/interfaces/parser.php', 'ezcDocumentPcssDirective' => 'Document/pcss/directive.php', 'ezcDocumentPcssStyleBoxValue' => 'Document/pcss/style/box_value.php', 'ezcDocumentPdfDriver' => 'Document/document/pdf/driver.php', 'ezcDocumentPdfFooterPdfPart' => 'Document/document/pdf/part/footer.php', 'ezcDocumentPdfHyphenator' => 'Document/document/pdf/hyphenator.php', 'ezcDocumentPdfImageHandler' => 'Document/document/pdf/image/handler.php', 'ezcDocumentPdfMainRenderer' => 'Document/document/pdf/renderer/main.php', 'ezcDocumentPdfTableColumnWidthCalculator' => 'Document/document/pdf/table_column_width_calculator.php', 'ezcDocumentPdfTokenizer' => 'Document/document/pdf/tokenizer.php', 'ezcDocumentPdfWrappingTextBoxRenderer' => 'Document/document/pdf/renderer/paragraph.php', 'ezcDocumentRstBlockNode' => 'Document/document/rst/nodes/block.php', 'ezcDocumentRstImageDirective' => 'Document/document/rst/directive/image.php', 'ezcDocumentRstLinkNode' => 'Document/document/rst/nodes/link.php', 'ezcDocumentRstMarkupNode' => 'Document/document/rst/nodes/markup.php', 'ezcDocumentRstTextRole' => 'Document/document/rst/role.php', 'ezcDocumentRstXhtmlTextRole' => 'Document/interfaces/rst_xhtml_role.php', 'ezcDocumentRstXhtmlVisitor' => 'Document/document/rst/visitor/xhtml.php', 'ezcDocumentWiki' => 'Document/document/wiki.php', 'ezcDocumentWikiLineLevelNode' => 'Document/document/wiki/nodes/line.php', 'ezcDocumentWikiLineMarkupToken' => 'Document/document/wiki/token/line_markup.php', 'ezcDocumentWikiLinkStartToken' => 'Document/document/wiki/token/link_start.php', 'ezcDocumentWikiListNode' => 'Document/document/wiki/nodes/list.php', 'ezcDocumentWikiMatchingInlineNode' => 'Document/document/wiki/nodes/matching_inline.php', 'ezcDocumentWikiPlugin' => 'Document/document/wiki/plugin.php', 'ezcDocumentWikiSectionNode' => 'Document/document/wiki/nodes/section.php', 'ezcDocumentWikiSeparatorNode' => 'Document/document/wiki/nodes/separator.php', 'ezcDocumentWikiTokenizer' => 'Document/document/wiki/tokenizer.php', 'ezcDocumentWikiVisitor' => 'Document/document/wiki/visitor.php', 'ezcDocumentXhtmlBaseFilter' => 'Document/document/xml/xhtml/filter/base.php', 'ezcDocumentXhtmlConversion' => 'Document/interfaces/conversions/xhtml.php', 'ezcDocumentXhtmlElementBaseFilter' => 'Document/document/xml/xhtml/filter/element/base.php', 'ezcDocumentXmlBase' => 'Document/document/xml_base.php', 'ezcDocumentXmlOptions' => 'Document/options/document_xml.php', 'ezcDocumentXsltConverter' => 'Document/converters/xslt.php', 'ezcDocumentXsltConverterOptions' => 'Document/options/converter_xslt.php', 'ezcDocumentAlphaListItemGenerator' => 'Document/document/pdf/item_generator/alpha.php', 'ezcDocumentBBCode' => 'Document/document/bbcode.php', 'ezcDocumentBBCodeBulletListNode' => 'Document/document/bbcode/nodes/bullet_list.php', 'ezcDocumentBBCodeClosingTagNode' => 'Document/document/bbcode/nodes/tag_close.php', 'ezcDocumentBBCodeDocbookVisitor' => 'Document/document/bbcode/visitor/docbook.php', 'ezcDocumentBBCodeDocumentNode' => 'Document/document/bbcode/nodes/document.php', 'ezcDocumentBBCodeEmailPlugin' => 'Document/document/bbcode/plugins/email.php', 'ezcDocumentBBCodeEmphasisPlugin' => 'Document/document/bbcode/plugins/emphasis.php', 'ezcDocumentBBCodeEndOfFileToken' => 'Document/document/bbcode/token/end_of_file.php', 'ezcDocumentBBCodeEnumeratedListNode' => 'Document/document/bbcode/nodes/enumerated_list.php', 'ezcDocumentBBCodeImagePlugin' => 'Document/document/bbcode/plugins/image.php', 'ezcDocumentBBCodeInlineLiteralNode' => 'Document/document/bbcode/nodes/inline_literal.php', 'ezcDocumentBBCodeLineBreakToken' => 'Document/document/bbcode/token/line_break.php', 'ezcDocumentBBCodeListEndNode' => 'Document/document/bbcode/nodes/list_end.php', 'ezcDocumentBBCodeListItemNode' => 'Document/document/bbcode/nodes/list_item.php', 'ezcDocumentBBCodeListItemToken' => 'Document/document/bbcode/token/list_item.php', 'ezcDocumentBBCodeLiteralBlockNode' => 'Document/document/bbcode/nodes/literal_block.php', 'ezcDocumentBBCodeLiteralBlockToken' => 'Document/document/bbcode/token/literal_block.php', 'ezcDocumentBBCodeNewLineToken' => 'Document/document/bbcode/token/new_line.php', 'ezcDocumentBBCodeNoMarkupPlugin' => 'Document/document/bbcode/plugins/no.php', 'ezcDocumentBBCodeOptions' => 'Document/options/document_bbcode.php', 'ezcDocumentBBCodeParagraphNode' => 'Document/document/bbcode/nodes/paragraph.php', 'ezcDocumentBBCodeParser' => 'Document/document/bbcode/parser.php', 'ezcDocumentBBCodeQuotePlugin' => 'Document/document/bbcode/plugins/quote.php', 'ezcDocumentBBCodeSpecialCharsToken' => 'Document/document/bbcode/token/special_chars.php', 'ezcDocumentBBCodeTagCloseToken' => 'Document/document/bbcode/token/tag_clsoe.php', 'ezcDocumentBBCodeTagNode' => 'Document/document/bbcode/nodes/tag.php', 'ezcDocumentBBCodeTagOpenToken' => 'Document/document/bbcode/token/tag_open.php', 'ezcDocumentBBCodeTextLineToken' => 'Document/document/bbcode/token/text_line.php', 'ezcDocumentBBCodeTextNode' => 'Document/document/bbcode/nodes/text.php', 'ezcDocumentBBCodeTokenizer' => 'Document/document/bbcode/tokenizer.php', 'ezcDocumentBBCodeUrlPlugin' => 'Document/document/bbcode/plugins/url.php', 'ezcDocumentBBCodeWhitespaceToken' => 'Document/document/bbcode/token/whitespace.php', 'ezcDocumentBulletListItemGenerator' => 'Document/document/pdf/item_generator/bullet.php', 'ezcDocumentConfluenceWiki' => 'Document/document/wiki/confluence.php', 'ezcDocumentCreoleWiki' => 'Document/document/wiki/creole.php', 'ezcDocumentDocbook' => 'Document/document/xml/docbook.php', 'ezcDocumentDocbookOptions' => 'Document/options/document_docbook.php', 'ezcDocumentDocbookToEzXmlAnchorHandler' => 'Document/converters/element_visitor/docbook/ezxml/anchor.php', 'ezcDocumentDocbookToEzXmlCommentHandler' => 'Document/converters/element_visitor/docbook/ezxml/comment.php', 'ezcDocumentDocbookToEzXmlConverter' => 'Document/converters/element_visitor/docbook_ezxml.php', 'ezcDocumentDocbookToEzXmlConverterOptions' => 'Document/options/converter_docbook_ezxml.php', 'ezcDocumentDocbookToEzXmlEmphasisHandler' => 'Document/converters/element_visitor/docbook/ezxml/emphasis.php', 'ezcDocumentDocbookToEzXmlExternalLinkHandler' => 'Document/converters/element_visitor/docbook/ezxml/external_link.php', 'ezcDocumentDocbookToEzXmlFootnoteHandler' => 'Document/converters/element_visitor/docbook/ezxml/footnote.php', 'ezcDocumentDocbookToEzXmlIgnoreHandler' => 'Document/converters/element_visitor/docbook/ezxml/ignore.php', 'ezcDocumentDocbookToEzXmlInternalLinkHandler' => 'Document/converters/element_visitor/docbook/ezxml/internal_link.php', 'ezcDocumentDocbookToEzXmlItemizedListHandler' => 'Document/converters/element_visitor/docbook/ezxml/itemized_list.php', 'ezcDocumentDocbookToEzXmlLiteralLayoutHandler' => 'Document/converters/element_visitor/docbook/ezxml/literal_layout.php', 'ezcDocumentDocbookToEzXmlMappingHandler' => 'Document/converters/element_visitor/docbook/ezxml/mapper.php', 'ezcDocumentDocbookToEzXmlOrderedListHandler' => 'Document/converters/element_visitor/docbook/ezxml/ordered_list.php', 'ezcDocumentDocbookToEzXmlParagraphHandler' => 'Document/converters/element_visitor/docbook/ezxml/paragraph.php', 'ezcDocumentDocbookToEzXmlRecurseHandler' => 'Document/converters/element_visitor/docbook/ezxml/recurse.php', 'ezcDocumentDocbookToEzXmlSectionHandler' => 'Document/converters/element_visitor/docbook/ezxml/section.php', 'ezcDocumentDocbookToEzXmlTableCellHandler' => 'Document/converters/element_visitor/docbook/ezxml/table_cell.php', 'ezcDocumentDocbookToEzXmlTableHandler' => 'Document/converters/element_visitor/docbook/ezxml/table.php', 'ezcDocumentDocbookToEzXmlTitleHandler' => 'Document/converters/element_visitor/docbook/ezxml/title.php', 'ezcDocumentDocbookToHtmlAnchorHandler' => 'Document/converters/element_visitor/docbook/xhtml/anchor.php', 'ezcDocumentDocbookToHtmlBlockquoteHandler' => 'Document/converters/element_visitor/docbook/xhtml/blockquote.php', 'ezcDocumentDocbookToHtmlCommentHandler' => 'Document/converters/element_visitor/docbook/xhtml/comment.php', 'ezcDocumentDocbookToHtmlConverter' => 'Document/converters/element_visitor/docbook_html.php', 'ezcDocumentDocbookToHtmlConverterOptions' => 'Document/options/converter_docbook_html.php', 'ezcDocumentDocbookToHtmlDefinitionListEntryHandler' => 'Document/converters/element_visitor/docbook/xhtml/definition_list_entry.php', 'ezcDocumentDocbookToHtmlEmphasisHandler' => 'Document/converters/element_visitor/docbook/xhtml/emphasis.php', 'ezcDocumentDocbookToHtmlExternalLinkHandler' => 'Document/converters/element_visitor/docbook/xhtml/external_link.php', 'ezcDocumentDocbookToHtmlFootnoteHandler' => 'Document/converters/element_visitor/docbook/xhtml/footnote.php', 'ezcDocumentDocbookToHtmlHeadHandler' => 'Document/converters/element_visitor/docbook/xhtml/head.php', 'ezcDocumentDocbookToHtmlIgnoreHandler' => 'Document/converters/element_visitor/docbook/xhtml/ignore.php', 'ezcDocumentDocbookToHtmlInternalLinkHandler' => 'Document/converters/element_visitor/docbook/xhtml/internal_link.php', 'ezcDocumentDocbookToHtmlLiteralLayoutHandler' => 'Document/converters/element_visitor/docbook/xhtml/literal_layout.php', 'ezcDocumentDocbookToHtmlMappingHandler' => 'Document/converters/element_visitor/docbook/xhtml/mapper.php', 'ezcDocumentDocbookToHtmlMediaObjectHandler' => 'Document/converters/element_visitor/docbook/xhtml/mediaobject.php', 'ezcDocumentDocbookToHtmlParagraphHandler' => 'Document/converters/element_visitor/docbook/xhtml/paragraph.php', 'ezcDocumentDocbookToHtmlSectionHandler' => 'Document/converters/element_visitor/docbook/xhtml/section.php', 'ezcDocumentDocbookToHtmlSpecialParagraphHandler' => 'Document/converters/element_visitor/docbook/xhtml/special_paragraph.php', 'ezcDocumentDocbookToHtmlTableCellHandler' => 'Document/converters/element_visitor/docbook/xhtml/table_cell.php', 'ezcDocumentDocbookToHtmlXsltConverter' => 'Document/converters/xslt/docbook_html.php', 'ezcDocumentDocbookToHtmlXsltConverterOptions' => 'Document/options/converter_docbook_html_xslt.php', 'ezcDocumentDocbookToOdtAnchorHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/anchor.php', 'ezcDocumentDocbookToOdtCommentHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/comment.php', 'ezcDocumentDocbookToOdtConverter' => 'Document/converters/element_visitor/docbook_odt.php', 'ezcDocumentDocbookToOdtConverterOptions' => 'Document/options/converter_docbook_odt.php', 'ezcDocumentDocbookToOdtFootnoteHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/footnote.php', 'ezcDocumentDocbookToOdtIgnoreHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/ignore.php', 'ezcDocumentDocbookToOdtInlineHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/inline.php', 'ezcDocumentDocbookToOdtLinkHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/link.php', 'ezcDocumentDocbookToOdtListHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/list.php', 'ezcDocumentDocbookToOdtLiteralLayoutHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/literal_layout.php', 'ezcDocumentDocbookToOdtMappingHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/mapper.php', 'ezcDocumentDocbookToOdtMediaObjectHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/media_object.php', 'ezcDocumentDocbookToOdtPageBreakHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/page_break.php', 'ezcDocumentDocbookToOdtParagraphHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/paragraph.php', 'ezcDocumentDocbookToOdtSectionHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/section.php', 'ezcDocumentDocbookToOdtTableHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/table.php', 'ezcDocumentDocbookToOdtUlinkHandler' => 'Document/converters/element_visitor/docbook/odt/element_handlers/ulink.php', 'ezcDocumentDocbookToRstBeginPageHandler' => 'Document/converters/element_visitor/docbook/rst/begin_page.php', 'ezcDocumentDocbookToRstBlockquoteHandler' => 'Document/converters/element_visitor/docbook/rst/blockquote.php', 'ezcDocumentDocbookToRstCitationHandler' => 'Document/converters/element_visitor/docbook/rst/citation.php', 'ezcDocumentDocbookToRstCommentHandler' => 'Document/converters/element_visitor/docbook/rst/comment.php', 'ezcDocumentDocbookToRstConverter' => 'Document/converters/element_visitor/docbook_rst.php', 'ezcDocumentDocbookToRstConverterOptions' => 'Document/options/converter_docbook_rst.php', 'ezcDocumentDocbookToRstEmphasisHandler' => 'Document/converters/element_visitor/docbook/rst/emphasis.php', 'ezcDocumentDocbookToRstExternalLinkHandler' => 'Document/converters/element_visitor/docbook/rst/external_link.php', 'ezcDocumentDocbookToRstFootnoteHandler' => 'Document/converters/element_visitor/docbook/rst/footnote.php', 'ezcDocumentDocbookToRstHeadHandler' => 'Document/converters/element_visitor/docbook/rst/head.php', 'ezcDocumentDocbookToRstIgnoreHandler' => 'Document/converters/element_visitor/docbook/rst/ignore.php', 'ezcDocumentDocbookToRstInlineMediaObjectHandler' => 'Document/converters/element_visitor/docbook/rst/inlinemediaobject.php', 'ezcDocumentDocbookToRstInternalLinkHandler' => 'Document/converters/element_visitor/docbook/rst/internal_link.php', 'ezcDocumentDocbookToRstItemizedListHandler' => 'Document/converters/element_visitor/docbook/rst/itemized_list.php', 'ezcDocumentDocbookToRstLiteralHandler' => 'Document/converters/element_visitor/docbook/rst/literal.php', 'ezcDocumentDocbookToRstLiteralLayoutHandler' => 'Document/converters/element_visitor/docbook/rst/literal_layout.php', 'ezcDocumentDocbookToRstOrderedListHandler' => 'Document/converters/element_visitor/docbook/rst/ordered_list.php', 'ezcDocumentDocbookToRstParagraphHandler' => 'Document/converters/element_visitor/docbook/rst/paragraph.php', 'ezcDocumentDocbookToRstRecurseHandler' => 'Document/converters/element_visitor/docbook/rst/recurse.php', 'ezcDocumentDocbookToRstSectionHandler' => 'Document/converters/element_visitor/docbook/rst/section.php', 'ezcDocumentDocbookToRstSpecialParagraphHandler' => 'Document/converters/element_visitor/docbook/rst/special_paragraph.php', 'ezcDocumentDocbookToRstTableHandler' => 'Document/converters/element_visitor/docbook/rst/table.php', 'ezcDocumentDocbookToRstVariableListHandler' => 'Document/converters/element_visitor/docbook/rst/variable_list.php', 'ezcDocumentDocbookToWikiBeginPageHandler' => 'Document/converters/element_visitor/docbook/wiki/begin_page.php', 'ezcDocumentDocbookToWikiConverter' => 'Document/converters/element_visitor/docbook_wiki.php', 'ezcDocumentDocbookToWikiConverterOptions' => 'Document/options/converter_docbook_wiki.php', 'ezcDocumentDocbookToWikiEmphasisHandler' => 'Document/converters/element_visitor/docbook/wiki/emphasis.php', 'ezcDocumentDocbookToWikiExternalLinkHandler' => 'Document/converters/element_visitor/docbook/wiki/external_link.php', 'ezcDocumentDocbookToWikiIgnoreHandler' => 'Document/converters/element_visitor/docbook/wiki/ignore.php', 'ezcDocumentDocbookToWikiInlineMediaObjectHandler' => 'Document/converters/element_visitor/docbook/wiki/inlinemediaobject.php', 'ezcDocumentDocbookToWikiInternalLinkHandler' => 'Document/converters/element_visitor/docbook/wiki/internal_link.php', 'ezcDocumentDocbookToWikiItemizedListHandler' => 'Document/converters/element_visitor/docbook/wiki/itemized_list.php', 'ezcDocumentDocbookToWikiLiteralHandler' => 'Document/converters/element_visitor/docbook/wiki/literal.php', 'ezcDocumentDocbookToWikiLiteralLayoutHandler' => 'Document/converters/element_visitor/docbook/wiki/literal_layout.php', 'ezcDocumentDocbookToWikiOrderedListHandler' => 'Document/converters/element_visitor/docbook/wiki/ordered_list.php', 'ezcDocumentDocbookToWikiParagraphHandler' => 'Document/converters/element_visitor/docbook/wiki/paragraph.php', 'ezcDocumentDocbookToWikiRecurseHandler' => 'Document/converters/element_visitor/docbook/wiki/recurse.php', 'ezcDocumentDocbookToWikiSectionHandler' => 'Document/converters/element_visitor/docbook/wiki/section.php', 'ezcDocumentDocbookToWikiTableHandler' => 'Document/converters/element_visitor/docbook/wiki/table.php', 'ezcDocumentDokuwikiWiki' => 'Document/document/wiki/dokuwiki.php', 'ezcDocumentEzXml' => 'Document/document/xml/ezxml.php', 'ezcDocumentEzXmlDummyLinkConverter' => 'Document/document/xml/ezxml/dummy_link_converter.php', 'ezcDocumentEzXmlDummyLinkProvider' => 'Document/document/xml/ezxml/dummy_link_provider.php', 'ezcDocumentEzXmlOptions' => 'Document/options/document_ezxml.php', 'ezcDocumentEzXmlToDocbookAnchorHandler' => 'Document/converters/element_visitor/ezxml/docbook/anchor.php', 'ezcDocumentEzXmlToDocbookConverter' => 'Document/converters/element_visitor/ezxml_docbook.php', 'ezcDocumentEzXmlToDocbookConverterOptions' => 'Document/options/converter_ezxml_docbook.php', 'ezcDocumentEzXmlToDocbookEmphasisHandler' => 'Document/converters/element_visitor/ezxml/docbook/emphasis.php', 'ezcDocumentEzXmlToDocbookHeaderHandler' => 'Document/converters/element_visitor/ezxml/docbook/header.php', 'ezcDocumentEzXmlToDocbookLineHandler' => 'Document/converters/element_visitor/ezxml/docbook/line.php', 'ezcDocumentEzXmlToDocbookLinkHandler' => 'Document/converters/element_visitor/ezxml/docbook/link.php', 'ezcDocumentEzXmlToDocbookListHandler' => 'Document/converters/element_visitor/ezxml/docbook/list.php', 'ezcDocumentEzXmlToDocbookLiteralHandler' => 'Document/converters/element_visitor/ezxml/docbook/literal.php', 'ezcDocumentEzXmlToDocbookMappingHandler' => 'Document/converters/element_visitor/ezxml/docbook/mapper.php', 'ezcDocumentEzXmlToDocbookTableCellHandler' => 'Document/converters/element_visitor/ezxml/docbook/table_cell.php', 'ezcDocumentEzXmlToDocbookTableHandler' => 'Document/converters/element_visitor/ezxml/docbook/table.php', 'ezcDocumentEzXmlToDocbookTableRowHandler' => 'Document/converters/element_visitor/ezxml/docbook/table_row.php', 'ezcDocumentListBulletGuesser' => 'Document/tools/list_bullet_guesser.php', 'ezcDocumentLocateableDomElement' => 'Document/dom_elements/locateable.php', 'ezcDocumentNoListItemGenerator' => 'Document/document/pdf/item_generator/no.php', 'ezcDocumentNumberedListItemGenerator' => 'Document/document/pdf/item_generator/number.php', 'ezcDocumentOdt' => 'Document/document/xml/odt.php', 'ezcDocumentOdtDefaultPcssConverter' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter/default.php', 'ezcDocumentOdtElementFilter' => 'Document/document/xml/odt/filter/element.php', 'ezcDocumentOdtElementFootnoteFilter' => 'Document/document/xml/odt/filter/element/footnote.php', 'ezcDocumentOdtElementFrameFilter' => 'Document/document/xml/odt/filter/element/frame.php', 'ezcDocumentOdtElementHeaderFilter' => 'Document/document/xml/odt/filter/element/header.php', 'ezcDocumentOdtElementHtmlTableFilter' => 'Document/document/xml/odt/filter/element/html_table.php', 'ezcDocumentOdtElementImageFilter' => 'Document/document/xml/odt/filter/element/image.php', 'ezcDocumentOdtElementLinkFilter' => 'Document/document/xml/odt/filter/element/link.php', 'ezcDocumentOdtElementListFilter' => 'Document/document/xml/odt/filter/element/list.php', 'ezcDocumentOdtElementParagraphFilter' => 'Document/document/xml/odt/filter/element/paragraph.php', 'ezcDocumentOdtElementTableFilter' => 'Document/document/xml/odt/filter/element/table.php', 'ezcDocumentOdtElementWhitespaceFilter' => 'Document/document/xml/odt/filter/element/whitespace.php', 'ezcDocumentOdtEmphasisStyleFilterRule' => 'Document/document/xml/odt/filter/style/rule/emphasis.php', 'ezcDocumentOdtFormattingProperties' => 'Document/document/xml/odt/formatting/properties.php', 'ezcDocumentOdtFormattingPropertyCollection' => 'Document/document/xml/odt/formatting/property_collection.php', 'ezcDocumentOdtImageFilter' => 'Document/document/xml/odt/filter/image.php', 'ezcDocumentOdtImageLocator' => 'Document/converters/element_visitor/docbook/odt/image_locator.php', 'ezcDocumentOdtListLevelStyleBullet' => 'Document/document/xml/odt/list_level_style/bullet.php', 'ezcDocumentOdtListLevelStyleFilterRule' => 'Document/document/xml/odt/filter/style/rule/list_level.php', 'ezcDocumentOdtListLevelStyleNumber' => 'Document/document/xml/odt/list_level_style/number.php', 'ezcDocumentOdtListStyle' => 'Document/document/xml/odt/list_style.php', 'ezcDocumentOdtListStyleGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/generator/list.php', 'ezcDocumentOdtMetaGenerator' => 'Document/converters/element_visitor/docbook/odt/meta_generator.php', 'ezcDocumentOdtOptions' => 'Document/options/document_odt.php', 'ezcDocumentOdtParagraphStyleGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/generator/paragraph.php', 'ezcDocumentOdtPcssBorderConverter' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter/border.php', 'ezcDocumentOdtPcssColorConverter' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter/color.php', 'ezcDocumentOdtPcssConverterManager' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter_manager.php', 'ezcDocumentOdtPcssConverterTools' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter_tools.php', 'ezcDocumentOdtPcssFontConverter' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter/font.php', 'ezcDocumentOdtPcssFontNameConverter' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter/font_name.php', 'ezcDocumentOdtPcssFontSizeConverter' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter/font_size.php', 'ezcDocumentOdtPcssFontStylePreprocessor' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/preprocessor/font.php', 'ezcDocumentOdtPcssListStylePreprocessor' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/preprocessor/list.php', 'ezcDocumentOdtPcssMarginConverter' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter/margin.php', 'ezcDocumentOdtPcssParagraphStylePreprocessor' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/preprocessor/paragraph.php', 'ezcDocumentOdtPcssPreprocessor' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/preprocessor.php', 'ezcDocumentOdtPcssStyler' => 'Document/converters/element_visitor/docbook/odt/styler/pcss.php', 'ezcDocumentOdtPcssTextDecorationConverter' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/converter/text_decoration.php', 'ezcDocumentOdtStyle' => 'Document/document/xml/odt/style.php', 'ezcDocumentOdtStyleExtractor' => 'Document/document/xml/odt/style/extractor.php', 'ezcDocumentOdtStyleFilter' => 'Document/document/xml/odt/filter/style.php', 'ezcDocumentOdtStyleInferencer' => 'Document/document/xml/odt/style/inferencer.php', 'ezcDocumentOdtStyleInformation' => 'Document/converters/element_visitor/docbook/odt/style_information.php', 'ezcDocumentOdtStyleListPropertyGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/property_generator/list.php', 'ezcDocumentOdtStyleParagraphPropertyGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/property_generator/paragraph.php', 'ezcDocumentOdtStyleParser' => 'Document/document/xml/odt/style/parser.php', 'ezcDocumentOdtStyleTableCellPropertyGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/property_generator/table_cell.php', 'ezcDocumentOdtStyleTablePropertyGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/property_generator/table.php', 'ezcDocumentOdtStyleTableRowPropertyGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/property_generator/table_row.php', 'ezcDocumentOdtStyleTextPropertyGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/property_generator/text.php', 'ezcDocumentOdtTableCellStyleGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/generator/table_cell.php', 'ezcDocumentOdtTableRowStyleGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/generator/table_row.php', 'ezcDocumentOdtTableStyleGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/generator/table.php', 'ezcDocumentOdtTextProcessor' => 'Document/converters/element_visitor/docbook/odt/text_processor.php', 'ezcDocumentOdtTextStyleGenerator' => 'Document/converters/element_visitor/docbook/odt/styler/pcss/generator/text.php', 'ezcDocumentParserOptions' => 'Document/options/document_parser.php', 'ezcDocumentPcssDeclarationDirective' => 'Document/pcss/declaration_directive.php', 'ezcDocumentPcssLayoutDirective' => 'Document/pcss/layout_directive.php', 'ezcDocumentPcssMeasure' => 'Document/pcss/measure.php', 'ezcDocumentPcssParser' => 'Document/pcss/parser.php', 'ezcDocumentPcssStyleBorderBoxValue' => 'Document/pcss/style/border_box_value.php', 'ezcDocumentPcssStyleBorderValue' => 'Document/pcss/style/border_value.php', 'ezcDocumentPcssStyleColorBoxValue' => 'Document/pcss/style/color_box_value.php', 'ezcDocumentPcssStyleColorValue' => 'Document/pcss/style/color_value.php', 'ezcDocumentPcssStyleInferencer' => 'Document/pcss/style_inferencer.php', 'ezcDocumentPcssStyleIntValue' => 'Document/pcss/style/int_value.php', 'ezcDocumentPcssStyleLineBoxValue' => 'Document/pcss/style/line_box_value.php', 'ezcDocumentPcssStyleLineValue' => 'Document/pcss/style/line_value.php', 'ezcDocumentPcssStyleListValue' => 'Document/pcss/style/list_value.php', 'ezcDocumentPcssStyleMeasureBoxValue' => 'Document/pcss/style/measure_box_value.php', 'ezcDocumentPcssStyleMeasureValue' => 'Document/pcss/style/measure_value.php', 'ezcDocumentPcssStyleSrcValue' => 'Document/pcss/style/src_value.php', 'ezcDocumentPcssStyleStringValue' => 'Document/pcss/style/string_value.php', 'ezcDocumentPdf' => 'Document/document/pdf.php', 'ezcDocumentPdfBlockquoteRenderer' => 'Document/document/pdf/renderer/blockquote.php', 'ezcDocumentPdfBoundingBox' => 'Document/document/pdf/box.php', 'ezcDocumentPdfDefaultHyphenator' => 'Document/document/pdf/hyphenator/default.php', 'ezcDocumentPdfDefaultTableColumnWidthCalculator' => 'Document/document/pdf/default_table_column_width_calculator.php', 'ezcDocumentPdfDefaultTokenizer' => 'Document/document/pdf/tokenizer/default.php', 'ezcDocumentPdfFooterOptions' => 'Document/options/document_pdf_footer.php', 'ezcDocumentPdfHaruDriver' => 'Document/document/pdf/driver/haru.php', 'ezcDocumentPdfHeaderPdfPart' => 'Document/document/pdf/part/header.php', 'ezcDocumentPdfImage' => 'Document/document/pdf/image.php', 'ezcDocumentPdfListItemRenderer' => 'Document/document/pdf/renderer/list_item.php', 'ezcDocumentPdfListRenderer' => 'Document/document/pdf/renderer/list.php', 'ezcDocumentPdfLiteralBlockRenderer' => 'Document/document/pdf/renderer/literal_block.php', 'ezcDocumentPdfLiteralTokenizer' => 'Document/document/pdf/tokenizer/literal.php', 'ezcDocumentPdfMediaObjectRenderer' => 'Document/document/pdf/renderer/mediaobject.php', 'ezcDocumentPdfOptions' => 'Document/options/document_pdf.php', 'ezcDocumentPdfPage' => 'Document/document/pdf/page.php', 'ezcDocumentPdfPhpImageHandler' => 'Document/document/pdf/image/php.php', 'ezcDocumentPdfSvgDriver' => 'Document/document/pdf/driver/svg.php', 'ezcDocumentPdfTableRenderer' => 'Document/document/pdf/renderer/table.php', 'ezcDocumentPdfTcpdfDriver' => 'Document/document/pdf/driver/tcpdf.php', 'ezcDocumentPdfTextBlockRenderer' => 'Document/document/pdf/renderer/text_block.php', 'ezcDocumentPdfTitleRenderer' => 'Document/document/pdf/renderer/title.php', 'ezcDocumentPdfTransactionalDriverWrapper' => 'Document/document/pdf/driver/wrapper.php', 'ezcDocumentPdfTransactionalDriverWrapperState' => 'Document/document/pdf/driver/wrapper_state.php', 'ezcDocumentPropertyContainerDomElement' => 'Document/dom_elements/property_container.php', 'ezcDocumentRomanListItemGenerator' => 'Document/document/pdf/item_generator/roman.php', 'ezcDocumentRst' => 'Document/document/rst.php', 'ezcDocumentRstAnonymousLinkNode' => 'Document/document/rst/nodes/link_anonymous.php', 'ezcDocumentRstAnonymousReferenceNode' => 'Document/document/rst/nodes/anon_reference.php', 'ezcDocumentRstAttentionDirective' => 'Document/document/rst/directive/attention.php', 'ezcDocumentRstBlockquoteAnnotationNode' => 'Document/document/rst/nodes/blockquote_annotation.php', 'ezcDocumentRstBlockquoteNode' => 'Document/document/rst/nodes/blockquote.php', 'ezcDocumentRstBulletListListNode' => 'Document/document/rst/nodes/bullet_list_list.php', 'ezcDocumentRstBulletListNode' => 'Document/document/rst/nodes/bullet_list.php', 'ezcDocumentRstCommentNode' => 'Document/document/rst/nodes/comment.php', 'ezcDocumentRstContentsDirective' => 'Document/document/rst/directive/contents.php', 'ezcDocumentRstDangerDirective' => 'Document/document/rst/directive/danger.php', 'ezcDocumentRstDefinitionListListNode' => 'Document/document/rst/nodes/definition_list_list.php', 'ezcDocumentRstDefinitionListNode' => 'Document/document/rst/nodes/definition_list.php', 'ezcDocumentRstDirectiveNode' => 'Document/document/rst/nodes/directive.php', 'ezcDocumentRstDocbookVisitor' => 'Document/document/rst/visitor/docbook.php', 'ezcDocumentRstDocumentNode' => 'Document/document/rst/nodes/document.php', 'ezcDocumentRstEmphasisTextRole' => 'Document/document/rst/role/emphasis.php', 'ezcDocumentRstEnumeratedListListNode' => 'Document/document/rst/nodes/enumerated_list_list.php', 'ezcDocumentRstEnumeratedListNode' => 'Document/document/rst/nodes/enumerated_list.php', 'ezcDocumentRstExternalReferenceNode' => 'Document/document/rst/nodes/link_reference.php', 'ezcDocumentRstFieldListNode' => 'Document/document/rst/nodes/field_list.php', 'ezcDocumentRstFigureDirective' => 'Document/document/rst/directive/figure.php', 'ezcDocumentRstFootnoteNode' => 'Document/document/rst/nodes/footnote.php', 'ezcDocumentRstIncludeDirective' => 'Document/document/rst/directive/include.php', 'ezcDocumentRstLineBlockLineNode' => 'Document/document/rst/nodes/line_block_line.php', 'ezcDocumentRstLineBlockNode' => 'Document/document/rst/nodes/line_block.php', 'ezcDocumentRstLiteralBlockNode' => 'Document/document/rst/nodes/literal_block.php', 'ezcDocumentRstLiteralNode' => 'Document/document/rst/nodes/literal.php', 'ezcDocumentRstLiteralTextRole' => 'Document/document/rst/role/literal.php', 'ezcDocumentRstMarkupEmphasisNode' => 'Document/document/rst/nodes/markup_emphasis.php', 'ezcDocumentRstMarkupInlineLiteralNode' => 'Document/document/rst/nodes/markup_inline_literal.php', 'ezcDocumentRstMarkupInterpretedTextNode' => 'Document/document/rst/nodes/markup_interpreted_text.php', 'ezcDocumentRstMarkupStrongEmphasisNode' => 'Document/document/rst/nodes/markup_strong_emphasis.php', 'ezcDocumentRstMarkupSubstitutionNode' => 'Document/document/rst/nodes/markup_substitution.php', 'ezcDocumentRstNamedReferenceNode' => 'Document/document/rst/nodes/named_reference.php', 'ezcDocumentRstNoteDirective' => 'Document/document/rst/directive/note.php', 'ezcDocumentRstNoticeDirective' => 'Document/document/rst/directive/notice.php', 'ezcDocumentRstOptions' => 'Document/options/document_rst.php', 'ezcDocumentRstParagraphNode' => 'Document/document/rst/nodes/paragraph.php', 'ezcDocumentRstParser' => 'Document/document/rst/parser.php', 'ezcDocumentRstReferenceNode' => 'Document/document/rst/nodes/reference.php', 'ezcDocumentRstSectionNode' => 'Document/document/rst/nodes/section.php', 'ezcDocumentRstStack' => 'Document/document/rst/document_stack.php', 'ezcDocumentRstStrongTextRole' => 'Document/document/rst/role/strong.php', 'ezcDocumentRstSubscriptTextRole' => 'Document/document/rst/role/subscript.php', 'ezcDocumentRstSubstitutionNode' => 'Document/document/rst/nodes/substitution.php', 'ezcDocumentRstSuperscriptTextRole' => 'Document/document/rst/role/superscript.php', 'ezcDocumentRstTableBodyNode' => 'Document/document/rst/nodes/table_body.php', 'ezcDocumentRstTableCellNode' => 'Document/document/rst/nodes/table_cell.php', 'ezcDocumentRstTableHeadNode' => 'Document/document/rst/nodes/table_head.php', 'ezcDocumentRstTableNode' => 'Document/document/rst/nodes/table.php', 'ezcDocumentRstTableRowNode' => 'Document/document/rst/nodes/table_row.php', 'ezcDocumentRstTargetNode' => 'Document/document/rst/nodes/target.php', 'ezcDocumentRstTextLineNode' => 'Document/document/rst/nodes/text_line.php', 'ezcDocumentRstTitleNode' => 'Document/document/rst/nodes/title.php', 'ezcDocumentRstTitleReferenceTextRole' => 'Document/document/rst/role/title_reference.php', 'ezcDocumentRstToken' => 'Document/document/rst/token.php', 'ezcDocumentRstTokenizer' => 'Document/document/rst/tokenizer.php', 'ezcDocumentRstTransitionNode' => 'Document/document/rst/nodes/transition.php', 'ezcDocumentRstWarningDirective' => 'Document/document/rst/directive/warning.php', 'ezcDocumentRstXhtmlBodyVisitor' => 'Document/document/rst/visitor/xhtml_body.php', 'ezcDocumentValidationError' => 'Document/validation_error.php', 'ezcDocumentWikiBlockquoteNode' => 'Document/document/wiki/nodes/blockquote.php', 'ezcDocumentWikiBoldNode' => 'Document/document/wiki/nodes/bold.php', 'ezcDocumentWikiBoldToken' => 'Document/document/wiki/token/bold.php', 'ezcDocumentWikiBulletListItemNode' => 'Document/document/wiki/nodes/bullet_list_item.php', 'ezcDocumentWikiBulletListItemToken' => 'Document/document/wiki/token/bullet_list.php', 'ezcDocumentWikiBulletListNode' => 'Document/document/wiki/nodes/bullet_list.php', 'ezcDocumentWikiCodePlugin' => 'Document/document/wiki/plugin/code.php', 'ezcDocumentWikiConfluenceLinkStartToken' => 'Document/document/wiki/token/confluence_link_start.php', 'ezcDocumentWikiConfluenceTokenizer' => 'Document/document/wiki/tokenizer/confluence.php', 'ezcDocumentWikiCreoleTokenizer' => 'Document/document/wiki/tokenizer/creole.php', 'ezcDocumentWikiDefinitionListItemToken' => 'Document/document/wiki/token/definition_list.php', 'ezcDocumentWikiDeletedNode' => 'Document/document/wiki/nodes/deleted.php', 'ezcDocumentWikiDeletedToken' => 'Document/document/wiki/token/deleted.php', 'ezcDocumentWikiDocbookVisitor' => 'Document/document/wiki/visitor/docbook.php', 'ezcDocumentWikiDocumentNode' => 'Document/document/wiki/nodes/document.php', 'ezcDocumentWikiDokuwikiTokenizer' => 'Document/document/wiki/tokenizer/dokuwiki.php', 'ezcDocumentWikiEndOfFileToken' => 'Document/document/wiki/token/end_of_file.php', 'ezcDocumentWikiEnumeratedListItemNode' => 'Document/document/wiki/nodes/enumerated_list_item.php', 'ezcDocumentWikiEnumeratedListItemToken' => 'Document/document/wiki/token/enumerated_list.php', 'ezcDocumentWikiEnumeratedListNode' => 'Document/document/wiki/nodes/enumerated_list.php', 'ezcDocumentWikiEscapeCharacterToken' => 'Document/document/wiki/token/escape_character.php', 'ezcDocumentWikiExternalLinkNode' => 'Document/document/wiki/nodes/external_link.php', 'ezcDocumentWikiExternalLinkToken' => 'Document/document/wiki/token/external_link.php', 'ezcDocumentWikiFootnoteEndNode' => 'Document/document/wiki/nodes/footnote_end.php', 'ezcDocumentWikiFootnoteEndToken' => 'Document/document/wiki/token/footnote_end.php', 'ezcDocumentWikiFootnoteNode' => 'Document/document/wiki/nodes/footnote.php', 'ezcDocumentWikiFootnoteStartToken' => 'Document/document/wiki/token/footnote_start.php', 'ezcDocumentWikiImageEndNode' => 'Document/document/wiki/nodes/image_end.php', 'ezcDocumentWikiImageEndToken' => 'Document/document/wiki/token/image_end.php', 'ezcDocumentWikiImageNode' => 'Document/document/wiki/nodes/image.php', 'ezcDocumentWikiImageStartToken' => 'Document/document/wiki/token/image_start.php', 'ezcDocumentWikiInlineLiteralNode' => 'Document/document/wiki/nodes/inline_literal.php', 'ezcDocumentWikiInlineLiteralToken' => 'Document/document/wiki/token/inline_literal.php', 'ezcDocumentWikiInlineQuoteNode' => 'Document/document/wiki/nodes/inline_quote.php', 'ezcDocumentWikiInlineQuoteToken' => 'Document/document/wiki/token/inline_quote.php', 'ezcDocumentWikiInterWikiLinkNode' => 'Document/document/wiki/nodes/inter_wiki_link.php', 'ezcDocumentWikiInterWikiLinkToken' => 'Document/document/wiki/token/inter_wiki_link.php', 'ezcDocumentWikiInternalLinkNode' => 'Document/document/wiki/nodes/internal_link.php', 'ezcDocumentWikiInternalLinkToken' => 'Document/document/wiki/token/internal_link.php', 'ezcDocumentWikiInvisibleBreakNode' => 'Document/document/wiki/nodes/invisible_break.php', 'ezcDocumentWikiItalicNode' => 'Document/document/wiki/nodes/italic.php', 'ezcDocumentWikiItalicToken' => 'Document/document/wiki/token/italic.php', 'ezcDocumentWikiLineBreakNode' => 'Document/document/wiki/nodes/line_break.php', 'ezcDocumentWikiLineBreakToken' => 'Document/document/wiki/token/line_break.php', 'ezcDocumentWikiLinkEndNode' => 'Document/document/wiki/nodes/link_end.php', 'ezcDocumentWikiLinkEndToken' => 'Document/document/wiki/token/link_end.php', 'ezcDocumentWikiLinkNode' => 'Document/document/wiki/nodes/link.php', 'ezcDocumentWikiLiteralBlockNode' => 'Document/document/wiki/nodes/literal_block.php', 'ezcDocumentWikiLiteralBlockToken' => 'Document/document/wiki/token/literal_block.php', 'ezcDocumentWikiLiteralLineToken' => 'Document/document/wiki/token/literal_line.php', 'ezcDocumentWikiMediawikiEmphasisToken' => 'Document/document/wiki/token/mediawiki_emphasis.php', 'ezcDocumentWikiMediawikiTokenizer' => 'Document/document/wiki/tokenizer/mediawiki.php', 'ezcDocumentWikiMonospaceNode' => 'Document/document/wiki/nodes/monospace.php', 'ezcDocumentWikiMonospaceToken' => 'Document/document/wiki/token/monospace.php', 'ezcDocumentWikiNewLineToken' => 'Document/document/wiki/token/new_line.php', 'ezcDocumentWikiOptions' => 'Document/options/document_wiki.php', 'ezcDocumentWikiPageBreakNode' => 'Document/document/wiki/nodes/page_break.php', 'ezcDocumentWikiPageBreakToken' => 'Document/document/wiki/token/page_break.php', 'ezcDocumentWikiParagraphIndentationToken' => 'Document/document/wiki/token/indentation.php', 'ezcDocumentWikiParagraphNode' => 'Document/document/wiki/nodes/paragraph.php', 'ezcDocumentWikiParser' => 'Document/document/wiki/parser.php', 'ezcDocumentWikiPluginNode' => 'Document/document/wiki/nodes/plugin.php', 'ezcDocumentWikiPluginToken' => 'Document/document/wiki/token/plugin.php', 'ezcDocumentWikiQuoteToken' => 'Document/document/wiki/token/quote.php', 'ezcDocumentWikiSeparatorToken' => 'Document/document/wiki/token/separator.php', 'ezcDocumentWikiSpecialCharsToken' => 'Document/document/wiki/token/special_chars.php', 'ezcDocumentWikiStrikeToken' => 'Document/document/wiki/token/strike.php', 'ezcDocumentWikiSubscriptNode' => 'Document/document/wiki/nodes/subscript.php', 'ezcDocumentWikiSubscriptToken' => 'Document/document/wiki/token/subscript.php', 'ezcDocumentWikiSuperscriptNode' => 'Document/document/wiki/nodes/superscript.php', 'ezcDocumentWikiSuperscriptToken' => 'Document/document/wiki/token/superscript.php', 'ezcDocumentWikiTableCellNode' => 'Document/document/wiki/nodes/table_cell.php', 'ezcDocumentWikiTableHeaderSeparatorNode' => 'Document/document/wiki/nodes/table_header_separator.php', 'ezcDocumentWikiTableHeaderToken' => 'Document/document/wiki/token/table_header.php', 'ezcDocumentWikiTableNode' => 'Document/document/wiki/nodes/table.php', 'ezcDocumentWikiTableRowNode' => 'Document/document/wiki/nodes/table_row.php', 'ezcDocumentWikiTableRowToken' => 'Document/document/wiki/token/table_row.php', 'ezcDocumentWikiTextLineToken' => 'Document/document/wiki/token/text_line.php', 'ezcDocumentWikiTextNode' => 'Document/document/wiki/nodes/text.php', 'ezcDocumentWikiTitleNode' => 'Document/document/wiki/nodes/title.php', 'ezcDocumentWikiTitleToken' => 'Document/document/wiki/token/title.php', 'ezcDocumentWikiUnderlineNode' => 'Document/document/wiki/nodes/underline.php', 'ezcDocumentWikiUnderlineToken' => 'Document/document/wiki/token/underline.php', 'ezcDocumentWikiWhitespaceToken' => 'Document/document/wiki/token/whitespace.php', 'ezcDocumentXhtml' => 'Document/document/xml/xhtml.php', 'ezcDocumentXhtmlBlockquoteElementFilter' => 'Document/document/xml/xhtml/filter/element/blockquote.php', 'ezcDocumentXhtmlContentLocatorFilter' => 'Document/document/xml/xhtml/filter/content_locator.php', 'ezcDocumentXhtmlDefinitionListElementFilter' => 'Document/document/xml/xhtml/filter/element/definitionlist.php', 'ezcDocumentXhtmlElementFilter' => 'Document/document/xml/xhtml/filter/element.php', 'ezcDocumentXhtmlElementMappingFilter' => 'Document/document/xml/xhtml/filter/element/mapping.php', 'ezcDocumentXhtmlEnumeratedElementFilter' => 'Document/document/xml/xhtml/filter/element/enumerated.php', 'ezcDocumentXhtmlFootnoteElementFilter' => 'Document/document/xml/xhtml/filter/element/footnote.php', 'ezcDocumentXhtmlHeaderElementFilter' => 'Document/document/xml/xhtml/filter/element/header.php', 'ezcDocumentXhtmlImageElementFilter' => 'Document/document/xml/xhtml/filter/element/image.php', 'ezcDocumentXhtmlLineBlockElementFilter' => 'Document/document/xml/xhtml/filter/element/lineblock.php', 'ezcDocumentXhtmlLinkElementFilter' => 'Document/document/xml/xhtml/filter/element/link.php', 'ezcDocumentXhtmlLiteralElementFilter' => 'Document/document/xml/xhtml/filter/element/literal.php', 'ezcDocumentXhtmlMetadataFilter' => 'Document/document/xml/xhtml/filter/metadata.php', 'ezcDocumentXhtmlOptions' => 'Document/options/document_xhtml.php', 'ezcDocumentXhtmlParagraphElementFilter' => 'Document/document/xml/xhtml/filter/element/paragraph.php', 'ezcDocumentXhtmlSpecialParagraphElementFilter' => 'Document/document/xml/xhtml/filter/element/special_paragraph.php', 'ezcDocumentXhtmlStrongElementFilter' => 'Document/document/xml/xhtml/filter/element/strong.php', 'ezcDocumentXhtmlTableCellElementFilter' => 'Document/document/xml/xhtml/filter/element/tablecell.php', 'ezcDocumentXhtmlTableElementFilter' => 'Document/document/xml/xhtml/filter/element/table.php', 'ezcDocumentXhtmlTablesFilter' => 'Document/document/xml/xhtml/filter/tables.php', 'ezcDocumentXhtmlTextToParagraphFilter' => 'Document/document/xml/xhtml/filter/element/text.php', 'ezcDocumentXhtmlXpathFilter' => 'Document/document/xml/xhtml/filter/xpath.php', ); ?> mixed) */ protected $properties = array( 'errorReporting' => 15, // E_PARSE | E_ERROR | E_WARNING | E_NOTICE 'validate' => true, ); /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'errorReporting': if ( !is_int( $value ) || ( ( $value & E_PARSE ) === 0 ) ) { throw new ezcBaseValueException( $name, $value, 'int & E_PARSE' ); } $this->properties[$name] = $value; break; case 'validate': if ( !is_bool( $value ) ) { throw new ezcBaseValueException( $name, $value, 'bool' ); } $this->properties[$name] = $value; break; default: throw new ezcBasePropertyNotFoundException( $name ); } } } ?> mixed) */ protected $properties = array( 'errorReporting' => 15, // E_PARSE | E_ERROR | E_WARNING | E_NOTICE ); /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'errorReporting': if ( !is_int( $value ) || ( ( $value & E_PARSE ) === 0 ) ) { throw new ezcBaseValueException( $name, $value, 'int & E_PARSE' ); } $this->properties[$name] = $value; break; default: throw new ezcBasePropertyNotFoundException( $name ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->linkConverter = new ezcDocumentEzXmlDummyLinkConverter(); parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'linkConverter': if ( !is_object( $value ) || ( !$value instanceof ezcDocumentEzXmlLinkConverter ) ) { throw new ezcBaseValueException( $name, $value, 'instanceof ezcDocumentEzXmlLinkConverter' ); } $this->properties[$name] = $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->imageDir = sys_get_temp_dir(); parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'imageDir': if ( !is_string( $value ) || !is_dir( $value ) || !is_writeable( $value ) ) { throw new ezcBaseValueException( $name, $value, 'Path to a writeable directory.' ); } break; default: parent::__set( $name, $value ); } $this->properties[$name] = $value; } } ?> mixed) */ protected $properties = array( 'errorReporting' => 15, // E_PARSE | E_ERROR | E_WARNING | E_NOTICE ); /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'errorReporting': if ( !is_int( $value ) || ( ( $value & E_PARSE ) === 0 ) ) { throw new ezcBaseValueException( $name, $value, 'int & E_PARSE' ); } $this->properties[$name] = $value; break; default: throw new ezcBasePropertyNotFoundException( $name ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->dublinCoreMetadata = false; $this->formatOutput = false; $this->styleSheets = null; $this->styleSheet = file_get_contents( dirname( __FILE__ ) . '/data/html_style.css' ); $this->headerLevel = 1; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'formatOutput': case 'dublinCoreMetadata': if ( !is_bool( $value ) ) { throw new ezcBaseValueException( $name, $value, 'boolean' ); } $this->properties[$name] = $value; break; case 'styleSheets': if ( !is_array( $value ) && !is_null( $value ) ) { throw new ezcBaseValueException( $name, $value, 'null OR array( URL )' ); } $this->properties[$name] = $value; break; case 'styleSheet': $this->properties[$name] = (string) $value; break; case 'headerLevel': if ( !is_int( $value ) || ( $value > 6 ) || ( $value < 0 ) ) { throw new ezcBaseValueException( $name, $value, '0 < int < 7' ); } $this->properties[$name] = $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->properties['docbookVisitor'] = 'ezcDocumentRstDocbookVisitor'; $this->properties['xhtmlVisitor'] = 'ezcDocumentRstXhtmlVisitor'; $this->properties['xhtmlVisitorOptions'] = new ezcDocumentHtmlConverterOptions(); parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'docbookVisitor': case 'xhtmlVisitor': if ( !is_string( $value ) ) { throw new ezcBaseValueException( $name, $value, 'classname' ); } $this->properties[$name] = $value; break; case 'xhtmlVisitorOptions': if ( !is_object( $value ) || !( $value instanceof ezcDocumentHtmlConverterOptions ) ) { throw new ezcBaseValueException( $name, $value, 'instanceof ezcDocumentHtmlConverterOptions' ); } $this->properties[$name] = $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->wordWrap = 78; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'wordWrap': if ( !is_numeric( $value ) ) { throw new ezcBaseValueException( $name, $value, 'int' ); } $this->properties[$name] = (int) $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->properties['tokenizer'] = new ezcDocumentWikiCreoleTokenizer(); parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'tokenizer': if ( !is_object( $value ) || !( $value instanceof ezcDocumentWikiTokenizer ) ) { throw new ezcBaseValueException( $name, $value, 'instanceof ezcDocumentWikiTokenizer' ); } $this->properties[$name] = $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->headerTypes = array( '==', '--', '=', '-', '^', '~', '`', '*', ':', '+', '/', '.', ); $this->wordWrap = 78; $this->itemListCharacter = '-'; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'headerTypes': if ( !is_array( $value ) ) { throw new ezcBaseValueException( $name, $value, 'array' ); } $this->properties[$name] = $value; break; case 'wordWrap': if ( !is_numeric( $value ) ) { throw new ezcBaseValueException( $name, $value, 'int' ); } $this->properties[$name] = (int) $value; break; case 'itemListCharacter': if ( !in_array( $value, $listCharacters = array( '*', '-', '+', "\xe2\x80\xa2", "\xe2\x80\xa3", "\xe2\x81\x83" ), true ) ) { throw new ezcBaseValueException( $name, $value, 'Item list characters: ' . implode( ', ', $listCharacters ) ); } $this->properties[$name] = $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->relaxNgSchema = dirname( __FILE__ ) . '/../document/xml/ezxml/schema/ezxml_schema.rng'; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'relaxNgSchema': if ( !is_file( $value ) || !is_readable( $value ) ) { throw new ezcBaseValueException( $name, $value, 'RelaxNG schema file' ); } $this->properties[$name] = (string) $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->properties['tags'] = new ArrayObject(); $this->properties['tags']['b'] = new ezcDocumentBBCodeEmphasisPlugin(); $this->properties['tags']['i'] = new ezcDocumentBBCodeEmphasisPlugin(); $this->properties['tags']['u'] = new ezcDocumentBBCodeEmphasisPlugin(); $this->properties['tags']['size'] = new ezcDocumentBBCodeNoMarkupPlugin(); $this->properties['tags']['color'] = new ezcDocumentBBCodeNoMarkupPlugin(); $this->properties['tags']['quote'] = new ezcDocumentBBCodeQuotePlugin(); $this->properties['tags']['url'] = new ezcDocumentBBCodeUrlPlugin(); $this->properties['tags']['email'] = new ezcDocumentBBCodeEmailPlugin(); $this->properties['tags']['img'] = new ezcDocumentBBCodeImagePlugin(); parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { /* case 'tokenizer': if ( !is_object( $value ) || !( $value instanceof ezcDocumentBBCodeTokenizer ) ) { throw new ezcBaseValueException( $name, $value, 'instanceof ezcDocumentBBCodeTokenizer' ); } $this->properties[$name] = $value; break; */ default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->height = '15mm'; $this->footer = true; $this->showDocumentTitle = true; $this->showDocumentAuthor = true; $this->showPageNumber = true; $this->pageNumberOffset = 0; $this->centerPageNumber = false; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'footer': case 'showDocumentTitle': case 'showDocumentAuthor': case 'showPageNumber': case 'centerPageNumber': if ( !is_bool( $value ) ) { throw new ezcBaseValueException( $name, $value, 'boolean' ); } $this->properties[$name] = $value; break; case 'height': $this->properties[$name] = ezcDocumentPcssMeasure::create( $value ); break; case 'pageNumberOffset': if ( !is_int( $value ) ) { throw new ezcBaseValueException( $name, $value, 'int' ); } $this->properties[$name] = $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->xslt = 'http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl'; $this->parameters = array( '' => array( 'make.valid.html' => '1', ), ); parent::__construct( $options ); } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->xmlHeader = false; parent::__construct( $options ); // Do not fail on error by default in (X)Html documents, as they // often contain errors. $this->failOnError = false; } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'xmlHeader': if ( !is_bool( $value ) ) { throw new ezcBaseValueException( $name, $value, 'bool' ); } $this->properties[$name] = (bool) $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->indentXml = false; $this->failOnError = true; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'indentXml': case 'failOnError': if ( !is_bool( $value ) ) { throw new ezcBaseValueException( $name, $value, 'bool' ); } $this->properties[$name] = (bool) $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->linkProvider = new ezcDocumentEzXmlDummyLinkProvider(); parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'linkProvider': if ( !is_object( $value ) || ( !$value instanceof ezcDocumentEzXmlLinkProvider ) ) { throw new ezcBaseValueException( $name, $value, 'instanceof ezcDocumentEzXmlLinkProvider' ); } $this->properties[$name] = $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->hyphenator = new ezcDocumentPdfDefaultHyphenator(); $this->tokenizer = new ezcDocumentPdfDefaultTokenizer(); $this->tableColumnWidthCalculator = new ezcDocumentPdfDefaultTableColumnWidthCalculator(); $this->compress = false; $this->permissions = -1; $this->ownerPassword = null; $this->userPassword = null; $this->properties['driver'] = null; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'hyphenator': if ( !$value instanceof ezcDocumentPdfHyphenator ) { throw new ezcBaseValueException( $name, $value, 'instanceof ezcDocumentPdfHyphenator' ); } $this->properties[$name] = $value; break; case 'tokenizer': if ( !$value instanceof ezcDocumentPdfTokenizer ) { throw new ezcBaseValueException( $name, $value, 'instanceof ezcDocumentPdfTokenizer' ); } $this->properties[$name] = $value; break; case 'driver': if ( !$value instanceof ezcDocumentPdfDriver ) { throw new ezcBaseValueException( $name, $value, 'instanceof ezcDocumentPdfDriver' ); } $this->properties[$name] = $value; break; case 'tableColumnWidthCalculator': if ( !$value instanceof ezcDocumentPdfTableColumnWidthCalculator ) { throw new ezcBaseValueException( $name, $value, 'instanceof ezcDocumentPdfTableColumnWidthCalculator' ); } $this->properties[$name] = $value; break; case 'compress': if ( !is_bool( $value ) ) { throw new ezcBaseValueException( $name, $value, 'bool' ); } $this->properties[$name] = $value; break; case 'ownerPassword': case 'userPassword': if ( !is_string( $value ) && !is_null( $value ) ) { throw new ezcBaseValueException( $name, $value, 'string OR null' ); } if ( ( $name === 'userPassword' ) && ( $value !== null ) && ( $this->properties['ownerPassword'] === null ) ) { throw new ezcBaseValueException( $name, $value, 'ownerPassword must be specified, before a userPassword can be set.' ); } $this->properties[$name] = $value; break; case 'permissions': if ( !is_int( $value ) ) { throw new ezcBaseValueException( $name, $value, 'Vitwise combination of ezcDocumentPdfOptions::EDIT, ezcDocumentPdfOptions::PRINTABLE, ezcDocumentPdfOptions::MODIFY, ezcDocumentPdfOptions::COPY' ); } $this->properties[$name] = (int) $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->schema = dirname( __FILE__ ) . '/data/docbook.xsd'; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'schema': if ( !is_file( $value ) || !is_readable( $value ) ) { throw new ezcBaseValueException( $name, $value, 'XML schema file' ); } $this->properties[$name] = (string) $value; break; default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { default: parent::__set( $name, $value ); } } } ?> mixed) $options */ public function __construct( array $options = array() ) { $this->template = dirname( __FILE__ ) . '/data/template.fodt'; $this->styler = new ezcDocumentOdtPcssStyler(); $this->lengthMeasure = 'px'; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'template': if ( !is_string( $value ) || !is_file( $value ) || !is_readable( $value ) ) { throw new ezcBaseValueException( $name, $value, 'file, readable' ); } break; case 'styler': if ( !is_object( $value ) || !( $value instanceof ezcDocumentOdtStyler ) ) { throw new ezcBaseValueException( $name, $value, 'ezcDocumentOdtStyler' ); } break; case 'lengthMeasure': if ( !is_string( $value ) || !in_array( $value, self::$validLengthMeasures ) ) { throw new ezcBaseValueException( $name, $value, implode( ', ', self::$validLengthMeasures ) ); } break; default: parent::__set( $name, $value ); break; } $this->properties[$name] = $value; } } ?> array( * 'option' => 'value' ) ), where namespace may also be an empty * string. * @property boolean $failOnError * Boolean indicator if the conversion should be aborted, when errors * occurs with an exception, or if the errors just should be ignored. * * @package Document * @version //autogen// */ class ezcDocumentXsltConverterOptions extends ezcDocumentConverterOptions { /** * Constructs an object with the specified values. * * @throws ezcBasePropertyNotFoundException * if $options contains a property not defined * @throws ezcBaseValueException * if $options contains a property with a value not allowed * @param array(string=>mixed) $options */ public function __construct( array $options = array() ) { if ( !isset( $this->properties['xslt'] ) ) { $this->properties['xslt'] = null; } if ( !isset( $this->properties['parameters'] ) ) { $this->parameters = array(); } $this->properties['failOnError'] = false; parent::__construct( $options ); } /** * Sets the option $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name is not defined * @throws ezcBaseValueException * if $value is not correct for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'xslt': $this->properties[$name] = (string) $value; break; case 'parameters': if ( !is_array( $value ) ) { throw new ezcBaseValueException( $name, $value, 'array' ); } $this->properties[$name] = $value; break; case 'failOnError': if ( !is_bool( $value ) ) { throw new ezcBaseValueException( $name, $value, 'boolean' ); } $this->properties[$name] = (bool) $value; break; default: parent::__set( $name, $value ); } } } ?> options = ( $options === null ? new ezcDocumentOptions() : $options ); } /** * Trigger visitor error * * Emit a vistitor error, and convert it to an exception depending on the * error reporting settings. * * @param int $level * @param string $message * @param string $file * @param int $line * @param int $position * @return void */ public function triggerError( $level, $message, $file = null, $line = null, $position = null ) { if ( $level & $this->options->errorReporting ) { throw new ezcDocumentVisitException( $level, $message, $file, $line, $position ); } else { // If the error should not been reported, we aggregate it to maybe // display it later. $this->errors[] = new ezcDocumentVisitException( $level, $message, $file, $line, $position ); } } /** * Return list of errors occured during visiting the document. * * May be an empty array, if on errors occured, or a list of * ezcDocumentVisitException objects. * * @return array */ public function getErrors() { return $this->errors; } /** * Create document from input string * * Create a document of the current type handler class and parse it into a * usable internal structure. * * @param string $string * @return void */ abstract public function loadString( $string ); /** * Create document from file * * Create a document of the current type handler class and parse it into a * usable internal structure. The default implementation just calls * loadString(), but you may want to provide an optimized implementation. * * @param string $file * @return void */ public function loadFile( $file ) { if ( !file_exists( $file ) || !is_readable( $file ) ) { throw new ezcBaseFileNotFoundException( $file ); } $this->path = realpath( dirname( $file ) ) . '/'; $this->loadString( file_get_contents( $file ) ); } /** * Get document base path * * @return string */ public function getPath() { return $this->path; } /** * Set document base path * * The base path will be used as a base for relative file * inclusions in the document. * * @param string $path */ public function setPath( $path ) { $this->path = $path; } /** * Return document compiled to the docbook format * * The internal document structure is compiled to the docbook format and * the resulting docbook document is returned. * * This method is required for all formats to have one central format, so * that each format can be compiled into each other format using docbook as * an intermediate format. * * You may of course just call an existing converter for this conversion. * * @return ezcDocumentDocbook */ abstract public function getAsDocbook(); /** * Create document from docbook document * * A document of the docbook format is provided and the internal document * structure should be created out of this. * * This method is required for all formats to have one central format, so * that each format can be compiled into each other format using docbook as * an intermediate format. * * You may of course just call an existing converter for this conversion. * * @param ezcDocumentDocbook $document * @return void */ abstract public function createFromDocbook( ezcDocumentDocbook $document ); /** * Return document as string * * Serialize the document to a string an return it. * * @return string */ abstract public function save(); /** * Magic wrapper for save() * * @ignore * @return string */ public function __toString() { return $this->save(); } /** * Returns the value of the property $name. * * @throws ezcBasePropertyNotFoundException * if the property $name does not exist * @param string $name * @ignore */ public function __get( $name ) { switch ( $name ) { case 'options': return $this->options; } throw new ezcBasePropertyNotFoundException( $name ); } /** * Sets the property $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name does not exist * @throws ezcBaseValueException * if $value is not accepted for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'options': if ( !( $value instanceof ezcDocumentOptions ) ) { throw new ezcBaseValueException( 'options', $value, 'instanceof ezcDocumentOptions' ); } $this->options = $value; break; default: throw new ezcBasePropertyNotFoundException( $name ); } } /** * Returns true if the property $name is set, otherwise false. * * @param string $name * @return bool * @ignore */ public function __isset( $name ) { switch ( $name ) { case 'options': return true; default: return false; } } } ?> array(), ); /** * Construct new document * * @param ezcDocumentParserOptions $options */ public function __construct( ezcDocumentParserOptions $options = null ) { $this->options = ( $options === null ? new ezcDocumentParserOptions() : $options ); } /** * Trigger parser error * * Emit a parser error and handle it dependiing on the current error * reporting settings. * * @param int $level * @param string $message * @param string $file * @param int $line * @param int $position * @return void */ public function triggerError( $level, $message, $file = null, $line = null, $position = null ) { if ( $level & $this->options->errorReporting ) { throw new ezcDocumentParserException( $level, $message, $file, $line, $position ); } // For lower error level settings, just aggregate errors $this->properties['errors'][] = new ezcDocumentParserException( $level, $message, $file, $line, $position ); } /** * Return list of errors occured during visiting the document. * * May be an empty array, if on errors occured, or a list of * ezcDocumentVisitException objects. * * @return array */ public function getErrors() { return $this->properties['errors']; } /** * Returns the value of the property $name. * * @throws ezcBasePropertyNotFoundException * if the property $name does not exist * @param string $name * @ignore */ public function __get( $name ) { switch ( $name ) { case 'options': return $this->options; case 'errors': return $this->properties['errors']; } throw new ezcBasePropertyNotFoundException( $name ); } /** * Sets the property $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name does not exist * @throws ezcBaseValueException * if $value is not accepted for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'options': if ( !( $value instanceof ezcDocumentParserOptions ) ) { throw new ezcBaseValueException( 'options', $value, 'instanceof ezcDocumentParserOptions' ); } $this->options = $value; break; case 'errors': throw new ezcBasePropertyPermissionException( $name, ezcBasePropertyPermissionException::READ ); default: throw new ezcBasePropertyNotFoundException( $name ); } } /** * Returns true if the property $name is set, otherwise false. * * @param string $name * @return bool * @ignore */ public function __isset( $name ) { switch ( $name ) { case 'options': return true; default: return false; } } } ?> array(), ); /** * Construct new document * * @param ezcDocumentConverterOptions $options */ public function __construct( ezcDocumentConverterOptions $options = null ) { $this->options = ( $options === null ? new ezcDocumentConverterOptions() : $options ); } /** * Convert documents between two formats * * Convert documents of the given type to the requested type. * * @param ezcDocument $doc * @return ezcDocument */ abstract public function convert( $doc ); /** * Trigger parser error * * Emit a parser error and handle it dependiing on the current error * reporting settings. * * @param int $level * @param string $message * @param string $file * @param int $line * @param int $position * @return void */ public function triggerError( $level, $message, $file = null, $line = null, $position = null ) { if ( $level & $this->options->errorReporting ) { throw new ezcDocumentConversionException( $level, $message, $file, $line, $position ); } // For lower error level settings, just aggregate errors $this->properties['errors'][] = new ezcDocumentParserException( $level, $message, $file, $line, $position ); } /** * Return list of errors occured during visiting the document. * * May be an empty array, if on errors occured, or a list of * ezcDocumentVisitException objects. * * @return array */ public function getErrors() { return $this->properties['errors']; } /** * Returns the value of the property $name. * * @throws ezcBasePropertyNotFoundException * if the property $name does not exist * @param string $name * @ignore */ public function __get( $name ) { switch ( $name ) { case 'options': return $this->options; case 'errors': return $this->properties['errors']; } throw new ezcBasePropertyNotFoundException( $name ); } /** * Sets the property $name to $value. * * @throws ezcBasePropertyNotFoundException * if the property $name does not exist * @throws ezcBaseValueException * if $value is not accepted for the property $name * @param string $name * @param mixed $value * @ignore */ public function __set( $name, $value ) { switch ( $name ) { case 'options': if ( !( $value instanceof ezcDocumentConverterOptions ) ) { throw new ezcBaseValueException( 'options', $value, 'instanceof ezcDocumentConverterOptions' ); } $this->options = $value; break; case 'errors': throw new ezcBasePropertyPermissionException( $name, ezcBasePropertyPermissionException::READ ); default: throw new ezcBasePropertyNotFoundException( $name ); } } /** * Returns true if the property $name is set, otherwise false. * * @param string $name * @return bool * @ignore */ public function __isset( $name ) { switch ( $name ) { case 'options': return true; default: return false; } } } ?> Copyright (c) 2016 Nils Adermann, Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. [ { "name": "symfony/process", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/Process", "source": { "type": "git", "url": "https://github.com/symfony/process.git", "reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/process/zipball/57f1e88bb5dafa449b83f9f265b11d52d517b3e9", "reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "time": "2015-06-30 16:10:16", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Process\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Process Component", "homepage": "https://symfony.com" }, { "name": "symfony/finder", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/Finder", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", "reference": "203a10f928ae30176deeba33512999233181dd28" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/finder/zipball/203a10f928ae30176deeba33512999233181dd28", "reference": "203a10f928ae30176deeba33512999233181dd28", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "time": "2015-07-09 16:02:48", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Finder\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Finder Component", "homepage": "https://symfony.com" }, { "name": "pimple/pimple", "version": "v1.1.1", "version_normalized": "1.1.1.0", "source": { "type": "git", "url": "https://github.com/silexphp/Pimple.git", "reference": "2019c145fe393923f3441b23f29bbdfaa5c58c4d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/silexphp/Pimple/zipball/2019c145fe393923f3441b23f29bbdfaa5c58c4d", "reference": "2019c145fe393923f3441b23f29bbdfaa5c58c4d", "shasum": "" }, "require": { "php": ">=5.3.0" }, "time": "2013-11-22 08:30:29", "type": "library", "extra": { "branch-alias": { "dev-master": "1.1.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Pimple": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" } ], "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", "homepage": "http://pimple.sensiolabs.org", "keywords": [ "container", "dependency injection" ] }, { "name": "symfony/console", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/console.git", "reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/console/zipball/0e5e18ae09d3f5c06367759be940e9ed3f568359", "reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "psr/log": "~1.0", "symfony/event-dispatcher": "~2.1", "symfony/phpunit-bridge": "~2.7", "symfony/process": "~2.1" }, "suggest": { "psr/log": "For using the console logger", "symfony/event-dispatcher": "", "symfony/process": "" }, "time": "2015-07-26 09:08:40", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Console\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Console Component", "homepage": "https://symfony.com" }, { "name": "cilex/console-service-provider", "version": "1.0.0", "version_normalized": "1.0.0.0", "source": { "type": "git", "url": "https://github.com/Cilex/console-service-provider.git", "reference": "25ee3d1875243d38e1a3448ff94bdf944f70d24e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Cilex/console-service-provider/zipball/25ee3d1875243d38e1a3448ff94bdf944f70d24e", "reference": "25ee3d1875243d38e1a3448ff94bdf944f70d24e", "shasum": "" }, "require": { "php": ">=5.3.3", "pimple/pimple": "1.*@dev", "symfony/console": "~2.1" }, "require-dev": { "cilex/cilex": "1.*@dev", "silex/silex": "1.*@dev" }, "time": "2012-12-19 10:50:58", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Cilex\\Provider\\Console": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Beau Simensen", "email": "beau@dflydev.com", "homepage": "http://beausimensen.com" }, { "name": "Mike van Riel", "email": "mike.vanriel@naenius.com" } ], "description": "Console Service Provider", "keywords": [ "cilex", "console", "pimple", "service-provider", "silex" ] }, { "name": "cilex/cilex", "version": "1.1.0", "version_normalized": "1.1.0.0", "source": { "type": "git", "url": "https://github.com/Cilex/Cilex.git", "reference": "7acd965a609a56d0345e8b6071c261fbdb926cb5" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Cilex/Cilex/zipball/7acd965a609a56d0345e8b6071c261fbdb926cb5", "reference": "7acd965a609a56d0345e8b6071c261fbdb926cb5", "shasum": "" }, "require": { "cilex/console-service-provider": "1.*", "php": ">=5.3.3", "pimple/pimple": "~1.0", "symfony/finder": "~2.1", "symfony/process": "~2.1" }, "require-dev": { "phpunit/phpunit": "3.7.*", "symfony/validator": "~2.1" }, "suggest": { "monolog/monolog": ">=1.0.0", "symfony/validator": ">=1.0.0", "symfony/yaml": ">=1.0.0" }, "time": "2014-03-29 14:03:13", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Cilex": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Mike van Riel", "email": "mike.vanriel@naenius.com" } ], "description": "The PHP micro-framework for Command line tools based on the Symfony2 Components", "homepage": "http://cilex.github.com", "keywords": [ "cli", "microframework" ] }, { "name": "doctrine/lexer", "version": "v1.0.1", "version_normalized": "1.0.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", "shasum": "" }, "require": { "php": ">=5.3.2" }, "time": "2014-09-09 13:34:57", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Doctrine\\Common\\Lexer\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Roman Borschel", "email": "roman@code-factory.org" }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", "homepage": "http://www.doctrine-project.org", "keywords": [ "lexer", "parser" ] }, { "name": "erusev/parsedown", "version": "1.6.0", "version_normalized": "1.6.0.0", "source": { "type": "git", "url": "https://github.com/erusev/parsedown.git", "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/erusev/parsedown/zipball/3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", "reference": "3ebbd730b5c2cf5ce78bc1bf64071407fc6674b7", "shasum": "" }, "time": "2015-10-04 16:44:32", "type": "library", "installation-source": "dist", "autoload": { "psr-0": { "Parsedown": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Emanuil Rusev", "email": "hello@erusev.com", "homepage": "http://erusev.com" } ], "description": "Parser for Markdown.", "homepage": "http://parsedown.org", "keywords": [ "markdown", "parser" ] }, { "name": "kherge/version", "version": "1.0.1", "version_normalized": "1.0.1.0", "source": { "type": "git", "url": "https://github.com/kherge-abandoned/Version.git", "reference": "f07cf83f8ce533be8f93d2893d96d674bbeb7e30" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/kherge-abandoned/Version/zipball/f07cf83f8ce533be8f93d2893d96d674bbeb7e30", "reference": "f07cf83f8ce533be8f93d2893d96d674bbeb7e30", "shasum": "" }, "require": { "php": ">=5.3.3" }, "time": "2012-08-16 17:13:03", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "KevinGH\\Version": "src/lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Kevin Herrera", "email": "me@kevingh.com" } ], "description": "A parsing and comparison library for semantic versioning.", "homepage": "http://github.com/kherge/Version" }, { "name": "seld/jsonlint", "version": "1.3.1", "version_normalized": "1.3.1.0", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", "reference": "863ae85c6d3ef60ca49cb12bd051c4a0648c40c4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/863ae85c6d3ef60ca49cb12bd051c4a0648c40c4", "reference": "863ae85c6d3ef60ca49cb12bd051c4a0648c40c4", "shasum": "" }, "require": { "php": ">=5.3.0" }, "time": "2015-01-04 21:18:15", "bin": [ "bin/jsonlint" ], "type": "library", "installation-source": "dist", "autoload": { "psr-4": { "Seld\\JsonLint\\": "src/Seld/JsonLint/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http://seld.be" } ], "description": "JSON Linter", "keywords": [ "json", "linter", "parser", "validator" ] }, { "name": "justinrainbow/json-schema", "version": "1.5.0", "version_normalized": "1.5.0.0", "source": { "type": "git", "url": "https://github.com/justinrainbow/json-schema.git", "reference": "a4bee9f4b344b66e0a0d96c7afae1e92edf385fe" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/a4bee9f4b344b66e0a0d96c7afae1e92edf385fe", "reference": "a4bee9f4b344b66e0a0d96c7afae1e92edf385fe", "shasum": "" }, "require": { "php": ">=5.3.2" }, "require-dev": { "json-schema/json-schema-test-suite": "1.1.0", "phpdocumentor/phpdocumentor": "~2", "phpunit/phpunit": "~3.7" }, "time": "2015-09-08 22:28:04", "bin": [ "bin/validate-json" ], "type": "library", "extra": { "branch-alias": { "dev-master": "1.4.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "JsonSchema\\": "src/JsonSchema/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Bruno Prieto Reis", "email": "bruno.p.reis@gmail.com" }, { "name": "Justin Rainbow", "email": "justin.rainbow@gmail.com" }, { "name": "Igor Wiedler", "email": "igor@wiedler.ch" }, { "name": "Robert Schönthal", "email": "seroscho@googlemail.com" } ], "description": "A library to validate a json schema.", "homepage": "https://github.com/justinrainbow/json-schema", "keywords": [ "json", "schema" ] }, { "name": "herrera-io/json", "version": "1.0.3", "version_normalized": "1.0.3.0", "source": { "type": "git", "url": "https://github.com/kherge-abandoned/php-json.git", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/kherge-abandoned/php-json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1", "shasum": "" }, "require": { "ext-json": "*", "justinrainbow/json-schema": ">=1.0,<2.0-dev", "php": ">=5.3.3", "seld/jsonlint": ">=1.0,<2.0-dev" }, "require-dev": { "herrera-io/phpunit-test-case": "1.*", "mikey179/vfsstream": "1.1.0", "phpunit/phpunit": "3.7.*" }, "time": "2013-10-30 16:51:34", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0-dev" } }, "installation-source": "dist", "autoload": { "files": [ "src/lib/json_version.php" ], "psr-0": { "Herrera\\Json": "src/lib" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Kevin Herrera", "email": "kevin@herrera.io", "homepage": "http://kevin.herrera.io" } ], "description": "A library for simplifying JSON linting and validation.", "homepage": "http://herrera-io.github.com/php-json", "keywords": [ "json", "lint", "schema", "validate" ] }, { "name": "herrera-io/phar-update", "version": "1.0.3", "version_normalized": "1.0.3.0", "source": { "type": "git", "url": "https://github.com/kherge-abandoned/php-phar-update.git", "reference": "00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/kherge-abandoned/php-phar-update/zipball/00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b", "reference": "00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b", "shasum": "" }, "require": { "herrera-io/json": "1.*", "kherge/version": "1.*", "php": ">=5.3.3" }, "require-dev": { "herrera-io/phpunit-test-case": "1.*", "mikey179/vfsstream": "1.1.0", "phpunit/phpunit": "3.7.*" }, "time": "2013-10-30 17:23:01", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0-dev" } }, "installation-source": "dist", "autoload": { "files": [ "src/lib/constants.php" ], "psr-0": { "Herrera\\Phar\\Update": "src/lib" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Kevin Herrera", "email": "kevin@herrera.io", "homepage": "http://kevin.herrera.io" } ], "description": "A library for self-updating Phars.", "homepage": "http://herrera-io.github.com/php-phar-update", "keywords": [ "phar", "update" ] }, { "name": "phpoption/phpoption", "version": "1.5.0", "version_normalized": "1.5.0.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/94e644f7d2051a5f0fcf77d81605f152eecff0ed", "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { "phpunit/phpunit": "4.7.*" }, "time": "2015-07-25 16:39:46", "type": "library", "extra": { "branch-alias": { "dev-master": "1.3-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "PhpOption\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "Apache2" ], "authors": [ { "name": "Johannes M. Schmitt", "email": "schmittjoh@gmail.com" } ], "description": "Option Type for PHP", "keywords": [ "language", "option", "php", "type" ] }, { "name": "phpcollection/phpcollection", "version": "0.2.0", "version_normalized": "0.2.0.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-collection.git", "reference": "acb02a921bb364f360ce786b13455345063c4a07" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/schmittjoh/php-collection/zipball/acb02a921bb364f360ce786b13455345063c4a07", "reference": "acb02a921bb364f360ce786b13455345063c4a07", "shasum": "" }, "require": { "phpoption/phpoption": "1.*" }, "time": "2013-01-23 15:16:14", "type": "library", "extra": { "branch-alias": { "dev-master": "0.2-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "PhpCollection": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "Apache2" ], "authors": [ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], "description": "General-Purpose Collection Library for PHP", "keywords": [ "collection", "list", "map", "sequence", "set" ] }, { "name": "jms/parser-lib", "version": "1.0.0", "version_normalized": "1.0.0.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/parser-lib.git", "reference": "c509473bc1b4866415627af0e1c6cc8ac97fa51d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/schmittjoh/parser-lib/zipball/c509473bc1b4866415627af0e1c6cc8ac97fa51d", "reference": "c509473bc1b4866415627af0e1c6cc8ac97fa51d", "shasum": "" }, "require": { "phpoption/phpoption": ">=0.9,<2.0-dev" }, "time": "2012-11-18 18:08:43", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "JMS\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "Apache2" ], "description": "A library for easily creating recursive-descent parsers." }, { "name": "jms/metadata", "version": "1.5.1", "version_normalized": "1.5.1.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/metadata.git", "reference": "22b72455559a25777cfd28c4ffda81ff7639f353" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/22b72455559a25777cfd28c4ffda81ff7639f353", "reference": "22b72455559a25777cfd28c4ffda81ff7639f353", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { "doctrine/cache": "~1.0" }, "time": "2014-07-12 07:13:19", "type": "library", "extra": { "branch-alias": { "dev-master": "1.5.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Metadata\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "Apache" ], "authors": [ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], "description": "Class/method/property metadata management in PHP", "keywords": [ "annotations", "metadata", "xml", "yaml" ] }, { "name": "doctrine/annotations", "version": "v1.2.7", "version_normalized": "1.2.7.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535", "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535", "shasum": "" }, "require": { "doctrine/lexer": "1.*", "php": ">=5.3.2" }, "require-dev": { "doctrine/cache": "1.*", "phpunit/phpunit": "4.*" }, "time": "2015-08-31 12:32:49", "type": "library", "extra": { "branch-alias": { "dev-master": "1.3.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Doctrine\\Common\\Annotations\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Roman Borschel", "email": "roman@code-factory.org" }, { "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], "description": "Docblock Annotations Parser", "homepage": "http://www.doctrine-project.org", "keywords": [ "annotations", "docblock", "parser" ] }, { "name": "jms/serializer", "version": "0.12.0", "version_normalized": "0.12.0.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/serializer.git", "reference": "f901383fd3fb5faa55fdf82558a08e7773050d78" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/f901383fd3fb5faa55fdf82558a08e7773050d78", "reference": "f901383fd3fb5faa55fdf82558a08e7773050d78", "shasum": "" }, "require": { "doctrine/annotations": "1.*", "jms/metadata": "~1.1", "jms/parser-lib": "1.*", "php": ">=5.3.2", "phpcollection/phpcollection": ">=0.1,<0.3-dev" }, "require-dev": { "doctrine/orm": ">=2.1,<2.4-dev", "symfony/filesystem": "2.*", "symfony/form": ">=2.1,<2.2-dev", "symfony/translation": ">=2.0,<2.2-dev", "symfony/validator": ">=2.0,<2.2-dev", "symfony/yaml": "2.*", "twig/twig": ">=1.8,<2.0-dev" }, "suggest": { "symfony/yaml": "Required if you'd like to serialize data to YAML format." }, "time": "2013-03-28 16:41:24", "type": "library", "extra": { "branch-alias": { "dev-master": "0.12-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "JMS\\Serializer": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "Apache2" ], "authors": [ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.", "homepage": "http://jmsyst.com/libs/serializer", "keywords": [ "deserialization", "jaxb", "json", "serialization", "xml" ] }, { "name": "psr/log", "version": "1.0.0", "version_normalized": "1.0.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", "shasum": "" }, "time": "2012-12-21 11:40:51", "type": "library", "installation-source": "dist", "autoload": { "psr-0": { "Psr\\Log\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "http://www.php-fig.org/" } ], "description": "Common interface for logging libraries", "keywords": [ "log", "psr", "psr-3" ] }, { "name": "monolog/monolog", "version": "1.19.0", "version_normalized": "1.19.0.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", "reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5f56ed5212dc509c8dc8caeba2715732abb32dbf", "reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf", "shasum": "" }, "require": { "php": ">=5.3.0", "psr/log": "~1.0" }, "provide": { "psr/log-implementation": "1.0.0" }, "require-dev": { "aws/aws-sdk-php": "^2.4.9", "doctrine/couchdb": "~1.0@dev", "graylog2/gelf-php": "~1.0", "jakub-onderka/php-parallel-lint": "0.9", "php-amqplib/php-amqplib": "~2.4", "php-console/php-console": "^3.1.3", "phpunit/phpunit": "~4.5", "phpunit/phpunit-mock-objects": "2.3.0", "raven/raven": "^0.13", "ruflin/elastica": ">=0.90 <3.0", "swiftmailer/swiftmailer": "~5.3" }, "suggest": { "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", "doctrine/couchdb": "Allow sending log messages to a CouchDB server", "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", "ext-mongo": "Allow sending log messages to a MongoDB server", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", "php-console/php-console": "Allow sending log messages to Google Chrome", "raven/raven": "Allow sending log messages to a Sentry server", "rollbar/rollbar": "Allow sending log messages to Rollbar", "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, "time": "2016-04-12 18:29:35", "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Monolog\\": "src/Monolog" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", "homepage": "http://seld.be" } ], "description": "Sends your logs to files, sockets, inboxes, databases and various web services", "homepage": "http://github.com/Seldaek/monolog", "keywords": [ "log", "logging", "psr-3" ] }, { "name": "phpdocumentor/fileset", "version": "1.0.0", "version_normalized": "1.0.0.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/Fileset.git", "reference": "bfa78d8fa9763dfce6d0e5d3730c1d8ab25d34b0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpDocumentor/Fileset/zipball/bfa78d8fa9763dfce6d0e5d3730c1d8ab25d34b0", "reference": "bfa78d8fa9763dfce6d0e5d3730c1d8ab25d34b0", "shasum": "" }, "require": { "php": ">=5.3.3", "symfony/finder": "~2.1" }, "require-dev": { "phpunit/phpunit": "~3.7" }, "time": "2013-08-06 21:07:42", "type": "library", "installation-source": "dist", "autoload": { "psr-0": { "phpDocumentor": [ "src/", "tests/unit/" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Fileset component for collecting a set of files given directories and file paths", "homepage": "http://www.phpdoc.org", "keywords": [ "files", "fileset", "phpdoc" ] }, { "name": "phpdocumentor/graphviz", "version": "1.0.3", "version_normalized": "1.0.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/GraphViz.git", "reference": "aa243118c8a055fc853c02802e8503c5435862f7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpDocumentor/GraphViz/zipball/aa243118c8a055fc853c02802e8503c5435862f7", "reference": "aa243118c8a055fc853c02802e8503c5435862f7", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~3.7" }, "time": "2014-07-19 06:52:59", "type": "library", "installation-source": "dist", "autoload": { "psr-0": { "phpDocumentor": [ "src/", "tests/unit" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Mike van Riel", "email": "mike.vanriel@naenius.com" } ] }, { "name": "phpdocumentor/reflection-docblock", "version": "2.0.4", "version_normalized": "2.0.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.0" }, "suggest": { "dflydev/markdown": "~1.0", "erusev/parsedown": "~1.0" }, "time": "2015-02-03 12:10:50", "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "phpDocumentor": [ "src/" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Mike van Riel", "email": "mike.vanriel@naenius.com" } ] }, { "name": "nikic/php-parser", "version": "v1.4.1", "version_normalized": "1.4.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51", "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=5.3" }, "time": "2015-09-19 14:15:08", "type": "library", "extra": { "branch-alias": { "dev-master": "1.4-dev" } }, "installation-source": "dist", "autoload": { "files": [ "lib/bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Nikita Popov" } ], "description": "A PHP parser written in PHP", "keywords": [ "parser", "php" ] }, { "name": "phpdocumentor/reflection", "version": "3.0.1", "version_normalized": "3.0.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/Reflection.git", "reference": "793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d", "reference": "793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d", "shasum": "" }, "require": { "nikic/php-parser": "^1.0", "php": ">=5.3.3", "phpdocumentor/reflection-docblock": "~2.0", "psr/log": "~1.0" }, "require-dev": { "behat/behat": "~2.4", "mockery/mockery": "~0.8", "phpunit/phpunit": "~4.0" }, "time": "2016-05-21 08:42:32", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "phpDocumentor": [ "src/", "tests/unit/", "tests/mocks/" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Reflection library to do Static Analysis for PHP Projects", "homepage": "http://www.phpdoc.org", "keywords": [ "phpDocumentor", "phpdoc", "reflection", "static analysis" ] }, { "name": "symfony/filesystem", "version": "v2.3.0", "version_normalized": "2.3.0.0", "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", "reference": "93ca76c45530d146d0def76d1eb6f60a939a2104" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/filesystem/zipball/93ca76c45530d146d0def76d1eb6f60a939a2104", "reference": "93ca76c45530d146d0def76d1eb6f60a939a2104", "shasum": "" }, "require": { "php": ">=5.3.3" }, "time": "2013-05-06 20:03:44", "type": "library", "extra": { "branch-alias": { "dev-master": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Filesystem\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" } ], "description": "Symfony Filesystem Component", "homepage": "http://symfony.com" }, { "name": "symfony/config", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/Config", "source": { "type": "git", "url": "https://github.com/symfony/config.git", "reference": "0ca496cbe208fc37c4cf3415ebb3056e0963115b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/config/zipball/0ca496cbe208fc37c4cf3415ebb3056e0963115b", "reference": "0ca496cbe208fc37c4cf3415ebb3056e0963115b", "shasum": "" }, "require": { "php": ">=5.3.3", "symfony/filesystem": "~2.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "time": "2015-07-08 05:59:48", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Config\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Config Component", "homepage": "https://symfony.com" }, { "name": "symfony/event-dispatcher", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/672593bc4b0043a0acf91903bb75a1c82d8f2e02", "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "psr/log": "~1.0", "symfony/config": "~2.0,>=2.0.5", "symfony/dependency-injection": "~2.6", "symfony/expression-language": "~2.6", "symfony/phpunit-bridge": "~2.7", "symfony/stopwatch": "~2.3" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, "time": "2015-05-02 15:18:45", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\EventDispatcher\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com" }, { "name": "symfony/stopwatch", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/Stopwatch", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", "reference": "a0d91f2f4e2c60bd78f13388aa68f9d7cab8c987" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/stopwatch/zipball/a0d91f2f4e2c60bd78f13388aa68f9d7cab8c987", "reference": "a0d91f2f4e2c60bd78f13388aa68f9d7cab8c987", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "time": "2015-07-01 18:23:01", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Stopwatch\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com" }, { "name": "symfony/translation", "version": "v2.3.0", "version_normalized": "2.3.0.0", "target-dir": "Symfony/Component/Translation", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", "reference": "70fddb8499919f459322b9857ada7824722db9df" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/translation/zipball/70fddb8499919f459322b9857ada7824722db9df", "reference": "70fddb8499919f459322b9857ada7824722db9df", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/config": "~2.0", "symfony/yaml": "~2.2" }, "suggest": { "symfony/config": "", "symfony/yaml": "" }, "time": "2013-05-13 14:36:40", "type": "library", "extra": { "branch-alias": { "dev-master": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Translation\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" } ], "description": "Symfony Translation Component", "homepage": "http://symfony.com" }, { "name": "symfony/validator", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/Validator", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", "reference": "fccfab79928e612eedca96dcf3a9e8efd2ee495f" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/validator/zipball/fccfab79928e612eedca96dcf3a9e8efd2ee495f", "reference": "fccfab79928e612eedca96dcf3a9e8efd2ee495f", "shasum": "" }, "require": { "php": ">=5.3.3", "symfony/translation": "~2.0,>=2.0.5" }, "require-dev": { "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", "doctrine/common": "~2.3", "egulias/email-validator": "~1.2,>=1.2.1", "symfony/config": "~2.2", "symfony/expression-language": "~2.4", "symfony/http-foundation": "~2.1", "symfony/intl": "~2.3", "symfony/phpunit-bridge": "~2.7", "symfony/property-access": "~2.3", "symfony/yaml": "~2.0,>=2.0.5" }, "suggest": { "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", "doctrine/cache": "For using the default cached annotation reader and metadata cache.", "egulias/email-validator": "Strict (RFC compliant) email validation", "symfony/config": "", "symfony/expression-language": "For using the 2.4 Expression validator", "symfony/http-foundation": "", "symfony/intl": "", "symfony/property-access": "For using the 2.4 Validator API", "symfony/yaml": "" }, "time": "2015-07-01 19:58:06", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Validator\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Validator Component", "homepage": "https://symfony.com" }, { "name": "twig/twig", "version": "v1.22.2", "version_normalized": "1.22.2.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", "reference": "79249fc8c9ff62e41e217e0c630e2e00bcadda6a" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/twigphp/Twig/zipball/79249fc8c9ff62e41e217e0c630e2e00bcadda6a", "reference": "79249fc8c9ff62e41e217e0c630e2e00bcadda6a", "shasum": "" }, "require": { "php": ">=5.2.7" }, "require-dev": { "symfony/debug": "~2.7", "symfony/phpunit-bridge": "~2.7" }, "time": "2015-09-22 13:59:32", "type": "library", "extra": { "branch-alias": { "dev-master": "1.22-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Twig_": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com", "homepage": "http://fabien.potencier.org", "role": "Lead Developer" }, { "name": "Armin Ronacher", "email": "armin.ronacher@active-4.com", "role": "Project Founder" }, { "name": "Twig Team", "homepage": "http://twig.sensiolabs.org/contributors", "role": "Contributors" } ], "description": "Twig, the flexible, fast, and secure template language for PHP", "homepage": "http://twig.sensiolabs.org", "keywords": [ "templating" ] }, { "name": "zendframework/zend-stdlib", "version": "2.2.10", "version_normalized": "2.2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-stdlib.git", "reference": "b42d784bd142e916058a9d68eeafcc10ff63c12e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/b42d784bd142e916058a9d68eeafcc10ff63c12e", "reference": "b42d784bd142e916058a9d68eeafcc10ff63c12e", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master", "zendframework/zend-eventmanager": "self.version", "zendframework/zend-filter": "self.version", "zendframework/zend-serializer": "self.version", "zendframework/zend-servicemanager": "self.version" }, "suggest": { "zendframework/zend-eventmanager": "To support aggregate hydrator usage", "zendframework/zend-filter": "To support naming strategy hydrator usage", "zendframework/zend-serializer": "Zend\\Serializer component", "zendframework/zend-servicemanager": "To support hydrator plugin manager usage" }, "time": "2014-03-05 17:29:35", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Zend\\Stdlib\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "homepage": "https://github.com/zendframework/zend-stdlib", "keywords": [ "stdlib", "zf2" ] }, { "name": "zendframework/zend-servicemanager", "version": "2.2.10", "version_normalized": "2.2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-servicemanager.git", "reference": "b9eaf9e3268d2e10ddca807e3a2980b3e662a8e0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/b9eaf9e3268d2e10ddca807e3a2980b3e662a8e0", "reference": "b9eaf9e3268d2e10ddca807e3a2980b3e662a8e0", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master" }, "suggest": { "zendframework/zend-di": "Zend\\Di component" }, "time": "2014-03-05 17:29:35", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Zend\\ServiceManager\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "homepage": "https://github.com/zendframework/zend-service-manager", "keywords": [ "servicemanager", "zf2" ] }, { "name": "zendframework/zend-math", "version": "2.2.10", "version_normalized": "2.2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-math.git", "reference": "0e5ba13e2bc64f6544f5508acf705dd2fc12d91d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-math/zipball/0e5ba13e2bc64f6544f5508acf705dd2fc12d91d", "reference": "0e5ba13e2bc64f6544f5508acf705dd2fc12d91d", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master" }, "suggest": { "ext-bcmath": "If using the bcmath functionality", "ext-gmp": "If using the gmp functionality", "ircmaxell/random-lib": "Fallback random byte generator for Zend\\Math\\Rand if OpenSSL/Mcrypt extensions are unavailable", "zendframework/zend-servicemanager": ">= current version, if using the BigInteger::factory functionality" }, "time": "2014-03-05 17:29:35", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Zend\\Math\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "homepage": "https://github.com/zendframework/zend-math", "keywords": [ "math", "zf2" ] }, { "name": "zendframework/zend-json", "version": "2.2.10", "version_normalized": "2.2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-json.git", "reference": "e0a2e72459b029c3d3785fe8a0b41312670bfd24" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-json/zipball/e0a2e72459b029c3d3785fe8a0b41312670bfd24", "reference": "e0a2e72459b029c3d3785fe8a0b41312670bfd24", "shasum": "" }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master", "zendframework/zend-http": "self.version", "zendframework/zend-server": "self.version" }, "suggest": { "zendframework/zend-http": "Zend\\Http component", "zendframework/zend-server": "Zend\\Server component", "zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage" }, "time": "2014-03-06 17:27:03", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Zend\\Json\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", "homepage": "https://github.com/zendframework/zend-json", "keywords": [ "json", "zf2" ] }, { "name": "zendframework/zend-serializer", "version": "2.2.10", "version_normalized": "2.2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-serializer.git", "reference": "aabfa157039e0c8ca0627a002e8e8f13e62393a8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/aabfa157039e0c8ca0627a002e8e8f13e62393a8", "reference": "aabfa157039e0c8ca0627a002e8e8f13e62393a8", "shasum": "" }, "require": { "php": ">=5.3.3", "zendframework/zend-json": "self.version", "zendframework/zend-math": "self.version", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master", "zendframework/zend-servicemanager": "self.version" }, "suggest": { "zendframework/zend-servicemanager": "To support plugin manager support" }, "time": "2014-03-05 17:29:35", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Zend\\Serializer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides an adapter based interface to simply generate storable representation of PHP types by different facilities, and recover", "homepage": "https://github.com/zendframework/zend-serializer", "keywords": [ "serializer", "zf2" ] }, { "name": "zendframework/zend-eventmanager", "version": "2.2.10", "version_normalized": "2.2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-eventmanager.git", "reference": "aa23086ec1d6d0dad7a33e4eaf3fc851c2bc851b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/aa23086ec1d6d0dad7a33e4eaf3fc851c2bc851b", "reference": "aa23086ec1d6d0dad7a33e4eaf3fc851c2bc851b", "shasum": "" }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master" }, "time": "2014-03-05 17:29:35", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Zend\\EventManager\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "homepage": "https://github.com/zendframework/zend-event-manager", "keywords": [ "eventmanager", "zf2" ] }, { "name": "zendframework/zend-cache", "version": "2.2.10", "version_normalized": "2.2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-cache.git", "reference": "ead910ec8b0aa464ede58c959665d0292d9482b0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-cache/zipball/ead910ec8b0aa464ede58c959665d0292d9482b0", "reference": "ead910ec8b0aa464ede58c959665d0292d9482b0", "shasum": "" }, "require": { "php": ">=5.3.3", "zendframework/zend-eventmanager": "self.version", "zendframework/zend-serializer": "self.version", "zendframework/zend-servicemanager": "self.version", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master", "zendframework/zend-serializer": "self.version", "zendframework/zend-session": "self.version" }, "suggest": { "ext-apc": "APC >= 3.1.6 to use the APC storage adapter", "ext-dba": "DBA, to use the DBA storage adapter", "ext-memcached": "Memcached >= 1.0.0 to use the Memcached storage adapter", "ext-mongo": "Mongo, to use MongoDb storage adapter", "ext-wincache": "WinCache, to use the WinCache storage adapter", "mongofill/mongofill": "Alternative to ext-mongo - a pure PHP implementation designed as a drop in replacement", "zendframework/zend-serializer": "Zend\\Serializer component", "zendframework/zend-session": "Zend\\Session component" }, "time": "2014-03-05 17:29:35", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Zend\\Cache\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides a generic way to cache any data", "homepage": "https://github.com/zendframework/zend-cache", "keywords": [ "cache", "zf2" ] }, { "name": "zendframework/zend-config", "version": "2.2.10", "version_normalized": "2.2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-config.git", "reference": "2077985e6de29bf2bd7df16d4f385dcb53062394" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-config/zipball/2077985e6de29bf2bd7df16d4f385dcb53062394", "reference": "2077985e6de29bf2bd7df16d4f385dcb53062394", "shasum": "" }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master", "zendframework/zend-filter": "self.version", "zendframework/zend-i18n": "self.version", "zendframework/zend-json": "self.version", "zendframework/zend-servicemanager": "self.version" }, "suggest": { "zendframework/zend-filter": "Zend\\Filter component", "zendframework/zend-i18n": "Zend\\I18n component", "zendframework/zend-json": "Zend\\Json to use the Json reader or writer classes", "zendframework/zend-servicemanager": "Zend\\ServiceManager for use with the Config Factory to retrieve reader and writer instances" }, "time": "2014-03-05 17:29:35", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Zend\\Config\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides a nested object property based user interface for accessing this configuration data within application code", "homepage": "https://github.com/zendframework/zend-config", "keywords": [ "config", "zf2" ] }, { "name": "zendframework/zend-filter", "version": "2.2.10", "version_normalized": "2.2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-filter.git", "reference": "790934a61b9bce2c00106ec75fbc024c029de4d0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-filter/zipball/790934a61b9bce2c00106ec75fbc024c029de4d0", "reference": "790934a61b9bce2c00106ec75fbc024c029de4d0", "shasum": "" }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master", "zendframework/zend-crypt": "self.version", "zendframework/zend-servicemanager": "self.version", "zendframework/zend-uri": "self.version" }, "suggest": { "zendframework/zend-crypt": "Zend\\Crypt component", "zendframework/zend-i18n": "Zend\\I18n component", "zendframework/zend-servicemanager": "Zend\\ServiceManager component", "zendframework/zend-uri": "Zend\\Uri component for UriNormalize filter", "zendframework/zend-validator": "Zend\\Validator component" }, "time": "2014-03-05 17:29:35", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Zend\\Filter\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides a set of commonly needed data filters", "homepage": "https://github.com/zendframework/zend-filter", "keywords": [ "filter", "zf2" ] }, { "name": "zendframework/zend-i18n", "version": "2.2.10", "version_normalized": "2.2.10.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-i18n.git", "reference": "6a5a65c1cdcf02877e2526c1b3e315de6a59bb8c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-i18n/zipball/6a5a65c1cdcf02877e2526c1b3e315de6a59bb8c", "reference": "6a5a65c1cdcf02877e2526c1b3e315de6a59bb8c", "shasum": "" }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", "satooshi/php-coveralls": "dev-master", "zendframework/zend-cache": "self.version", "zendframework/zend-config": "self.version", "zendframework/zend-eventmanager": "self.version", "zendframework/zend-filter": "self.version", "zendframework/zend-servicemanager": "self.version", "zendframework/zend-validator": "self.version", "zendframework/zend-view": "self.version" }, "suggest": { "ext-intl": "Required for most features of Zend\\I18n; included in default builds of PHP", "zendframework/zend-cache": "Zend\\Cache component", "zendframework/zend-config": "Zend\\Config component", "zendframework/zend-eventmanager": "You should install this package to use the events in the translator", "zendframework/zend-filter": "You should install this package to use the provided filters", "zendframework/zend-resources": "Translation resources", "zendframework/zend-servicemanager": "Zend\\ServiceManager component", "zendframework/zend-validator": "You should install this package to use the provided validators", "zendframework/zend-view": "You should install this package to use the provided view helpers" }, "time": "2014-03-05 17:29:35", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { "Zend\\I18n\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "homepage": "https://github.com/zendframework/zend-i18n", "keywords": [ "i18n", "zf2" ] }, { "name": "zetacomponents/base", "version": "1.9", "version_normalized": "1.9.0.0", "source": { "type": "git", "url": "https://github.com/zetacomponents/Base.git", "reference": "f20df24e8de3e48b6b69b2503f917e457281e687" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zetacomponents/Base/zipball/f20df24e8de3e48b6b69b2503f917e457281e687", "reference": "f20df24e8de3e48b6b69b2503f917e457281e687", "shasum": "" }, "require-dev": { "zetacomponents/unit-test": "*" }, "time": "2014-09-19 03:28:34", "type": "library", "installation-source": "dist", "autoload": { "classmap": [ "src" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "Apache-2.0" ], "authors": [ { "name": "Sergey Alexeev" }, { "name": "Sebastian Bergmann" }, { "name": "Jan Borsodi" }, { "name": "Raymond Bosman" }, { "name": "Frederik Holljen" }, { "name": "Kore Nordmann" }, { "name": "Derick Rethans" }, { "name": "Vadym Savchuk" }, { "name": "Tobias Schlitt" }, { "name": "Alexandru Stanoi" } ], "description": "The Base package provides the basic infrastructure that all packages rely on. Therefore every component relies on this package.", "homepage": "https://github.com/zetacomponents" }, { "name": "zetacomponents/document", "version": "1.3.1", "version_normalized": "1.3.1.0", "source": { "type": "git", "url": "https://github.com/zetacomponents/Document.git", "reference": "688abfde573cf3fe0730f82538fbd7aa9fc95bc8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zetacomponents/Document/zipball/688abfde573cf3fe0730f82538fbd7aa9fc95bc8", "reference": "688abfde573cf3fe0730f82538fbd7aa9fc95bc8", "shasum": "" }, "require": { "zetacomponents/base": "*" }, "require-dev": { "zetacomponents/unit-test": "dev-master" }, "time": "2013-12-19 11:40:00", "type": "library", "installation-source": "dist", "autoload": { "classmap": [ "src" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "Apache-2.0" ], "authors": [ { "name": "Sebastian Bergmann" }, { "name": "Kore Nordmann" }, { "name": "Derick Rethans" }, { "name": "Tobias Schlitt" }, { "name": "Alexandru Stanoi" } ], "description": "The Document components provides a general conversion framework for different semantic document markup languages like XHTML, Docbook, RST and similar.", "homepage": "https://github.com/zetacomponents" }, { "name": "symfony/yaml", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", "reference": "c044d1744b8e91aaaa0d9bac683ab87ec7cbf359" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/yaml/zipball/c044d1744b8e91aaaa0d9bac683ab87ec7cbf359", "reference": "c044d1744b8e91aaaa0d9bac683ab87ec7cbf359", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "time": "2015-07-26 08:59:42", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\Yaml\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com" }, { "name": "symfony/dependency-injection", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/DependencyInjection", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", "reference": "d9fe6837d74aed11e5ee741cd6b6dfe45e0af78e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d9fe6837d74aed11e5ee741cd6b6dfe45e0af78e", "reference": "d9fe6837d74aed11e5ee741cd6b6dfe45e0af78e", "shasum": "" }, "require": { "php": ">=5.3.3" }, "conflict": { "symfony/expression-language": "<2.6" }, "require-dev": { "symfony/config": "~2.2", "symfony/expression-language": "~2.6", "symfony/phpunit-bridge": "~2.7", "symfony/yaml": "~2.1" }, "suggest": { "symfony/config": "", "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", "symfony/yaml": "" }, "time": "2015-07-22 10:08:40", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\DependencyInjection\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com" }, { "name": "symfony/class-loader", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/ClassLoader", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", "reference": "c5311911ee5bf1c4bfcd8b5788037e7534e4e17d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/class-loader/zipball/c5311911ee5bf1c4bfcd8b5788037e7534e4e17d", "reference": "c5311911ee5bf1c4bfcd8b5788037e7534e4e17d", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/finder": "~2.0,>=2.0.5", "symfony/phpunit-bridge": "~2.7" }, "time": "2015-06-25 11:21:15", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\ClassLoader\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com" }, { "name": "behat/transliterator", "version": "v1.1.0", "version_normalized": "1.1.0.0", "source": { "type": "git", "url": "https://github.com/Behat/Transliterator.git", "reference": "868e05be3a9f25ba6424c2dd4849567f50715003" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Behat/Transliterator/zipball/868e05be3a9f25ba6424c2dd4849567f50715003", "reference": "868e05be3a9f25ba6424c2dd4849567f50715003", "shasum": "" }, "require": { "php": ">=5.3.3" }, "time": "2015-09-28 16:26:35", "type": "library", "extra": { "branch-alias": { "dev-master": "1.1-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Behat\\Transliterator": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "Artistic-1.0" ], "description": "String transliterator", "keywords": [ "i18n", "slug", "transliterator" ] }, { "name": "behat/gherkin", "version": "v4.4.0", "version_normalized": "4.4.0.0", "source": { "type": "git", "url": "https://github.com/Behat/Gherkin.git", "reference": "6b3f8cf3560dc4909c4cddd4f1af3e1f6e9d80af" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Behat/Gherkin/zipball/6b3f8cf3560dc4909c4cddd4f1af3e1f6e9d80af", "reference": "6b3f8cf3560dc4909c4cddd4f1af3e1f6e9d80af", "shasum": "" }, "require": { "php": ">=5.3.1" }, "require-dev": { "phpunit/phpunit": "~4.0", "symfony/yaml": "~2.1" }, "suggest": { "symfony/yaml": "If you want to parse features, represented in YAML files" }, "time": "2015-09-29 13:41:19", "type": "library", "extra": { "branch-alias": { "dev-master": "4.4-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Behat\\Gherkin": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", "homepage": "http://everzet.com" } ], "description": "Gherkin DSL parser for PHP 5.3", "homepage": "http://behat.org/", "keywords": [ "BDD", "Behat", "Cucumber", "DSL", "gherkin", "parser" ] }, { "name": "behat/behat", "version": "v3.0.15", "version_normalized": "3.0.15.0", "source": { "type": "git", "url": "https://github.com/Behat/Behat.git", "reference": "b35ae3d45332d80c532af69cc36f780a9397a996" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Behat/Behat/zipball/b35ae3d45332d80c532af69cc36f780a9397a996", "reference": "b35ae3d45332d80c532af69cc36f780a9397a996", "shasum": "" }, "require": { "behat/gherkin": "~4.3", "behat/transliterator": "~1.0", "ext-mbstring": "*", "php": ">=5.3.3", "symfony/class-loader": "~2.1", "symfony/config": "~2.3", "symfony/console": "~2.1", "symfony/dependency-injection": "~2.1", "symfony/event-dispatcher": "~2.1", "symfony/translation": "~2.3", "symfony/yaml": "~2.1" }, "require-dev": { "phpspec/prophecy-phpunit": "~1.0", "phpunit/phpunit": "~4.0", "symfony/process": "~2.1" }, "suggest": { "behat/mink-extension": "for integration with Mink testing framework", "behat/symfony2-extension": "for integration with Symfony2 web framework", "behat/yii-extension": "for integration with Yii web framework" }, "time": "2015-02-22 14:10:33", "bin": [ "bin/behat" ], "type": "library", "extra": { "branch-alias": { "dev-master": "3.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Behat\\Behat": "src/", "Behat\\Testwork": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", "homepage": "http://everzet.com" } ], "description": "Scenario-oriented BDD framework for PHP 5.3", "homepage": "http://behat.org/", "keywords": [ "Agile", "BDD", "ScenarioBDD", "Scrum", "StoryBDD", "User story", "business", "development", "documentation", "examples", "symfony", "testing" ] }, { "name": "mikey179/vfsStream", "version": "v1.6.0", "version_normalized": "1.6.0.0", "source": { "type": "git", "url": "https://github.com/mikey179/vfsStream.git", "reference": "73bcb605b741a7d5044b47592338c633788b0eb7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/73bcb605b741a7d5044b47592338c633788b0eb7", "reference": "73bcb605b741a7d5044b47592338c633788b0eb7", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { "phpunit/phpunit": "~4.5" }, "time": "2015-10-06 16:59:57", "type": "library", "extra": { "branch-alias": { "dev-master": "1.6.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "org\\bovigo\\vfs\\": "src/main/php" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Frank Kleine", "homepage": "http://frankkleine.de/", "role": "Developer" } ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/" }, { "name": "hamcrest/hamcrest-php", "version": "v1.2.2", "version_normalized": "1.2.2.0", "source": { "type": "git", "url": "https://github.com/hamcrest/hamcrest-php.git", "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", "shasum": "" }, "require": { "php": ">=5.3.2" }, "replace": { "cordoval/hamcrest-php": "*", "davedevelopment/hamcrest-php": "*", "kodova/hamcrest-php": "*" }, "require-dev": { "phpunit/php-file-iterator": "1.3.3", "satooshi/php-coveralls": "dev-master" }, "time": "2015-05-11 14:41:42", "type": "library", "installation-source": "dist", "autoload": { "classmap": [ "hamcrest" ], "files": [ "hamcrest/Hamcrest.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD" ], "description": "This is the PHP port of Hamcrest Matchers", "keywords": [ "test" ] }, { "name": "mockery/mockery", "version": "0.9.4", "version_normalized": "0.9.4.0", "source": { "type": "git", "url": "https://github.com/padraic/mockery.git", "reference": "70bba85e4aabc9449626651f48b9018ede04f86b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/padraic/mockery/zipball/70bba85e4aabc9449626651f48b9018ede04f86b", "reference": "70bba85e4aabc9449626651f48b9018ede04f86b", "shasum": "" }, "require": { "hamcrest/hamcrest-php": "~1.1", "lib-pcre": ">=7.0", "php": ">=5.3.2" }, "require-dev": { "phpunit/phpunit": "~4.0" }, "time": "2015-04-02 19:54:00", "type": "library", "extra": { "branch-alias": { "dev-master": "0.9.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Mockery": "library/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Pádraic Brady", "email": "padraic.brady@gmail.com", "homepage": "http://blog.astrumfutura.com" }, { "name": "Dave Marshall", "email": "dave.marshall@atstsolutions.co.uk", "homepage": "http://davedevelopment.co.uk" } ], "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", "homepage": "http://github.com/padraic/mockery", "keywords": [ "BDD", "TDD", "library", "mock", "mock objects", "mockery", "stub", "test", "test double", "testing" ] }, { "name": "phpunit/php-token-stream", "version": "1.4.8", "version_normalized": "1.4.8.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.2" }, "time": "2015-09-15 10:49:45", "type": "library", "extra": { "branch-alias": { "dev-master": "1.4-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Wrapper around PHP's tokenizer extension.", "homepage": "https://github.com/sebastianbergmann/php-token-stream/", "keywords": [ "tokenizer" ] }, { "name": "sebastian/version", "version": "1.0.6", "version_normalized": "1.0.6.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "shasum": "" }, "time": "2015-06-21 13:59:46", "type": "library", "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version" }, { "name": "sebastian/global-state", "version": "1.1.0", "version_normalized": "1.1.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", "reference": "23af31f402993cfd94e99cbc4b782e9a78eb0e97" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23af31f402993cfd94e99cbc4b782e9a78eb0e97", "reference": "23af31f402993cfd94e99cbc4b782e9a78eb0e97", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.2" }, "suggest": { "ext-uopz": "*" }, "time": "2015-06-21 15:11:22", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Snapshotting of global state", "homepage": "http://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ] }, { "name": "sebastian/recursion-context", "version": "1.0.1", "version_normalized": "1.0.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", "reference": "994d4a811bafe801fb06dccbee797863ba2792ba" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba", "reference": "994d4a811bafe801fb06dccbee797863ba2792ba", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "time": "2015-06-21 08:04:50", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context" }, { "name": "sebastian/exporter", "version": "1.2.1", "version_normalized": "1.2.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", "reference": "7ae5513327cb536431847bcc0c10edba2701064e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", "reference": "7ae5513327cb536431847bcc0c10edba2701064e", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/recursion-context": "~1.0" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "time": "2015-06-21 07:55:53", "type": "library", "extra": { "branch-alias": { "dev-master": "1.2.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "http://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ] }, { "name": "sebastian/environment", "version": "1.3.2", "version_normalized": "1.3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6324c907ce7a52478eeeaede764f48733ef5ae44", "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "time": "2015-08-03 06:14:51", "type": "library", "extra": { "branch-alias": { "dev-master": "1.3.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides functionality to handle HHVM/PHP environments", "homepage": "http://www.github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", "hhvm" ] }, { "name": "sebastian/diff", "version": "1.3.0", "version_normalized": "1.3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.2" }, "time": "2015-02-22 15:13:53", "type": "library", "extra": { "branch-alias": { "dev-master": "1.3-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Kore Nordmann", "email": "mail@kore-nordmann.de" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Diff implementation", "homepage": "http://www.github.com/sebastianbergmann/diff", "keywords": [ "diff" ] }, { "name": "sebastian/comparator", "version": "1.2.0", "version_normalized": "1.2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", "sebastian/exporter": "~1.2" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "time": "2015-07-26 15:48:44", "type": "library", "extra": { "branch-alias": { "dev-master": "1.2.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "http://www.github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ] }, { "name": "phpunit/php-text-template", "version": "1.2.1", "version_normalized": "1.2.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { "php": ">=5.3.3" }, "time": "2015-06-21 13:50:34", "type": "library", "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ "template" ] }, { "name": "doctrine/instantiator", "version": "1.0.2", "version_normalized": "1.0.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", "reference": "26404e0c90565b614ee76b988b9bc8790d77f590" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/instantiator/zipball/26404e0c90565b614ee76b988b9bc8790d77f590", "reference": "26404e0c90565b614ee76b988b9bc8790d77f590", "shasum": "" }, "require": { "php": "~5.3" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", "phpunit/phpunit": "~4.0", "squizlabs/php_codesniffer": "2.0.*@ALPHA" }, "time": "2014-08-25 15:09:25", "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Doctrine\\Instantiator\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", "homepage": "http://ocramius.github.com/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", "homepage": "https://github.com/doctrine/instantiator", "keywords": [ "constructor", "instantiate" ] }, { "name": "phpunit/phpunit-mock-objects", "version": "2.3.8", "version_normalized": "2.3.8.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": ">=5.3.3", "phpunit/php-text-template": "~1.2", "sebastian/exporter": "~1.2" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "suggest": { "ext-soap": "*" }, "time": "2015-10-02 06:51:40", "type": "library", "extra": { "branch-alias": { "dev-master": "2.3.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "Mock Object library for PHPUnit", "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", "keywords": [ "mock", "xunit" ] }, { "name": "phpunit/php-timer", "version": "1.0.7", "version_normalized": "1.0.7.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", "shasum": "" }, "require": { "php": ">=5.3.3" }, "time": "2015-06-21 08:01:12", "type": "library", "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ "timer" ] }, { "name": "phpunit/php-file-iterator", "version": "1.4.1", "version_normalized": "1.4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", "shasum": "" }, "require": { "php": ">=5.3.3" }, "time": "2015-06-21 13:08:43", "type": "library", "extra": { "branch-alias": { "dev-master": "1.4.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ "filesystem", "iterator" ] }, { "name": "phpunit/php-code-coverage", "version": "2.2.4", "version_normalized": "2.2.4.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", "shasum": "" }, "require": { "php": ">=5.3.3", "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", "phpunit/php-token-stream": "~1.3", "sebastian/environment": "^1.3.2", "sebastian/version": "~1.0" }, "require-dev": { "ext-xdebug": ">=2.1.4", "phpunit/phpunit": "~4" }, "suggest": { "ext-dom": "*", "ext-xdebug": ">=2.2.1", "ext-xmlwriter": "*" }, "time": "2015-10-06 15:47:00", "type": "library", "extra": { "branch-alias": { "dev-master": "2.2.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ "coverage", "testing", "xunit" ] }, { "name": "phpspec/prophecy", "version": "v1.6.0", "version_normalized": "1.6.0.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972", "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "~2.0", "sebastian/comparator": "~1.1", "sebastian/recursion-context": "~1.0" }, "require-dev": { "phpspec/phpspec": "~2.0" }, "time": "2016-02-15 07:46:21", "type": "library", "extra": { "branch-alias": { "dev-master": "1.5.x-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Prophecy\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", "homepage": "http://everzet.com" }, { "name": "Marcello Duarte", "email": "marcello.duarte@gmail.com" } ], "description": "Highly opinionated mocking framework for PHP 5.3+", "homepage": "https://github.com/phpspec/prophecy", "keywords": [ "Double", "Dummy", "fake", "mock", "spy", "stub" ] }, { "name": "phpunit/phpunit", "version": "4.8.11", "version_normalized": "4.8.11.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", "reference": "bdd199472410fd7e32751f9c814c7e06f2c21bd5" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bdd199472410fd7e32751f9c814c7e06f2c21bd5", "reference": "bdd199472410fd7e32751f9c814c7e06f2c21bd5", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", "phpspec/prophecy": "^1.3.1", "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", "phpunit/php-timer": ">=1.0.6", "phpunit/phpunit-mock-objects": "~2.3", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", "sebastian/environment": "~1.3", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", "sebastian/version": "~1.0", "symfony/yaml": "~2.1|~3.0" }, "suggest": { "phpunit/php-invoker": "~1.1" }, "time": "2015-10-07 10:39:46", "bin": [ "phpunit" ], "type": "library", "extra": { "branch-alias": { "dev-master": "4.8.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ] }, { "name": "squizlabs/php_codesniffer", "version": "1.5.6", "version_normalized": "1.5.6.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6f3e42d311b882b25b4d409d23a289f4d3b803d5", "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=5.1.2" }, "suggest": { "phpunit/php-timer": "dev-master" }, "time": "2014-12-04 22:32:15", "bin": [ "scripts/phpcs" ], "type": "library", "extra": { "branch-alias": { "dev-phpcs-fixer": "2.0.x-dev" } }, "installation-source": "dist", "autoload": { "classmap": [ "CodeSniffer.php", "CodeSniffer/CLI.php", "CodeSniffer/Exception.php", "CodeSniffer/File.php", "CodeSniffer/Report.php", "CodeSniffer/Reporting.php", "CodeSniffer/Sniff.php", "CodeSniffer/Tokens.php", "CodeSniffer/Reports/", "CodeSniffer/CommentParser/", "CodeSniffer/Tokenizers/", "CodeSniffer/DocGenerators/", "CodeSniffer/Standards/AbstractPatternSniff.php", "CodeSniffer/Standards/AbstractScopeSniff.php", "CodeSniffer/Standards/AbstractVariableSniff.php", "CodeSniffer/Standards/IncorrectPatternException.php", "CodeSniffer/Standards/Generic/Sniffs/", "CodeSniffer/Standards/MySource/Sniffs/", "CodeSniffer/Standards/PEAR/Sniffs/", "CodeSniffer/Standards/PSR1/Sniffs/", "CodeSniffer/Standards/PSR2/Sniffs/", "CodeSniffer/Standards/Squiz/Sniffs/", "CodeSniffer/Standards/Zend/Sniffs/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Greg Sherwood", "role": "lead" } ], "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "homepage": "http://www.squizlabs.com/php-codesniffer", "keywords": [ "phpcs", "standards" ] }, { "name": "symfony/expression-language", "version": "v2.6.12", "version_normalized": "2.6.12.0", "target-dir": "Symfony/Component/ExpressionLanguage", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", "reference": "f4cffea2eca850203d28209a5cbad5ad2e34b243" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/expression-language/zipball/f4cffea2eca850203d28209a5cbad5ad2e34b243", "reference": "f4cffea2eca850203d28209a5cbad5ad2e34b243", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "time": "2015-05-01 14:14:24", "type": "library", "extra": { "branch-alias": { "dev-master": "2.6-dev" } }, "installation-source": "dist", "autoload": { "psr-0": { "Symfony\\Component\\ExpressionLanguage\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony ExpressionLanguage Component", "homepage": "https://symfony.com" } ] CHANGELOG ========= 2.5.0 ----- * added support for GLOB_BRACE in the paths passed to Finder::in() 2.3.0 ----- * added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs()) * unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception 2.2.0 ----- * added Finder::path() and Finder::notPath() methods * added finder adapters to improve performance on specific platforms * added support for wildcard characters (glob patterns) in the paths passed to Finder::in() 2.1.0 ----- * added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and Finder::sortByModifiedTime() * added Countable to Finder * added support for an array of directories as an argument to Finder::exclude() * added searching based on the file content via Finder::contains() and Finder::notContains() * added support for the != operator in the Comparator * [BC BREAK] filter expressions (used for file name and content) are no more considered as regexps but glob patterns when they are enclosed in '*' or '?' Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Finder Component ================ Finder finds files and directories via an intuitive fluent interface. ```php use Symfony\Component\Finder\Finder; $finder = new Finder(); $iterator = $finder ->files() ->name('*.php') ->depth(0) ->size('>= 1K') ->in(__DIR__); foreach ($iterator as $file) { print $file->getRealpath()."\n"; } ``` The iterator returns instances of [Symfony\Component\Finder\SplFileInfo\SplFileInfo][1]. Besides the build-in methods inherited from [\SplFileInfo][2] (`getPerms()`, `getSize()`, ...), you can also use `getRelativePath()` and `getRelativePathname()`. Read the [official documentation][3] for more information. But you can also use it to find files stored remotely like in this example where we are looking for files on Amazon S3: ```php $s3 = new \Zend_Service_Amazon_S3($key, $secret); $s3->registerStreamWrapper("s3"); $finder = new Finder(); $finder->name('photos*')->size('< 100K')->date('since 1 hour ago'); foreach ($finder->in('s3://bucket-name') as $file) { print $file->getFilename()."\n"; } ``` Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Finder/ $ composer install $ phpunit [1]: http://api.symfony.com/2.5/Symfony/Component/Finder/SplFileInfo.html [2]: http://php.net/splfileinfo [3]: https://symfony.com/doc/current/components/finder.html#usage The MIT License (MIT) Copyright (c) 2013 Emanuil Rusev, erusev.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. test/ParsedownTest.php ## Parsedown [![Build Status](https://img.shields.io/travis/erusev/parsedown/master.svg?style=flat-square)](https://travis-ci.org/erusev/parsedown) Better Markdown Parser in PHP [Demo](http://parsedown.org/demo) | [Benchmarks](http://parsedown.org/speed) | [Tests](http://parsedown.org/tests/) | [Documentation](https://github.com/erusev/parsedown/wiki/) ### Features * Super Fast * [GitHub flavored](https://help.github.com/articles/github-flavored-markdown) * Extensible * Tested in 5.3 to 5.6 * [Markdown Extra extension](https://github.com/erusev/parsedown-extra) ### Installation Include `Parsedown.php` or install [the composer package](https://packagist.org/packages/erusev/parsedown). ### Example ``` php $Parsedown = new Parsedown(); echo $Parsedown->text('Hello _Parsedown_!'); # prints:

Hello Parsedown!

``` More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [this video tutorial](http://youtu.be/wYZBY8DEikI). ### Questions **How does Parsedown work?** It tries to read Markdown like a human. First, it looks at the lines. It’s interested in how the lines start. This helps it recognise blocks. It knows, for example, that if a line start with a `-` then it perhaps belong to a list. Once it recognises the blocks, it continues to the content. As it reads, it watches out for special characters. This helps it recognise inline elements (or inlines). We call this approach "line based". We believe that Parsedown is the first Markdown parser to use it. Since the release of Parsedown, other developers have used the same approach to develop other Markdown parsers in PHP and in other languages. **Is it compliant with CommonMark?** It passes most of the CommonMark tests. Most of the tests that don't pass deal with cases that are quite uncommon. Still, as CommonMark matures, compliance should improve. **Who uses it?** [phpDocumentor](http://www.phpdoc.org/), [October CMS](http://octobercms.com/), [Bolt CMS](http://bolt.cm/), [Kirby CMS](http://getkirby.com/), [Grav CMS](http://getgrav.org/), [Statamic CMS](http://www.statamic.com/), [RaspberryPi.org](http://www.raspberrypi.org/) and [more](https://www.versioneye.com/php/erusev:parsedown/references). **How can I help?** Use it, star it, share it and if you feel generous, [donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=528P3NZQMP8N2). --- You might also like [Caret](http://caret.io) - our Markdown editor for the desktop. { "name": "erusev/parsedown", "description": "Parser for Markdown.", "keywords": ["markdown", "parser"], "homepage": "http://parsedown.org", "type": "library", "license": "MIT", "authors": [ { "name": "Emanuil Rusev", "email": "hello@erusev.com", "homepage": "http://erusev.com" } ], "autoload": { "psr-0": {"Parsedown": ""} } }semValue #semval($,%t) $this->semValue #semval(%n) $this->stackPos-(%l-%n) #semval(%n,%t) $this->stackPos-(%l-%n) namespace PhpParser; #include; /* This is an automatically GENERATED file, which should not be manually edited. * Instead edit one of the following: * * the grammar file grammar/zend_language_parser.phpy * * the skeleton file grammar/kymacc.php.parser * * the preprocessing script grammar/rebuildParser.php */ class Parser extends ParserAbstract { protected $tokenToSymbolMapSize = #(YYMAXLEX); protected $actionTableSize = #(YYLAST); protected $gotoTableSize = #(YYGLAST); protected $invalidSymbol = #(YYBADCH); protected $errorSymbol = #(YYINTERRTOK); protected $defaultAction = #(YYDEFAULT); protected $unexpectedTokenRule = #(YYUNEXPECTED); protected $YY2TBLSTATE = #(YY2TBLSTATE); protected $YYNLSTATES = #(YYNLSTATES); #tokenval const %s = %n; #endtokenval protected $symbolToName = array( #listvar terminals ); protected $tokenToSymbol = array( #listvar yytranslate ); protected $action = array( #listvar yyaction ); protected $actionCheck = array( #listvar yycheck ); protected $actionBase = array( #listvar yybase ); protected $actionDefault = array( #listvar yydefault ); protected $goto = array( #listvar yygoto ); protected $gotoCheck = array( #listvar yygcheck ); protected $gotoBase = array( #listvar yygbase ); protected $gotoDefault = array( #listvar yygdefault ); protected $ruleToNonTerminal = array( #listvar yylhs ); protected $ruleToLength = array( #listvar yylen ); #if -t protected $productions = array( #production-strings; ); #endif #reduce protected function reduceRule%n() { %b } #noact protected function reduceRule%n() { $this->semValue = $this->semStack[$this->stackPos]; } #endreduce } #tailcode; %pure_parser %expect 2 %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE %left ',' %left T_LOGICAL_OR %left T_LOGICAL_XOR %left T_LOGICAL_AND %right T_PRINT %right T_YIELD %right T_YIELD_FROM %left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL %left '?' ':' %right T_COALESCE %left T_BOOLEAN_OR %left T_BOOLEAN_AND %left '|' %left '^' %left '&' %nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP %nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL %left T_SL T_SR %left '+' '-' '.' %left '*' '/' '%' %right '!' %nonassoc T_INSTANCEOF %right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' %right T_POW %right '[' %nonassoc T_NEW T_CLONE %token T_EXIT %token T_IF %left T_ELSEIF %left T_ELSE %left T_ENDIF %token T_LNUMBER %token T_DNUMBER %token T_STRING %token T_STRING_VARNAME %token T_VARIABLE %token T_NUM_STRING %token T_INLINE_HTML %token T_CHARACTER %token T_BAD_CHARACTER %token T_ENCAPSED_AND_WHITESPACE %token T_CONSTANT_ENCAPSED_STRING %token T_ECHO %token T_DO %token T_WHILE %token T_ENDWHILE %token T_FOR %token T_ENDFOR %token T_FOREACH %token T_ENDFOREACH %token T_DECLARE %token T_ENDDECLARE %token T_AS %token T_SWITCH %token T_ENDSWITCH %token T_CASE %token T_DEFAULT %token T_BREAK %token T_CONTINUE %token T_GOTO %token T_FUNCTION %token T_CONST %token T_RETURN %token T_TRY %token T_CATCH %token T_FINALLY %token T_THROW %token T_USE %token T_INSTEADOF %token T_GLOBAL %right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC %token T_VAR %token T_UNSET %token T_ISSET %token T_EMPTY %token T_HALT_COMPILER %token T_CLASS %token T_TRAIT %token T_INTERFACE %token T_EXTENDS %token T_IMPLEMENTS %token T_OBJECT_OPERATOR %token T_DOUBLE_ARROW %token T_LIST %token T_ARRAY %token T_CALLABLE %token T_CLASS_C %token T_TRAIT_C %token T_METHOD_C %token T_FUNC_C %token T_LINE %token T_FILE %token T_COMMENT %token T_DOC_COMMENT %token T_OPEN_TAG %token T_OPEN_TAG_WITH_ECHO %token T_CLOSE_TAG %token T_WHITESPACE %token T_START_HEREDOC %token T_END_HEREDOC %token T_DOLLAR_OPEN_CURLY_BRACES %token T_CURLY_OPEN %token T_PAAMAYIM_NEKUDOTAYIM %token T_NAMESPACE %token T_NS_C %token T_DIR %token T_NS_SEPARATOR %token T_ELLIPSIS %{ use PhpParser\Node\Expr; use PhpParser\Node\Name; use PhpParser\Node\Scalar; use PhpParser\Node\Stmt; %} %% start: top_statement_list { $$ = $this->handleNamespaces($1); } ; top_statement_list: top_statement_list top_statement { pushNormalizing($1, $2); } | /* empty */ { init(); } ; namespace_name_parts: T_STRING { init($1); } | namespace_name_parts T_NS_SEPARATOR T_STRING { push($1, $3); } ; namespace_name: namespace_name_parts { $$ = Name[$1]; } ; top_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | T_HALT_COMPILER { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } | T_NAMESPACE namespace_name ';' { $$ = Stmt\Namespace_[$2, null]; } | T_NAMESPACE namespace_name '{' top_statement_list '}' { $$ = Stmt\Namespace_[$2, $4]; } | T_NAMESPACE '{' top_statement_list '}' { $$ = Stmt\Namespace_[null, $3]; } | T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } | T_USE T_FUNCTION use_declarations ';' { $$ = Stmt\Use_[$3, Stmt\Use_::TYPE_FUNCTION]; } | T_USE T_CONST use_declarations ';' { $$ = Stmt\Use_[$3, Stmt\Use_::TYPE_CONSTANT]; } | T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; } ; use_declarations: use_declarations ',' use_declaration { push($1, $3); } | use_declaration { init($1); } ; use_declaration: namespace_name { $$ = Stmt\UseUse[$1, null]; } | namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$1, $3]; } | T_NS_SEPARATOR namespace_name { $$ = Stmt\UseUse[$2, null]; } | T_NS_SEPARATOR namespace_name T_AS T_STRING { $$ = Stmt\UseUse[$2, $4]; } ; constant_declaration_list: constant_declaration_list ',' constant_declaration { push($1, $3); } | constant_declaration { init($1); } ; constant_declaration: T_STRING '=' static_scalar { $$ = Node\Const_[$1, $3]; } ; inner_statement_list: inner_statement_list inner_statement { pushNormalizing($1, $2); } | /* empty */ { init(); } ; inner_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | T_HALT_COMPILER { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } ; statement: '{' inner_statement_list '}' { $$ = $2; } | T_IF parentheses_expr statement elseif_list else_single { $$ = Stmt\If_[$2, [stmts: toArray($3), elseifs: $4, else: $5]]; } | T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' { $$ = Stmt\If_[$2, [stmts: $4, elseifs: $5, else: $6]]; } | T_WHILE parentheses_expr while_statement { $$ = Stmt\While_[$2, $3]; } | T_DO statement T_WHILE parentheses_expr ';' { $$ = Stmt\Do_ [$4, toArray($2)]; } | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement { $$ = Stmt\For_[[init: $3, cond: $5, loop: $7, stmts: $9]]; } | T_SWITCH parentheses_expr switch_case_list { $$ = Stmt\Switch_[$2, $3]; } | T_BREAK ';' { $$ = Stmt\Break_[null]; } | T_BREAK expr ';' { $$ = Stmt\Break_[$2]; } | T_CONTINUE ';' { $$ = Stmt\Continue_[null]; } | T_CONTINUE expr ';' { $$ = Stmt\Continue_[$2]; } | T_RETURN ';' { $$ = Stmt\Return_[null]; } | T_RETURN expr ';' { $$ = Stmt\Return_[$2]; } | yield_expr ';' { $$ = $1; } | T_GLOBAL global_var_list ';' { $$ = Stmt\Global_[$2]; } | T_STATIC static_var_list ';' { $$ = Stmt\Static_[$2]; } | T_ECHO expr_list ';' { $$ = Stmt\Echo_[$2]; } | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } | expr ';' { $$ = $1; } | T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; } | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $5[0], [keyVar: null, byRef: $5[1], stmts: $7]]; } | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $7[0], [keyVar: $5, byRef: $7[1], stmts: $9]]; } | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } | ';' { $$ = array(); /* means: no statement */ } | T_TRY '{' inner_statement_list '}' catches optional_finally { $$ = Stmt\TryCatch[$3, $5, $6]; } | T_THROW expr ';' { $$ = Stmt\Throw_[$2]; } | T_GOTO T_STRING ';' { $$ = Stmt\Goto_[$2]; } | T_STRING ':' { $$ = Stmt\Label[$1]; } | error { $$ = array(); /* means: no statement */ } ; catches: /* empty */ { init(); } | catches catch { push($1, $2); } ; catch: T_CATCH '(' name T_VARIABLE ')' '{' inner_statement_list '}' { $$ = Stmt\Catch_[$3, parseVar($4), $7]; } ; optional_finally: /* empty */ { $$ = null; } | T_FINALLY '{' inner_statement_list '}' { $$ = $3; } ; variables_list: variable { init($1); } | variables_list ',' variable { push($1, $3); } ; optional_ref: /* empty */ { $$ = false; } | '&' { $$ = true; } ; optional_ellipsis: /* empty */ { $$ = false; } | T_ELLIPSIS { $$ = true; } ; function_declaration_statement: T_FUNCTION optional_ref T_STRING '(' parameter_list ')' optional_return_type '{' inner_statement_list '}' { $$ = Stmt\Function_[$3, [byRef: $2, params: $5, returnType: $7, stmts: $9]]; } ; class_declaration_statement: class_entry_type T_STRING extends_from implements_list '{' class_statement_list '}' { $$ = Stmt\Class_[$2, [type: $1, extends: $3, implements: $4, stmts: $6]]; } | T_INTERFACE T_STRING interface_extends_list '{' class_statement_list '}' { $$ = Stmt\Interface_[$2, [extends: $3, stmts: $5]]; } | T_TRAIT T_STRING '{' class_statement_list '}' { $$ = Stmt\Trait_[$2, $4]; } ; class_entry_type: T_CLASS { $$ = 0; } | T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } | T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; } ; extends_from: /* empty */ { $$ = null; } | T_EXTENDS name { $$ = $2; } ; interface_extends_list: /* empty */ { $$ = array(); } | T_EXTENDS name_list { $$ = $2; } ; implements_list: /* empty */ { $$ = array(); } | T_IMPLEMENTS name_list { $$ = $2; } ; name_list: name { init($1); } | name_list ',' name { push($1, $3); } ; for_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } ; foreach_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } ; declare_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } ; declare_list: declare_list_element { init($1); } | declare_list ',' declare_list_element { push($1, $3); } ; declare_list_element: T_STRING '=' static_scalar { $$ = Stmt\DeclareDeclare[$1, $3]; } ; switch_case_list: '{' case_list '}' { $$ = $2; } | '{' ';' case_list '}' { $$ = $3; } | ':' case_list T_ENDSWITCH ';' { $$ = $2; } | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } ; case_list: /* empty */ { init(); } | case_list case { push($1, $2); } ; case: T_CASE expr case_separator inner_statement_list { $$ = Stmt\Case_[$2, $4]; } | T_DEFAULT case_separator inner_statement_list { $$ = Stmt\Case_[null, $3]; } ; case_separator: ':' | ';' ; while_statement: statement { $$ = toArray($1); } | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } ; elseif_list: /* empty */ { init(); } | elseif_list elseif { push($1, $2); } ; elseif: T_ELSEIF parentheses_expr statement { $$ = Stmt\ElseIf_[$2, toArray($3)]; } ; new_elseif_list: /* empty */ { init(); } | new_elseif_list new_elseif { push($1, $2); } ; new_elseif: T_ELSEIF parentheses_expr ':' inner_statement_list { $$ = Stmt\ElseIf_[$2, $4]; } ; else_single: /* empty */ { $$ = null; } | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } ; new_else_single: /* empty */ { $$ = null; } | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } ; foreach_variable: variable { $$ = array($1, false); } | '&' variable { $$ = array($2, true); } | list_expr { $$ = array($1, false); } ; parameter_list: non_empty_parameter_list { $$ = $1; } | /* empty */ { $$ = array(); } ; non_empty_parameter_list: parameter { init($1); } | non_empty_parameter_list ',' parameter { push($1, $3); } ; parameter: optional_param_type optional_ref optional_ellipsis T_VARIABLE { $$ = Node\Param[parseVar($4), null, $1, $2, $3]; } | optional_param_type optional_ref optional_ellipsis T_VARIABLE '=' static_scalar { $$ = Node\Param[parseVar($4), $6, $1, $2, $3]; } ; type: name { $$ = $1; } | T_ARRAY { $$ = 'array'; } | T_CALLABLE { $$ = 'callable'; } ; optional_param_type: /* empty */ { $$ = null; } | type { $$ = $1; } ; optional_return_type: /* empty */ { $$ = null; } | ':' type { $$ = $2; } ; argument_list: '(' ')' { $$ = array(); } | '(' non_empty_argument_list ')' { $$ = $2; } | '(' yield_expr ')' { $$ = array(Node\Arg[$2, false, false]); } ; non_empty_argument_list: argument { init($1); } | non_empty_argument_list ',' argument { push($1, $3); } ; argument: expr { $$ = Node\Arg[$1, false, false]; } | '&' variable { $$ = Node\Arg[$2, true, false]; } | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } ; global_var_list: global_var_list ',' global_var { push($1, $3); } | global_var { init($1); } ; global_var: T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } | '$' variable { $$ = Expr\Variable[$2]; } | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } ; static_var_list: static_var_list ',' static_var { push($1, $3); } | static_var { init($1); } ; static_var: T_VARIABLE { $$ = Stmt\StaticVar[parseVar($1), null]; } | T_VARIABLE '=' static_scalar { $$ = Stmt\StaticVar[parseVar($1), $3]; } ; class_statement_list: class_statement_list class_statement { push($1, $2); } | /* empty */ { init(); } ; class_statement: variable_modifiers property_declaration_list ';' { $$ = Stmt\Property[$1, $2]; } | T_CONST constant_declaration_list ';' { $$ = Stmt\ClassConst[$2]; } | method_modifiers T_FUNCTION optional_ref T_STRING '(' parameter_list ')' optional_return_type method_body { $$ = Stmt\ClassMethod[$4, [type: $1, byRef: $3, params: $6, returnType: $8, stmts: $9]]; } | T_USE name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } ; trait_adaptations: ';' { $$ = array(); } | '{' trait_adaptation_list '}' { $$ = $2; } ; trait_adaptation_list: /* empty */ { init(); } | trait_adaptation_list trait_adaptation { push($1, $2); } ; trait_adaptation: trait_method_reference_fully_qualified T_INSTEADOF name_list ';' { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } | trait_method_reference T_AS member_modifier T_STRING ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } | trait_method_reference T_AS member_modifier ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } | trait_method_reference T_AS T_STRING ';' { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } ; trait_method_reference_fully_qualified: name T_PAAMAYIM_NEKUDOTAYIM T_STRING { $$ = array($1, $3); } ; trait_method_reference: trait_method_reference_fully_qualified { $$ = $1; } | T_STRING { $$ = array(null, $1); } ; method_body: ';' /* abstract method */ { $$ = null; } | '{' inner_statement_list '}' { $$ = $2; } ; variable_modifiers: non_empty_member_modifiers { $$ = $1; } | T_VAR { $$ = 0; } ; method_modifiers: /* empty */ { $$ = 0; } | non_empty_member_modifiers { $$ = $1; } ; non_empty_member_modifiers: member_modifier { $$ = $1; } | non_empty_member_modifiers member_modifier { Stmt\Class_::verifyModifier($1, $2); $$ = $1 | $2; } ; member_modifier: T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } ; property_declaration_list: property_declaration { init($1); } | property_declaration_list ',' property_declaration { push($1, $3); } ; property_declaration: T_VARIABLE { $$ = Stmt\PropertyProperty[parseVar($1), null]; } | T_VARIABLE '=' static_scalar { $$ = Stmt\PropertyProperty[parseVar($1), $3]; } ; expr_list: expr_list ',' expr { push($1, $3); } | expr { init($1); } ; for_expr: /* empty */ { $$ = array(); } | expr_list { $$ = $1; } ; expr: variable { $$ = $1; } | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } | variable '=' expr { $$ = Expr\Assign[$1, $3]; } | variable '=' '&' variable { $$ = Expr\AssignRef[$1, $4]; } | variable '=' '&' new_expr { $$ = Expr\AssignRef[$1, $4]; } | new_expr { $$ = $1; } | T_CLONE expr { $$ = Expr\Clone_[$2]; } | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } | variable T_INC { $$ = Expr\PostInc[$1]; } | T_INC variable { $$ = Expr\PreInc [$2]; } | variable T_DEC { $$ = Expr\PostDec[$1]; } | T_DEC variable { $$ = Expr\PreDec [$2]; } | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } | expr '&' expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } | '!' expr { $$ = Expr\BooleanNot[$2]; } | '~' expr { $$ = Expr\BitwiseNot[$2]; } | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } | parentheses_expr { $$ = $1; } /* we need a separate '(' new_expr ')' rule to avoid problems caused by a s/r conflict */ | '(' new_expr ')' { $$ = $2; } | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } | T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; } | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } | T_EVAL parentheses_expr { $$ = Expr\Eval_[$2]; } | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } | T_DOUBLE_CAST expr { $$ = Expr\Cast\Double [$2]; } | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } | T_EXIT exit_expr { $$ = Expr\Exit_ [$2]; } | '@' expr { $$ = Expr\ErrorSuppress[$2]; } | scalar { $$ = $1; } | array_expr { $$ = $1; } | scalar_dereference { $$ = $1; } | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } | T_PRINT expr { $$ = Expr\Print_[$2]; } | T_YIELD { $$ = Expr\Yield_[null, null]; } | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type '{' inner_statement_list '}' { $$ = Expr\Closure[[static: false, byRef: $2, params: $4, uses: $6, returnType: $7, stmts: $9]]; } | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type '{' inner_statement_list '}' { $$ = Expr\Closure[[static: true, byRef: $3, params: $5, uses: $7, returnType: $8, stmts: $10]]; } ; parentheses_expr: '(' expr ')' { $$ = $2; } | '(' yield_expr ')' { $$ = $2; } ; yield_expr: T_YIELD expr { $$ = Expr\Yield_[$2, null]; } | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } ; array_expr: T_ARRAY '(' array_pair_list ')' { $$ = Expr\Array_[$3]; } | '[' array_pair_list ']' { $$ = Expr\Array_[$2]; } ; scalar_dereference: array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[Scalar\String_[Scalar\String_::parse($1)], $3]; } | constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } /* alternative array syntax missing intentionally */ ; anonymous_class: T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' { $$ = array(Stmt\Class_[null, [type: 0, extends: $3, implements: $4, stmts: $6]], $2); } new_expr: T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } | T_NEW anonymous_class { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } ; lexical_vars: /* empty */ { $$ = array(); } | T_USE '(' lexical_var_list ')' { $$ = $3; } ; lexical_var_list: lexical_var { init($1); } | lexical_var_list ',' lexical_var { push($1, $3); } ; lexical_var: optional_ref T_VARIABLE { $$ = Expr\ClosureUse[parseVar($2), $1]; } ; function_call: name argument_list { $$ = Expr\FuncCall[$1, $2]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM T_STRING argument_list { $$ = Expr\StaticCall[$1, $3, $4]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list { $$ = Expr\StaticCall[$1, $4, $6]; } | static_property argument_list { if ($1 instanceof Node\Expr\StaticPropertyFetch) { $$ = Expr\StaticCall[$1->class, Expr\Variable[$1->name], $2]; } elseif ($1 instanceof Node\Expr\ArrayDimFetch) { $tmp = $1; while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { $tmp = $tmp->var; } $$ = Expr\StaticCall[$tmp->var->class, $1, $2]; $tmp->var = Expr\Variable[$tmp->var->name]; } else { throw new \Exception; } } | variable_without_objects argument_list { $$ = Expr\FuncCall[$1, $2]; } | function_call '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } /* alternative array syntax missing intentionally */ ; class_name: T_STATIC { $$ = Name[$1]; } | name { $$ = $1; } ; name: namespace_name_parts { $$ = Name[$1]; } | T_NS_SEPARATOR namespace_name_parts { $$ = Name\FullyQualified[$2]; } | T_NAMESPACE T_NS_SEPARATOR namespace_name_parts { $$ = Name\Relative[$3]; } ; class_name_reference: class_name { $$ = $1; } | dynamic_class_name_reference { $$ = $1; } ; dynamic_class_name_reference: object_access_for_dcnr { $$ = $1; } | base_variable { $$ = $1; } ; class_name_or_var: class_name { $$ = $1; } | reference_variable { $$ = $1; } ; object_access_for_dcnr: base_variable T_OBJECT_OPERATOR object_property { $$ = Expr\PropertyFetch[$1, $3]; } | object_access_for_dcnr T_OBJECT_OPERATOR object_property { $$ = Expr\PropertyFetch[$1, $3]; } | object_access_for_dcnr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | object_access_for_dcnr '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } ; exit_expr: /* empty */ { $$ = null; } | '(' ')' { $$ = null; } | parentheses_expr { $$ = $1; } ; backticks_expr: /* empty */ { $$ = array(); } | T_ENCAPSED_AND_WHITESPACE { $$ = array(Scalar\String_::parseEscapeSequences($1, '`')); } | encaps_list { parseEncapsed($1, '`'); $$ = $1; } ; ctor_arguments: /* empty */ { $$ = array(); } | argument_list { $$ = $1; } ; common_scalar: T_LNUMBER { $$ = Scalar\LNumber[Scalar\LNumber::parse($1)]; } | T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; } | T_CONSTANT_ENCAPSED_STRING { $$ = Scalar\String_[Scalar\String_::parse($1)]; } | T_LINE { $$ = Scalar\MagicConst\Line[]; } | T_FILE { $$ = Scalar\MagicConst\File[]; } | T_DIR { $$ = Scalar\MagicConst\Dir[]; } | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = Scalar\String_[Scalar\String_::parseDocString($1, $2)]; } | T_START_HEREDOC T_END_HEREDOC { $$ = Scalar\String_['']; } ; static_scalar: common_scalar { $$ = $1; } | class_name T_PAAMAYIM_NEKUDOTAYIM class_const_name { $$ = Expr\ClassConstFetch[$1, $3]; } | name { $$ = Expr\ConstFetch[$1]; } | T_ARRAY '(' static_array_pair_list ')' { $$ = Expr\Array_[$3]; } | '[' static_array_pair_list ']' { $$ = Expr\Array_[$2]; } | static_operation { $$ = $1; } ; static_operation: static_scalar T_BOOLEAN_OR static_scalar { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } | static_scalar T_BOOLEAN_AND static_scalar { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } | static_scalar T_LOGICAL_OR static_scalar { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } | static_scalar T_LOGICAL_AND static_scalar { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } | static_scalar T_LOGICAL_XOR static_scalar { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } | static_scalar '|' static_scalar { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } | static_scalar '&' static_scalar { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } | static_scalar '^' static_scalar { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } | static_scalar '.' static_scalar { $$ = Expr\BinaryOp\Concat [$1, $3]; } | static_scalar '+' static_scalar { $$ = Expr\BinaryOp\Plus [$1, $3]; } | static_scalar '-' static_scalar { $$ = Expr\BinaryOp\Minus [$1, $3]; } | static_scalar '*' static_scalar { $$ = Expr\BinaryOp\Mul [$1, $3]; } | static_scalar '/' static_scalar { $$ = Expr\BinaryOp\Div [$1, $3]; } | static_scalar '%' static_scalar { $$ = Expr\BinaryOp\Mod [$1, $3]; } | static_scalar T_SL static_scalar { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } | static_scalar T_SR static_scalar { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } | static_scalar T_POW static_scalar { $$ = Expr\BinaryOp\Pow [$1, $3]; } | '+' static_scalar %prec T_INC { $$ = Expr\UnaryPlus [$2]; } | '-' static_scalar %prec T_INC { $$ = Expr\UnaryMinus[$2]; } | '!' static_scalar { $$ = Expr\BooleanNot[$2]; } | '~' static_scalar { $$ = Expr\BitwiseNot[$2]; } | static_scalar T_IS_IDENTICAL static_scalar { $$ = Expr\BinaryOp\Identical [$1, $3]; } | static_scalar T_IS_NOT_IDENTICAL static_scalar { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } | static_scalar T_IS_EQUAL static_scalar { $$ = Expr\BinaryOp\Equal [$1, $3]; } | static_scalar T_IS_NOT_EQUAL static_scalar { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } | static_scalar '<' static_scalar { $$ = Expr\BinaryOp\Smaller [$1, $3]; } | static_scalar T_IS_SMALLER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } | static_scalar '>' static_scalar { $$ = Expr\BinaryOp\Greater [$1, $3]; } | static_scalar T_IS_GREATER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } | static_scalar '?' static_scalar ':' static_scalar { $$ = Expr\Ternary[$1, $3, $5]; } | static_scalar '?' ':' static_scalar { $$ = Expr\Ternary[$1, null, $4]; } | static_scalar '[' static_scalar ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | '(' static_scalar ')' { $$ = $2; } ; constant: name { $$ = Expr\ConstFetch[$1]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM class_const_name { $$ = Expr\ClassConstFetch[$1, $3]; } ; scalar: common_scalar { $$ = $1; } | constant { $$ = $1; } | '"' encaps_list '"' { parseEncapsed($2, '"'); $$ = Scalar\Encapsed[$2]; } | T_START_HEREDOC encaps_list T_END_HEREDOC { parseEncapsedDoc($2); $$ = Scalar\Encapsed[$2]; } ; class_const_name: T_STRING { $$ = $1; } | T_CLASS { $$ = 'class'; } ; static_array_pair_list: /* empty */ { $$ = array(); } | non_empty_static_array_pair_list optional_comma { $$ = $1; } ; optional_comma: /* empty */ | ',' ; non_empty_static_array_pair_list: non_empty_static_array_pair_list ',' static_array_pair { push($1, $3); } | static_array_pair { init($1); } ; static_array_pair: static_scalar T_DOUBLE_ARROW static_scalar { $$ = Expr\ArrayItem[$3, $1, false]; } | static_scalar { $$ = Expr\ArrayItem[$1, null, false]; } ; variable: object_access { $$ = $1; } | base_variable { $$ = $1; } | function_call { $$ = $1; } | new_expr_array_deref { $$ = $1; } ; new_expr_array_deref: '(' new_expr ')' '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$2, $5]; } | new_expr_array_deref '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } /* alternative array syntax missing intentionally */ ; object_access: variable_or_new_expr T_OBJECT_OPERATOR object_property { $$ = Expr\PropertyFetch[$1, $3]; } | variable_or_new_expr T_OBJECT_OPERATOR object_property argument_list { $$ = Expr\MethodCall[$1, $3, $4]; } | object_access argument_list { $$ = Expr\FuncCall[$1, $2]; } | object_access '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | object_access '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } ; variable_or_new_expr: variable { $$ = $1; } | '(' new_expr ')' { $$ = $2; } ; variable_without_objects: reference_variable { $$ = $1; } | '$' variable_without_objects { $$ = Expr\Variable[$2]; } ; base_variable: variable_without_objects { $$ = $1; } | static_property { $$ = $1; } ; static_property: class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' reference_variable { $$ = Expr\StaticPropertyFetch[$1, $4]; } | static_property_with_arrays { $$ = $1; } ; static_property_with_arrays: class_name_or_var T_PAAMAYIM_NEKUDOTAYIM T_VARIABLE { $$ = Expr\StaticPropertyFetch[$1, parseVar($3)]; } | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' '{' expr '}' { $$ = Expr\StaticPropertyFetch[$1, $5]; } | static_property_with_arrays '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | static_property_with_arrays '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } ; reference_variable: reference_variable '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } | reference_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } | T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } ; dim_offset: /* empty */ { $$ = null; } | expr { $$ = $1; } ; object_property: T_STRING { $$ = $1; } | '{' expr '}' { $$ = $2; } | variable_without_objects { $$ = $1; } ; list_expr: T_LIST '(' list_expr_elements ')' { $$ = Expr\List_[$3]; } ; list_expr_elements: list_expr_elements ',' list_expr_element { push($1, $3); } | list_expr_element { init($1); } ; list_expr_element: variable { $$ = $1; } | list_expr { $$ = $1; } | /* empty */ { $$ = null; } ; array_pair_list: /* empty */ { $$ = array(); } | non_empty_array_pair_list optional_comma { $$ = $1; } ; non_empty_array_pair_list: non_empty_array_pair_list ',' array_pair { push($1, $3); } | array_pair { init($1); } ; array_pair: expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } | expr { $$ = Expr\ArrayItem[$1, null, false]; } | expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; } | '&' variable { $$ = Expr\ArrayItem[$2, null, true]; } ; encaps_list: encaps_list encaps_var { push($1, $2); } | encaps_list T_ENCAPSED_AND_WHITESPACE { push($1, $2); } | encaps_var { init($1); } | T_ENCAPSED_AND_WHITESPACE encaps_var { init($1, $2); } ; encaps_var: T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } | T_VARIABLE '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[Expr\Variable[parseVar($1)], $3]; } | T_VARIABLE T_OBJECT_OPERATOR T_STRING { $$ = Expr\PropertyFetch[Expr\Variable[parseVar($1)], $3]; } | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' { $$ = Expr\ArrayDimFetch[Expr\Variable[$2], $4]; } | T_CURLY_OPEN variable '}' { $$ = $2; } ; encaps_var_offset: T_STRING { $$ = Scalar\String_[$1]; } | T_NUM_STRING { $$ = Scalar\String_[$1]; } | T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } ; %% What do all those files mean? ============================= * `zend_language_parser.phpy`: PHP grammer written in a pseudo language * `analyze.php`: Analyzes the `.phpy`-grammer and outputs some info about it * `rebuildParser.php`: Preprocesses the `.phpy`-grammar and builds the parser using `kmyacc` * `kmyacc.php.parser`: A `kmyacc` parser prototype file for PHP .phpy pseudo language ===================== The `.phpy` file is a normal grammer in `kmyacc` (`yacc`) style, with some transformations applied to it: * Nodes are created using the syntax `Name[..., ...]`. This is transformed into `new Name(..., ..., attributes())` * Some function-like constructs are resolved (see `rebuildParser.php` for a list) * Associative arrays are written as `[key: value, ...]`, which is transformed to `array('key' => value, ...)` Building the parser =================== In order to rebuild the parser, you need [moriyoshi's fork of kmyacc](https://github.com/moriyoshi/kmyacc-forked). After you compiled/installed it, run the `rebuildParser.php` script. By default only the `Parser.php` is built. If you want to additionally emit debug symbols and create `y.output`, run the script with `--debug`. If you want to retain the preprocessed grammar pass `--keep-tmp-grammar`. ./Tests/ ./ ./Tests CHANGELOG ========= 2.3.0 ----- * added the dumpFile() method to atomically write files 2.2.0 ----- * added a delete option for the mirror() method 2.1.0 ----- * 24eb396 : BC Break : mkdir() function now throws exception in case of failure instead of returning Boolean value * created the component Copyright (c) 2004-2013 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Filesystem Component ==================== Filesystem provides basic utility to manipulate the file system: ```php copy($originFile, $targetFile, $override = false); $filesystem->mkdir($dirs, $mode = 0777); $filesystem->touch($files, $time = null, $atime = null); $filesystem->remove($files); $filesystem->chmod($files, $mode, $umask = 0000, $recursive = false); $filesystem->chown($files, $user, $recursive = false); $filesystem->chgrp($files, $group, $recursive = false); $filesystem->rename($origin, $target); $filesystem->symlink($originDir, $targetDir, $copyOnWindows = false); $filesystem->makePathRelative($endPath, $startPath); $filesystem->mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array()); $filesystem->isAbsolutePath($file); ``` Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Filesystem/ $ composer.phar install --dev $ phpunit { "name": "symfony/filesystem", "type": "library", "description": "Symfony Filesystem Component", "keywords": [], "homepage": "http://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" } ], "require": { "php": ">=5.3.3" }, "autoload": { "psr-0": { "Symfony\\Component\\Filesystem\\": "" } }, "target-dir": "Symfony/Component/Filesystem", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.3-dev" } } } ./Tests/ ./ ./Resources ./Tests ./vendor CHANGELOG ========= 2.6.0 ----- * added new factory syntax and deprecated the old one 2.5.0 ----- * added DecoratorServicePass and a way to override a service definition (Definition::setDecoratedService()) * deprecated SimpleXMLElement class. 2.4.0 ----- * added support for expressions in service definitions * added ContainerAwareTrait to add default container aware behavior to a class 2.2.0 ----- * added Extension::isConfigEnabled() to ease working with enableable configurations * added an Extension base class with sensible defaults to be used in conjunction with the Config component. * added PrependExtensionInterface (to be able to allow extensions to prepend application configuration settings for any Bundle) 2.1.0 ----- * added IntrospectableContainerInterface (to be able to check if a service has been initialized or not) * added ConfigurationExtensionInterface * added Definition::clearTag() * component exceptions that inherit base SPL classes are now used exclusively (this includes dumped containers) * [BC BREAK] fixed unescaping of class arguments, method ParameterBag::unescapeValue() was made public Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. DependencyInjection Component ============================= DependencyInjection manages your services via a robust and flexible Dependency Injection Container. Here is a simple example that shows how to register services and parameters: ```php use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; $sc = new ContainerBuilder(); $sc ->register('foo', '%foo.class%') ->addArgument(new Reference('bar')) ; $sc->setParameter('foo.class', 'Foo'); $sc->get('foo'); ``` Method Calls (Setter Injection): ```php $sc = new ContainerBuilder(); $sc ->register('bar', '%bar.class%') ->addMethodCall('setFoo', array(new Reference('foo'))) ; $sc->setParameter('bar.class', 'Bar'); $sc->get('bar'); ``` Factory Class: If your service is retrieved by calling a static method: ```php $sc = new ContainerBuilder(); $sc ->register('bar', '%bar.class%') ->setFactory(array('%bar.class%', 'getInstance')) ->addArgument('Aarrg!!!') ; $sc->setParameter('bar.class', 'Bar'); $sc->get('bar'); ``` File Include: For some services, especially those that are difficult or impossible to autoload, you may need the container to include a file before instantiating your class. ```php $sc = new ContainerBuilder(); $sc ->register('bar', '%bar.class%') ->setFile('/path/to/file') ->addArgument('Aarrg!!!') ; $sc->setParameter('bar.class', 'Bar'); $sc->get('bar'); ``` Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/DependencyInjection/ $ composer install $ phpunit { "name": "symfony/dependency-injection", "type": "library", "description": "Symfony DependencyInjection Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7", "symfony/yaml": "~2.1", "symfony/config": "~2.2", "symfony/expression-language": "~2.6" }, "conflict": { "symfony/expression-language": "<2.6" }, "suggest": { "symfony/yaml": "", "symfony/config": "", "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them" }, "autoload": { "psr-0": { "Symfony\\Component\\DependencyInjection\\": "" } }, "target-dir": "Symfony/Component/DependencyInjection", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } ./Tests/ ./ ./Resources ./Tests ./vendor CHANGELOG ========= 2.6.0 ----- * added a Process helper * added a DebugFormatter helper 2.5.0 ----- * deprecated the dialog helper (use the question helper instead) * deprecated TableHelper in favor of Table * deprecated ProgressHelper in favor of ProgressBar * added ConsoleLogger * added a question helper * added a way to set the process name of a command * added a way to set a default command instead of `ListCommand` 2.4.0 ----- * added a way to force terminal dimensions * added a convenient method to detect verbosity level * [BC BREAK] made descriptors use output instead of returning a string 2.3.0 ----- * added multiselect support to the select dialog helper * added Table Helper for tabular data rendering * added support for events in `Application` * added a way to normalize EOLs in `ApplicationTester::getDisplay()` and `CommandTester::getDisplay()` * added a way to set the progress bar progress via the `setCurrent` method * added support for multiple InputOption shortcuts, written as `'-a|-b|-c'` * added two additional verbosity levels, VERBOSITY_VERY_VERBOSE and VERBOSITY_DEBUG 2.2.0 ----- * added support for colorization on Windows via ConEmu * add a method to Dialog Helper to ask for a question and hide the response * added support for interactive selections in console (DialogHelper::select()) * added support for autocompletion as you type in Dialog Helper 2.1.0 ----- * added ConsoleOutputInterface * added the possibility to disable a command (Command::isEnabled()) * added suggestions when a command does not exist * added a --raw option to the list command * added support for STDERR in the console output class (errors are now sent to STDERR) * made the defaults (helper set, commands, input definition) in Application more easily customizable * added support for the shell even if readline is not available * added support for process isolation in Symfony shell via `--process-isolation` switch * added support for `--`, which disables options parsing after that point (tokens will be parsed as arguments) Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. MZ@ !L!This program cannot be run in DOS mode. $,;B;B;B2מ:B2-B2ƞ9B2ў?Ba98B;CB2Ȟ:B2֞:B2Ӟ:BRich;BPELMoO  8 @`?@"P@ Pp!8!@ .text   `.rdata @@.data0@.rsrc @@@.relocP"@Bj$@xj @eEPV @EЃPV @MX @eEP5H @L @YY5\ @EP5` @D @YYP @MMT @3H; 0@uh@l3@$40@5h3@40@h$0@h(0@h 0@ @00@}jYjh"@3ۉ]dp]俀3@SVW0 @;t;u3Fuh4 @3F|3@;u j\Y;|3@u,5|3@h @h @YYtE5<0@|3@;uh @h @lYY|3@9]uSW8 @93@th3@Yt SjS3@$0@ @5$0@5(0@5 0@ 80@9,0@u7P @E MPQYYËeE80@39,0@uPh @9<0@u @E80@øMZf9@t3M<@@8PEuH t uՃv39xtv39j,0@p @jl @YY3@3@ @ t3@ @ p3@ @x3@V=0@u h@ @Yg=0@u j @Y3{U(H1@ D1@@1@<1@581@=41@f`1@f T1@f01@f,1@f%(1@f-$1@X1@EL1@EP1@E\1@0@P1@L0@@0@ D0@0@0@ @0@j?Yj @h!@$ @=0@ujYh ( @P, @ËUE8csmu*xu$@= t=!t="t=@u3]hH@ @3% @jh("@b53@5 @YEu u @YgjYe53@։E53@YYEEPEPu5l @YPUEu֣3@uփ3@E EjYËUuNYH]ËV!@!@W;stЃ;r_^ËV"@"@W;stЃ;r_^% @̋UMMZf9t3]ËA<8PEu3ҹ f9H‹]̋UEH<ASVq3WDv} H ;r X;r B(;r3_^[]̋UjhH"@he@dPSVW0@1E3PEdeEh@*tUE-@Ph@Pt;@$ЃEMd Y_^[]ËE3=‹ËeE3Md Y_^[]% @% @he@d5D$l$l$+SVW0@1E3PeuEEEEdËMd Y__^[]QËUuuu uh@h0@]ËVhh3V t VVVVV^3ËU0@eeSWN@;t t У0@`VEP< @u3u @3 @3 @3EP @E3E3;uO@ u 50@։50@^_[%t @%x @%| @% @% @% @% @% @% @Pd5D$ +d$ SVW(0@3PEuEEdËMd Y__^[]QËM3M%T @T$B J3J3l"@s###)r)b)H)4))(((((()#$%%&d&&$('''''(((6('H(Z(t(('''''l'^'R'F'>'>(0'')@W@@MoOl!@0@0@bad allocationH0@!@RSDSьJ!LZc:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdbe@@:@@@@"d"@"# $#&D H#(h ###)r)b)H)4))(((((()#$%%&d&&$('''''(((6('H(Z(t(('''''l'^'R'F'>'>(0'')GetConsoleModeSetConsoleMode;GetStdHandleKERNEL32.dll??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@AJ?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z_??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ{??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@ZMSVCP90.dll_amsg_exit__getmainargs,_cexit|_exitf_XcptFilterexit__initenv_initterm_initterm_e<_configthreadlocale__setusermatherr _adjust_fdiv__p__commode__p__fmodej_encode_pointer__set_app_typeK_crt_debugger_hookC?terminate@@YAXXZMSVCR90.dll_unlock__dllonexitv_lock_onexit`_decode_pointers_except_handler4_common _invoke_watson?_controlfp_sInterlockedExchange!SleepInterlockedCompareExchange-TerminateProcessGetCurrentProcess>UnhandledExceptionFilterSetUnhandledExceptionFilterIsDebuggerPresentTQueryPerformanceCounterfGetTickCountGetCurrentThreadIdGetCurrentProcessIdOGetSystemTimeAsFileTimes__CxxFrameHandler3N@D$!@ 8Ph  @(CV(4VS_VERSION_INFOStringFileInfob040904b0QFileDescriptionReads from stdin without leaking info to the terminal and outputs back to stdout6 FileVersion1, 0, 0, 08 InternalNamehiddeninputPLegalCopyrightJordi Boggiano - 2012HOriginalFilenamehiddeninput.exe: ProductNameHidden Input: ProductVersion1, 0, 0, 0DVarFileInfo$Translation  PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING@00!0/080F0L0T0^0d0n0{000000000000001#1-1@1J1O1T1v1{1111111111111112"2*23292A2M2_2j2p222222222222 333%303N3T3Z3`3f3l3s3z333333333333333334444%4;4B444444444445!5^5c5555H6M6_6}66677 7*7w7|777778 88=8E8P8V8\8b8h8n8t8z88889 $0001 1t1x12 2@2\2`2h2t20 0Console Component ================= Console eases the creation of beautiful and testable command line interfaces. The Application object manages the CLI application: ```php use Symfony\Component\Console\Application; $console = new Application(); $console->run(); ``` The ``run()`` method parses the arguments and options passed on the command line and executes the right command. Registering a new command can easily be done via the ``register()`` method, which returns a ``Command`` instance: ```php use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; $console ->register('ls') ->setDefinition(array( new InputArgument('dir', InputArgument::REQUIRED, 'Directory name'), )) ->setDescription('Displays the files in the given directory') ->setCode(function (InputInterface $input, OutputInterface $output) { $dir = $input->getArgument('dir'); $output->writeln(sprintf('Dir listing for %s', $dir)); }) ; ``` You can also register new commands via classes. The component provides a lot of features like output coloring, input and output abstractions (so that you can easily unit-test your commands), validation, automatic help messages, ... Tests ----- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Console/ $ composer install $ phpunit Third Party ----------- `Resources/bin/hiddeninput.exe` is a third party binary provided within this component. Find sources and license at https://github.com/Seldaek/hidden-input. Resources --------- [The Console Component](https://symfony.com/doc/current/components/console.html) [How to create a Console Command](https://symfony.com/doc/current/cookbook/console/console_command.html) { "name": "symfony/console", "type": "library", "description": "Symfony Console Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7", "symfony/event-dispatcher": "~2.1", "symfony/process": "~2.1", "psr/log": "~1.0" }, "suggest": { "symfony/event-dispatcher": "", "symfony/process": "", "psr/log": "For using the console logger" }, "autoload": { "psr-0": { "Symfony\\Component\\Console\\": "" } }, "target-dir": "Symfony/Component/Console", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } ./Tests/ ./ ./Tests ./vendor CHANGELOG ========= 2.6.0 ----- * Added ExpressionFunction and ExpressionFunctionProviderInterface 2.4.0 ----- * added the component Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ExpressionLanguage Component ============================ The ExpressionLanguage component provides an engine that can compile and evaluate expressions: use Symfony\Component\ExpressionLanguage\ExpressionLanguage; $language = new ExpressionLanguage(); echo $language->evaluate('1 + foo', array('foo' => 2)); // would output 3 echo $language->compile('1 + foo', array('foo')); // would output (1 + $foo) By default, the engine implements simple math and logic functions, method calls, property accesses, and array accesses. You can extend your DSL with functions: $compiler = function ($arg) { return sprintf('strtoupper(%s)', $arg); }; $evaluator = function (array $variables, $value) { return strtoupper($value); }; $language->register('upper', $compiler, $evaluator); echo $language->evaluate('"foo" ~ upper(foo)', array('foo' => 'bar')); // would output fooBAR echo $language->compile('"foo" ~ upper(foo)'); // would output ("foo" . strtoupper($foo)) Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/ExpressionLanguage/ $ composer.phar install --dev $ phpunit { "name": "symfony/expression-language", "type": "library", "description": "Symfony ExpressionLanguage Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "autoload": { "psr-0": { "Symfony\\Component\\ExpressionLanguage\\": "" } }, "target-dir": "Symfony/Component/ExpressionLanguage", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } ./Tests/ ./ ./Tests CHANGELOG ========= 2.5.0 ----- * added support for PTY mode * added the convenience method "mustRun" * deprecation: Process::setStdin() is deprecated in favor of Process::setInput() * deprecation: Process::getStdin() is deprecated in favor of Process::getInput() * deprecation: Process::setInput() and ProcessBuilder::setInput() do not accept non-scalar types 2.4.0 ----- * added the ability to define an idle timeout 2.3.0 ----- * added ProcessUtils::escapeArgument() to fix the bug in escapeshellarg() function on Windows * added Process::signal() * added Process::getPid() * added support for a TTY mode 2.2.0 ----- * added ProcessBuilder::setArguments() to reset the arguments on a builder * added a way to retrieve the standard and error output incrementally * added Process:restart() 2.1.0 ----- * added support for non-blocking processes (start(), wait(), isRunning(), stop()) * enhanced Windows compatibility * added Process::getExitCodeText() that returns a string representation for the exit code returned by the process * added ProcessBuilder Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Process Component ================= Process executes commands in sub-processes. In this example, we run a simple directory listing and get the result back: ```php use Symfony\Component\Process\Process; $process = new Process('ls -lsa'); $process->setTimeout(3600); $process->run(); if (!$process->isSuccessful()) { throw new RuntimeException($process->getErrorOutput()); } print $process->getOutput(); ``` You can think that this is easy to achieve with plain PHP but it's not especially if you want to take care of the subtle differences between the different platforms. And if you want to be able to get some feedback in real-time, just pass an anonymous function to the ``run()`` method and you will get the output buffer as it becomes available: ```php use Symfony\Component\Process\Process; $process = new Process('ls -lsa'); $process->run(function ($type, $buffer) { if (Process::ERR === $type) { echo 'ERR > '.$buffer; } else { echo 'OUT > '.$buffer; } }); ``` That's great if you want to execute a long running command (like rsync-ing files to a remote server) and give feedback to the user in real-time. Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Process/ $ composer install $ phpunit { "name": "symfony/process", "type": "library", "description": "Symfony Process Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "autoload": { "psr-0": { "Symfony\\Component\\Process\\": "" } }, "target-dir": "Symfony/Component/Process", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } ./Tests/ ./ ./Resources ./Tests ./vendor CHANGELOG ========= 2.5.0 ----- * added Debug\TraceableEventDispatcher (originally in HttpKernel) * changed Debug\TraceableEventDispatcherInterface to extend EventDispatcherInterface * added RegisterListenersPass (originally in HttpKernel) 2.1.0 ----- * added TraceableEventDispatcherInterface * added ContainerAwareEventDispatcher * added a reference to the EventDispatcher on the Event * added a reference to the Event name on the event * added fluid interface to the dispatch() method which now returns the Event object * added GenericEvent event class * added the possibility for subscribers to subscribe several times for the same event * added ImmutableEventDispatcher Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. EventDispatcher Component ========================= The Symfony EventDispatcher component implements the Mediator pattern in a simple and effective way to make your projects truly extensible. ```php use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\Event; $dispatcher = new EventDispatcher(); $dispatcher->addListener('event_name', function (Event $event) { // ... }); $dispatcher->dispatch('event_name'); ``` Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/EventDispatcher/ $ composer install $ phpunit { "name": "symfony/event-dispatcher", "type": "library", "description": "Symfony EventDispatcher Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7", "symfony/dependency-injection": "~2.6", "symfony/expression-language": "~2.6", "symfony/config": "~2.0,>=2.0.5", "symfony/stopwatch": "~2.3", "psr/log": "~1.0" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, "autoload": { "psr-0": { "Symfony\\Component\\EventDispatcher\\": "" } }, "target-dir": "Symfony/Component/EventDispatcher", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } ./Tests/ ./ ./Tests ./vendor CHANGELOG ========= 2.5.0 ----- * added support for GLOB_BRACE in the paths passed to Finder::in() 2.3.0 ----- * added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs()) * unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception 2.2.0 ----- * added Finder::path() and Finder::notPath() methods * added finder adapters to improve performance on specific platforms * added support for wildcard characters (glob patterns) in the paths passed to Finder::in() 2.1.0 ----- * added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and Finder::sortByModifiedTime() * added Countable to Finder * added support for an array of directories as an argument to Finder::exclude() * added searching based on the file content via Finder::contains() and Finder::notContains() * added support for the != operator in the Comparator * [BC BREAK] filter expressions (used for file name and content) are no more considered as regexps but glob patterns when they are enclosed in '*' or '?' Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Finder Component ================ Finder finds files and directories via an intuitive fluent interface. ```php use Symfony\Component\Finder\Finder; $finder = new Finder(); $iterator = $finder ->files() ->name('*.php') ->depth(0) ->size('>= 1K') ->in(__DIR__); foreach ($iterator as $file) { print $file->getRealpath()."\n"; } ``` The iterator returns instances of [Symfony\Component\Finder\SplFileInfo\SplFileInfo][1]. Besides the build-in methods inherited from [\SplFileInfo][2] (`getPerms()`, `getSize()`, ...), you can also use `getRelativePath()` and `getRelativePathname()`. Read the [official documentation][3] for more information. But you can also use it to find files stored remotely like in this example where we are looking for files on Amazon S3: ```php $s3 = new \Zend_Service_Amazon_S3($key, $secret); $s3->registerStreamWrapper("s3"); $finder = new Finder(); $finder->name('photos*')->size('< 100K')->date('since 1 hour ago'); foreach ($finder->in('s3://bucket-name') as $file) { print $file->getFilename()."\n"; } ``` Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Finder/ $ composer install $ phpunit [1]: http://api.symfony.com/2.5/Symfony/Component/Finder/SplFileInfo.html [2]: http://php.net/splfileinfo [3]: https://symfony.com/doc/current/components/finder.html#usage { "name": "symfony/finder", "type": "library", "description": "Symfony Finder Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "autoload": { "psr-0": { "Symfony\\Component\\Finder\\": "" } }, "target-dir": "Symfony/Component/Finder", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } ./Tests/ ./ ./vendor ./Tests CHANGELOG ========= 2.1.0 ----- * Yaml::parse() does not evaluate loaded files as PHP files by default anymore (call Yaml::enablePhpParsing() to get back the old behavior) Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Yaml Component ============== YAML implements most of the YAML 1.2 specification. ```php use Symfony\Component\Yaml\Yaml; $array = Yaml::parse(file_get_contents(filename)); print Yaml::dump($array); ``` Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Yaml/ $ composer install $ phpunit { "name": "symfony/yaml", "type": "library", "description": "Symfony Yaml Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "autoload": { "psr-0": { "Symfony\\Component\\Yaml\\": "" } }, "target-dir": "Symfony/Component/Yaml", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } ./Tests/ ./ ./Resources ./Tests ./vendor CHANGELOG ========= 2.4.0 ----- * deprecated the UniversalClassLoader in favor of the ClassLoader class instead * deprecated the ApcUniversalClassLoader in favor of the ApcClassLoader class instead * deprecated the DebugUniversalClassLoader in favor of the DebugClassLoader class from the Debug component * deprecated the DebugClassLoader as it has been moved to the Debug component instead 2.3.0 ----- * added a WinCacheClassLoader for WinCache 2.1.0 ----- * added a DebugClassLoader able to wrap any autoloader providing a findFile method * added a new ApcClassLoader and XcacheClassLoader using composition to wrap other loaders * added a new ClassLoader which does not distinguish between namespaced and pear-like classes (as the PEAR convention is a subset of PSR-0) and supports using Composer's namespace maps * added a class map generator * added support for loading globally-installed PEAR packages Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ClassLoader Component ===================== ClassLoader loads your project classes automatically if they follow some standard PHP conventions. The ClassLoader object is able to autoload classes that implement the PSR-0 standard or the PEAR naming convention. First, register the autoloader: ```php require_once __DIR__.'/src/Symfony/Component/ClassLoader/ClassLoader.php'; use Symfony\Component\ClassLoader\ClassLoader; $loader = new ClassLoader(); $loader->register(); ``` Then, register some namespaces with the `addPrefix()` method: ```php $loader->addPrefix('Symfony', __DIR__.'/src'); $loader->addPrefix('Monolog', __DIR__.'/vendor/monolog/src'); ``` The `addPrefix()` method takes a namespace prefix and a path where to look for the classes as arguments. You can also register a sub-namespaces: ```php $loader->addPrefix('Doctrine\\Common', __DIR__.'/vendor/doctrine-common/lib'); ``` The order of registration is significant and the first registered namespace takes precedence over later registered one. You can also register more than one path for a given namespace: ```php $loader->addPrefix('Symfony', array(__DIR__.'/src', __DIR__.'/symfony/src')); ``` Alternatively, you can use the `addPrefixes()` method to register more than one namespace at once: ```php $loader->addPrefixes(array( 'Symfony' => array(__DIR__.'/src', __DIR__.'/symfony/src'), 'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib', 'Doctrine' => __DIR__.'/vendor/doctrine/lib', 'Monolog' => __DIR__.'/vendor/monolog/src', )); ``` For better performance, you can use the APC class loader: ```php require_once __DIR__.'/src/Symfony/Component/ClassLoader/ClassLoader.php'; require_once __DIR__.'/src/Symfony/Component/ClassLoader/ApcClassLoader.php'; use Symfony\Component\ClassLoader\ClassLoader; use Symfony\Component\ClassLoader\ApcClassLoader; $loader = new ClassLoader(); $loader->addPrefix('Symfony', __DIR__.'/src'); $loader = new ApcClassLoader('apc.prefix.', $loader); $loader->register(); ``` Furthermore, the component provides tools to aggregate classes into a single file, which is especially useful to improve performance on servers that do not provide byte caches. Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/ClassLoader/ $ composer install $ phpunit { "name": "symfony/class-loader", "type": "library", "description": "Symfony ClassLoader Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "minimum-stability": "dev", "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7", "symfony/finder": "~2.0,>=2.0.5" }, "autoload": { "psr-0": { "Symfony\\Component\\ClassLoader\\": "" } }, "target-dir": "Symfony/Component/ClassLoader", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } ./Tests/ ./ ./vendor ./Tests CHANGELOG ========= 2.3.0 ----- * added classes to make operations on catalogues (like making a diff or a merge on 2 catalogues) * added Translator::getFallbackLocales() * deprecated Translator::setFallbackLocale() in favor of the new Translator::setFallbackLocales() method 2.2.0 ----- * QtTranslationsLoader class renamed to QtFileLoader. QtTranslationsLoader is deprecated and will be removed in 2.3. * [BC BREAK] uniformized the exception thrown by the load() method when an error occurs. The load() method now throws Symfony\Component\Translation\Exception\NotFoundResourceException when a resource cannot be found and Symfony\Component\Translation\Exception\InvalidResourceException when a resource is invalid. * changed the exception class thrown by some load() methods from \RuntimeException to \InvalidArgumentException (IcuDatFileLoader, IcuResFileLoader and QtFileLoader) 2.1.0 ----- * added support for more than one fallback locale * added support for extracting translation messages from templates (Twig and PHP) * added dumpers for translation catalogs * added support for QT, gettext, and ResourceBundles Copyright (c) 2004-2013 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Translation Component ===================== Translation provides tools for loading translation files and generating translated strings from these including support for pluralization. use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\MessageSelector; use Symfony\Component\Translation\Loader\ArrayLoader; $translator = new Translator('fr_FR', new MessageSelector()); $translator->setFallbackLocales(array('fr')); $translator->addLoader('array', new ArrayLoader()); $translator->addResource('array', array( 'Hello World!' => 'Bonjour', ), 'fr'); echo $translator->trans('Hello World!')."\n"; Resources --------- Silex integration: https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/TranslationServiceProvider.php Documentation: http://symfony.com/doc/2.3/book/translation.html You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Translation/ $ composer.phar install --dev $ phpunit Values for the attribute 'context-type'. Indicates a database content. Indicates the content of an element within an XML document. Indicates the name of an element within an XML document. Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found. Indicates a the number of parameters contained within the <source>. Indicates notes pertaining to the parameters in the <source>. Indicates the content of a record within a database. Indicates the name of a record within a database. Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file. Values for the attribute 'count-type'. Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts. Indicates the count units are translation units existing already in the same document. Indicates a total count. Values for the attribute 'ctype' when used other elements than <ph> or <x>. Indicates a run of bolded text. Indicates a run of text in italics. Indicates a run of underlined text. Indicates a run of hyper-text. Values for the attribute 'ctype' when used with <ph> or <x>. Indicates a inline image. Indicates a page break. Indicates a line break. Values for the attribute 'datatype'. Indicates Active Server Page data. Indicates C source file data. Indicates Channel Definition Format (CDF) data. Indicates ColdFusion data. Indicates C++ source file data. Indicates C-Sharp data. Indicates strings from C, ASM, and driver files data. Indicates comma-separated values data. Indicates database data. Indicates portions of document that follows data and contains metadata. Indicates portions of document that precedes data and contains metadata. Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import). Indicates standard user input screen data. Indicates HyperText Markup Language (HTML) data - document instance. Indicates content within an HTML document’s <body> element. Indicates Windows INI file data. Indicates Interleaf data. Indicates Java source file data (extension '.java'). Indicates Java property resource bundle data. Indicates Java list resource bundle data. Indicates JavaScript source file data. Indicates JScript source file data. Indicates information relating to formatting. Indicates LISP source file data. Indicates information relating to margin formats. Indicates a file containing menu. Indicates numerically identified string table. Indicates Maker Interchange Format (MIF) data. Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute. Indicates GNU Machine Object data. Indicates Message Librarian strings created by Novell's Message Librarian Tool. Indicates information to be displayed at the bottom of each page of a document. Indicates information to be displayed at the top of each page of a document. Indicates a list of property values (e.g., settings within INI files or preferences dialog). Indicates Pascal source file data. Indicates Hypertext Preprocessor data. Indicates plain text file (no formatting other than, possibly, wrapping). Indicates GNU Portable Object file. Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc. Indicates Windows .NET binary resources. Indicates Windows .NET Resources. Indicates Rich Text Format (RTF) data. Indicates Standard Generalized Markup Language (SGML) data - document instance. Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD). Indicates Scalable Vector Graphic (SVG) data. Indicates VisualBasic Script source file. Indicates warning message. Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file). Indicates Extensible HyperText Markup Language (XHTML) data - document instance. Indicates Extensible Markup Language (XML) data - document instance. Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD). Indicates Extensible Stylesheet Language (XSL) data. Indicates XUL elements. Values for the attribute 'mtype'. Indicates the marked text is an abbreviation. ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept. ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective'). ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging'). ISO-12620: A proper-name term, such as the name of an agency or other proper entity. ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another. ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language. Indicates the marked text is a date and/or time. ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign. ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form. ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula. ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record. ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy'). ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body. ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages. ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like. ISO-12620 2.1.17: A unit to track object. Indicates the marked text is a name. ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others. ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system. Indicates the marked text is a phrase. ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase. Indicates the marked text should not be translated. ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet. Indicates that the marked text represents a segment. ISO-12620 2.1.18.2: A fixed, lexicalized phrase. ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs'). ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system. ISO-12620 2.1.19: A fixed chunk of recurring text. ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof. ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry. ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language. Indicates the marked text is a term. ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted. ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system. ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza'). ISO-12620 2.1.9: One of the alternate forms of a term. Values for the attribute 'restype'. Indicates a Windows RC AUTO3STATE control. Indicates a Windows RC AUTOCHECKBOX control. Indicates a Windows RC AUTORADIOBUTTON control. Indicates a Windows RC BEDIT control. Indicates a bitmap, for example a BITMAP resource in Windows. Indicates a button object, for example a BUTTON control Windows. Indicates a caption, such as the caption of a dialog box. Indicates the cell in a table, for example the content of the <td> element in HTML. Indicates check box object, for example a CHECKBOX control in Windows. Indicates a menu item with an associated checkbox. Indicates a list box, but with a check-box for each item. Indicates a color selection dialog. Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows. Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234). Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403). Indicates a UI base class element that cannot be represented by any other element. Indicates a context menu. Indicates a Windows RC CTEXT control. Indicates a cursor, for example a CURSOR resource in Windows. Indicates a date/time picker. Indicates a Windows RC DEFPUSHBUTTON control. Indicates a dialog box. Indicates a Windows RC DLGINIT resource block. Indicates an edit box object, for example an EDIT control in Windows. Indicates a filename. Indicates a file dialog. Indicates a footnote. Indicates a font name. Indicates a footer. Indicates a frame object. Indicates a XUL grid element. Indicates a groupbox object, for example a GROUPBOX control in Windows. Indicates a header item. Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML. Indicates a Windows RC HEDIT control. Indicates a horizontal scrollbar. Indicates an icon, for example an ICON resource in Windows. Indicates a Windows RC IEDIT control. Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF. Indicates a label object. Indicates a label that is also a HTML link (not necessarily a URL). Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML). Indicates a listbox object, for example an LISTBOX control in Windows. Indicates an list item (an entry in a list). Indicates a Windows RC LTEXT control. Indicates a menu (a group of menu-items). Indicates a toolbar containing one or more tope level menus. Indicates a menu item (an entry in a menu). Indicates a XUL menuseparator element. Indicates a message, for example an entry in a MESSAGETABLE resource in Windows. Indicates a calendar control. Indicates an edit box beside a spin control. Indicates a catch all for rectangular areas. Indicates a standalone menu not necessarily associated with a menubar. Indicates a pushbox object, for example a PUSHBOX control in Windows. Indicates a Windows RC PUSHBUTTON control. Indicates a radio button object. Indicates a menuitem with associated radio button. Indicates raw data resources for an application. Indicates a row in a table. Indicates a Windows RC RTEXT control. Indicates a user navigable container used to show a portion of a document. Indicates a generic divider object (e.g. menu group separator). Windows accelerators, shortcuts in resource or property files. Indicates a UI control to indicate process activity but not progress. Indicates a splitter bar. Indicates a Windows RC STATE3 control. Indicates a window for providing feedback to the users, like 'read-only', etc. Indicates a string, for example an entry in a STRINGTABLE resource in Windows. Indicates a layers of controls with a tab to select layers. Indicates a display and edits regular two-dimensional tables of cells. Indicates a XUL textbox element. Indicates a UI button that can be toggled to on or off state. Indicates an array of controls, usually buttons. Indicates a pop up tool tip text. Indicates a bar with a pointer indicating a position within a certain range. Indicates a control that displays a set of hierarchical data. Indicates a URI (URN or URL). Indicates a Windows RC USERBUTTON control. Indicates a user-defined control like CONTROL control in Windows. Indicates the text of a variable. Indicates version information about a resource like VERSIONINFO in Windows. Indicates a vertical scrollbar. Indicates a graphical window. Values for the attribute 'size-unit'. Indicates a size in 8-bit bytes. Indicates a size in Unicode characters. Indicates a size in columns. Used for HTML text area. Indicates a size in centimeters. Indicates a size in dialog units, as defined in Windows resources. Indicates a size in 'font-size' units (as defined in CSS). Indicates a size in 'x-height' units (as defined in CSS). Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster' Indicates a size in inches. Indicates a size in millimeters. Indicates a size in percentage. Indicates a size in pixels. Indicates a size in point. Indicates a size in rows. Used for HTML text area. Values for the attribute 'state'. Indicates the terminating state. Indicates only non-textual information needs adaptation. Indicates both text and non-textual information needs adaptation. Indicates only non-textual information needs review. Indicates both text and non-textual information needs review. Indicates that only the text of the item needs to be reviewed. Indicates that the item needs to be translated. Indicates that the item is new. For example, translation units that were not in a previous version of the document. Indicates that changes are reviewed and approved. Indicates that the item has been translated. Values for the attribute 'state-qualifier'. Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously. Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.). Indicates a match based on matching IDs (in addition to matching text). Indicates a translation derived from a glossary. Indicates a translation derived from existing translation. Indicates a translation derived from machine translation. Indicates a translation derived from a translation repository. Indicates a translation derived from a translation memory. Indicates the translation is suggested by machine translation. Indicates that the item has been rejected because of incorrect grammar. Indicates that the item has been rejected because it is incorrect. Indicates that the item has been rejected because it is too long or too short. Indicates that the item has been rejected because of incorrect spelling. Indicates the translation is suggested by translation memory. Values for the attribute 'unit'. Refers to words. Refers to pages. Refers to <trans-unit> elements. Refers to <bin-unit> elements. Refers to glyphs. Refers to <trans-unit> and/or <bin-unit> elements. Refers to the occurrences of instances defined by the count-type value. Refers to characters. Refers to lines. Refers to sentences. Refers to paragraphs. Refers to segments. Refers to placeables (inline elements). Values for the attribute 'priority'. Highest priority. High priority. High priority, but not as important as 2. High priority, but not as important as 3. Medium priority, but more important than 6. Medium priority, but less important than 5. Low priority, but more important than 8. Low priority, but more important than 9. Low priority. Lowest priority. This value indicates that all properties can be reformatted. This value must be used alone. This value indicates that no properties should be reformatted. This value must be used alone. This value indicates that all information in the coord attribute can be modified. This value indicates that the x information in the coord attribute can be modified. This value indicates that the y information in the coord attribute can be modified. This value indicates that the cx information in the coord attribute can be modified. This value indicates that the cy information in the coord attribute can be modified. This value indicates that all the information in the font attribute can be modified. This value indicates that the name information in the font attribute can be modified. This value indicates that the size information in the font attribute can be modified. This value indicates that the weight information in the font attribute can be modified. This value indicates that the information in the css-style attribute can be modified. This value indicates that the information in the style attribute can be modified. This value indicates that the information in the exstyle attribute can be modified. Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document. Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed. Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed. Represents a translation proposal from a translation memory or other resource. Represents a previous version of the target element. Represents a rejected version of the target element. Represents a translation to be used for reference purposes only, for example from a related product or a different language. Represents a proposed translation that was used for the translation of the trans-unit, possibly modified. Values for the attribute 'coord'. Version values: 1.0 and 1.1 are allowed for backward compatibility.

About the XML namespace

This schema document describes the XML namespace, in a form suitable for import by other schema documents.

See http://www.w3.org/XML/1998/namespace.html and http://www.w3.org/TR/REC-xml for information about this namespace.

Note that local names in this namespace are intended to be defined only by the World Wide Web Consortium or its subgroups. The names currently defined in this namespace are listed below. They should not be used with conflicting semantics by any Working Group, specification, or document instance.

See further below in this document for more information about how to refer to this schema document from your own XSD schema documents and about the namespace-versioning policy governing this schema document.

lang (as an attribute name)

denotes an attribute whose value is a language code for the natural language of the content of any element; its value is inherited. This name is reserved by virtue of its definition in the XML specification.

Notes

Attempting to install the relevant ISO 2- and 3-letter codes as the enumerated possible values is probably never going to be a realistic possibility.

See BCP 47 at http://www.rfc-editor.org/rfc/bcp/bcp47.txt and the IANA language subtag registry at http://www.iana.org/assignments/language-subtag-registry for further information.

The union allows for the 'un-declaration' of xml:lang with the empty string.

space (as an attribute name)

denotes an attribute whose value is a keyword indicating what whitespace processing discipline is intended for the content of the element; its value is inherited. This name is reserved by virtue of its definition in the XML specification.

base (as an attribute name)

denotes an attribute whose value provides a URI to be used as the base for interpreting any relative URIs in the scope of the element on which it appears; its value is inherited. This name is reserved by virtue of its definition in the XML Base specification.

See http://www.w3.org/TR/xmlbase/ for information about this attribute.

id (as an attribute name)

denotes an attribute whose value should be interpreted as if declared to be of type ID. This name is reserved by virtue of its definition in the xml:id specification.

See http://www.w3.org/TR/xml-id/ for information about this attribute.

Father (in any context at all)

denotes Jon Bosak, the chair of the original XML Working Group. This name is reserved by the following decision of the W3C XML Plenary and XML Coordination groups:

In appreciation for his vision, leadership and dedication the W3C XML Plenary on this 10th day of February, 2000, reserves for Jon Bosak in perpetuity the XML name "xml:Father".

About this schema document

This schema defines attributes and an attribute group suitable for use by schemas wishing to allow xml:base, xml:lang, xml:space or xml:id attributes on elements they define.

To enable this, such a schema must import this schema for the XML namespace, e.g. as follows:

          <schema.. .>
          .. .
           <import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
     

or


           <import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
     

Subsequently, qualified reference to any of the attributes or the group defined below will have the desired effect, e.g.

          <type.. .>
          .. .
           <attributeGroup ref="xml:specialAttrs"/>
     

will define a type which will schema-validate an instance element with any of those attributes.

Versioning policy for this schema document

In keeping with the XML Schema WG's standard versioning policy, this schema document will persist at http://www.w3.org/2009/01/xml.xsd.

At the date of issue it can also be found at http://www.w3.org/2001/xml.xsd.

The schema document at that URI may however change in the future, in order to remain compatible with the latest version of XML Schema itself, or with the XML namespace itself. In other words, if the XML Schema or XML namespaces change, the version of this document at http://www.w3.org/2001/xml.xsd will change accordingly; the version at http://www.w3.org/2009/01/xml.xsd will not change.

Previous dated (and unchanging) versions of this schema document are at:

{ "name": "symfony/translation", "type": "library", "description": "Symfony Translation Component", "keywords": [], "homepage": "http://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" } ], "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/config": "~2.0", "symfony/yaml": "~2.2" }, "suggest": { "symfony/config": "", "symfony/yaml": "" }, "autoload": { "psr-0": { "Symfony\\Component\\Translation\\": "" } }, "target-dir": "Symfony/Component/Translation", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.3-dev" } } } ./Tests/ ./ ./Tests ./vendor Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Stopwatch Component =================== Stopwatch provides a way to profile code. Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Stopwatch/ $ composer install $ phpunit { "name": "symfony/stopwatch", "type": "library", "description": "Symfony Stopwatch Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=5.3.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "autoload": { "psr-0": { "Symfony\\Component\\Stopwatch\\": "" } }, "target-dir": "Symfony/Component/Stopwatch", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } ./Tests/ ./ ./Resources ./Tests ./vendor CHANGELOG ========= 2.2.0 ----- * added ArrayNodeDefinition::canBeEnabled() and ArrayNodeDefinition::canBeDisabled() to ease configuration when some sections are respectively disabled / enabled by default. * added a `normalizeKeys()` method for array nodes (to avoid key normalization) * added numerical type handling for config definitions * added convenience methods for optional configuration sections to ArrayNodeDefinition * added a utils class for XML manipulations 2.1.0 ----- * added a way to add documentation on configuration * implemented `Serializable` on resources * LoaderResolverInterface is now used instead of LoaderResolver for type hinting Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Config Component ================ Config provides the infrastructure for loading configurations from different data sources and optionally monitoring these data sources for changes. There are additional tools for validating, normalizing and handling of defaults that can optionally be used to convert from different formats to arrays. Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Config/ $ composer install $ phpunit { "name": "symfony/config", "type": "library", "description": "Symfony Config Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=5.3.3", "symfony/filesystem": "~2.3" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" }, "autoload": { "psr-0": { "Symfony\\Component\\Config\\": "" } }, "target-dir": "Symfony/Component/Config", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } ./Tests/ ./ ./vendor ./Tests CHANGELOG ========= 2.6.0 ----- * [BC BREAK] `FileValidator` disallow empty files * [BC BREAK] `UserPasswordValidator` source message change * [BC BREAK] added internal `ExecutionContextInterface::setConstraint()` * added `ConstraintViolation::getConstraint()` * [BC BREAK] The `ExpressionValidator` will now evaluate the Expression even when the property value is null or an empty string * deprecated `ClassMetadata::hasMemberMetadatas()` * deprecated `ClassMetadata::getMemberMetadatas()` * deprecated `ClassMetadata::addMemberMetadata()` * [BC BREAK] added `Mapping\MetadataInterface::getConstraints()` * added generic "payload" option to all constraints for attaching domain-specific data * [BC BREAK] added `ConstraintViolationBuilderInterface::setCause()` 2.5.0 ----- * deprecated `ApcCache` in favor of `DoctrineCache` * added `DoctrineCache` to adapt any Doctrine cache * `GroupSequence` now implements `ArrayAccess`, `Countable` and `Traversable` * [BC BREAK] changed `ClassMetadata::getGroupSequence()` to return a `GroupSequence` instance instead of an array * `Callback` can now be put onto properties (useful when you pass a closure to the constraint) * deprecated `ClassBasedInterface` * deprecated `MetadataInterface` * deprecated `PropertyMetadataInterface` * deprecated `PropertyMetadataContainerInterface` * deprecated `Mapping\ElementMetadata` * added `Mapping\MetadataInterface` * added `Mapping\ClassMetadataInterface` * added `Mapping\PropertyMetadataInterface` * added `Mapping\GenericMetadata` * added `Mapping\CascadingStrategy` * added `Mapping\TraversalStrategy` * deprecated `Mapping\ClassMetadata::accept()` * deprecated `Mapping\MemberMetadata::accept()` * removed array type hint of `Mapping\ClassMetadata::setGroupSequence()` * deprecated `MetadataFactoryInterface` * deprecated `Mapping\BlackholeMetadataFactory` * deprecated `Mapping\ClassMetadataFactory` * added `Mapping\Factory\MetadataFactoryInterface` * added `Mapping\Factory\BlackHoleMetadataFactory` * added `Mapping\Factory\LazyLoadingMetadataFactory` * deprecated `ExecutionContextInterface` * deprecated `ExecutionContext` * deprecated `GlobalExecutionContextInterface` * added `Context\ExecutionContextInterface` * added `Context\ExecutionContext` * added `Context\ExecutionContextFactoryInterface` * added `Context\ExecutionContextFactory` * deprecated `ValidatorInterface` * deprecated `Validator` * deprecated `ValidationVisitorInterface` * deprecated `ValidationVisitor` * added `Validator\ValidatorInterface` * added `Validator\RecursiveValidator` * added `Validator\ContextualValidatorInterface` * added `Validator\RecursiveContextualValidator` * added `Violation\ConstraintViolationBuilderInterface` * added `Violation\ConstraintViolationBuilder` * added `ConstraintViolation::getParameters()` * added `ConstraintViolation::getPlural()` * added `Constraints\Traverse` * deprecated `$deep` property in `Constraints\Valid` * added `ValidatorBuilderInterface::setApiVersion()` * added `Validation::API_VERSION_2_4` * added `Validation::API_VERSION_2_5` * added `Exception\OutOfBoundsException` * added `Exception\UnsupportedMetadataException` * made `Exception\ValidatorException` extend `Exception\RuntimeException` * added `Util\PropertyPath` * made the PropertyAccess component an optional dependency * deprecated `ValidatorBuilder::setPropertyAccessor()` 2.4.0 ----- * added a constraint the uses the expression language * added `minRatio`, `maxRatio`, `allowSquare`, `allowLandscape`, and `allowPortrait` to Image validator 2.3.29 ------ * fixed compatibility with PHP7 and up by introducing new constraints (IsNull, IsTrue, IsFalse) and related validators (IsNullValidator, IsTrueValidator, IsFalseValidator) 2.3.0 ----- * added the ISBN, ISSN, and IBAN validators * copied the constraints `Optional` and `Required` to the `Symfony\Component\Validator\Constraints\` namespace and deprecated the original classes. * added comparison validators (EqualTo, NotEqualTo, LessThan, LessThanOrEqualTo, GreaterThan, GreaterThanOrEqualTo, IdenticalTo, NotIdenticalTo) 2.2.0 ----- * added a CardScheme validator * added a Luhn validator * moved @api-tags from `Validator` to `ValidatorInterface` * moved @api-tags from `ConstraintViolation` to the new `ConstraintViolationInterface` * moved @api-tags from `ConstraintViolationList` to the new `ConstraintViolationListInterface` * moved @api-tags from `ExecutionContext` to the new `ExecutionContextInterface` * [BC BREAK] `ConstraintValidatorInterface::initialize` is now type hinted against `ExecutionContextInterface` instead of `ExecutionContext` * [BC BREAK] changed the visibility of the properties in `Validator` from protected to private * deprecated `ClassMetadataFactoryInterface` in favor of the new `MetadataFactoryInterface` * deprecated `ClassMetadataFactory::getClassMetadata` in favor of `getMetadataFor` * created `MetadataInterface`, `PropertyMetadataInterface`, `ClassBasedInterface` and `PropertyMetadataContainerInterface` * deprecated `GraphWalker` in favor of the new `ValidationVisitorInterface` * deprecated `ExecutionContext::addViolationAtPath` * deprecated `ExecutionContext::addViolationAtSubPath` in favor of `ExecutionContextInterface::addViolationAt` * deprecated `ExecutionContext::getCurrentClass` in favor of `ExecutionContextInterface::getClassName` * deprecated `ExecutionContext::getCurrentProperty` in favor of `ExecutionContextInterface::getPropertyName` * deprecated `ExecutionContext::getCurrentValue` in favor of `ExecutionContextInterface::getValue` * deprecated `ExecutionContext::getGraphWalker` in favor of `ExecutionContextInterface::validate` and `ExecutionContextInterface::validateValue` * improved `ValidatorInterface::validateValue` to accept arrays of constraints * changed `ValidatorInterface::getMetadataFactory` to return a `MetadataFactoryInterface` instead of a `ClassMetadataFactoryInterface` * removed `ClassMetadataFactoryInterface` type hint from `ValidatorBuilderInterface::setMetadataFactory`. As of Symfony 2.3, this method will be typed against `MetadataFactoryInterface` instead. * [BC BREAK] the switches `traverse` and `deep` in the `Valid` constraint and in `GraphWalker::walkReference` are ignored for arrays now. Arrays are always traversed recursively. * added dependency to Translation component * violation messages are now translated with a TranslatorInterface implementation * [BC BREAK] inserted argument `$message` in the constructor of `ConstraintViolation` * [BC BREAK] inserted arguments `$translator` and `$translationDomain` in the constructor of `ExecutionContext` * [BC BREAK] inserted arguments `$translator` and `$translationDomain` in the constructor of `GraphWalker` * [BC BREAK] inserted arguments `$translator` and `$translationDomain` in the constructor of `ValidationVisitor` * [BC BREAK] inserted arguments `$translator` and `$translationDomain` in the constructor of `Validator` * [BC BREAK] added `setTranslator()` and `setTranslationDomain()` to `ValidatorBuilderInterface` * improved the Validator to support pluralized messages by default * [BC BREAK] changed the source of all pluralized messages in the translation files to the pluralized version * added ExceptionInterface, BadMethodCallException and InvalidArgumentException 2.1.0 ----- * added support for `ctype_*` assertions in `TypeValidator` * improved the ImageValidator with min width, max width, min height, and max height constraints * added support for MIME with wildcard in FileValidator * changed Collection validator to add "missing" and "extra" errors to individual fields * changed default value for `extraFieldsMessage` and `missingFieldsMessage` in Collection constraint * made ExecutionContext immutable * deprecated Constraint methods `setMessage`, `getMessageTemplate` and `getMessageParameters` * added support for dynamic group sequences with the GroupSequenceProvider pattern * [BC BREAK] ConstraintValidatorInterface method `isValid` has been renamed to `validate`, its return value was dropped. ConstraintValidator still contains `isValid` for BC * [BC BREAK] collections in fields annotated with `Valid` are not traversed recursively anymore by default. `Valid` contains a new property `deep` which enables the BC behavior. * added Count constraint * added Length constraint * added Range constraint * deprecated the Min and Max constraints * deprecated the MinLength and MaxLength constraints * added Validation and ValidatorBuilderInterface * deprecated ValidatorContext, ValidatorContextInterface and ValidatorFactory Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. This value should be false. Cette valeur doit être fausse. This value should be true. Cette valeur doit être vraie. This value should be of type {{ type }}. Cette valeur doit être de type {{ type }}. This value should be blank. Cette valeur doit être vide. The value you selected is not a valid choice. Cette valeur doit être l'un des choix proposés. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Vous devez sélectionner au moins {{ limit }} choix.|Vous devez sélectionner au moins {{ limit }} choix. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Vous devez sélectionner au maximum {{ limit }} choix.|Vous devez sélectionner au maximum {{ limit }} choix. One or more of the given values is invalid. Une ou plusieurs des valeurs soumises sont invalides. This field was not expected. Ce champ n'a pas été prévu. This field is missing. Ce champ est manquant. This value is not a valid date. Cette valeur n'est pas une date valide. This value is not a valid datetime. Cette valeur n'est pas une date valide. This value is not a valid email address. Cette valeur n'est pas une adresse email valide. The file could not be found. Le fichier n'a pas été trouvé. The file is not readable. Le fichier n'est pas lisible. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Le fichier est trop volumineux ({{ size }} {{ suffix }}). Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Le type du fichier est invalide ({{ type }}). Les types autorisés sont {{ types }}. This value should be {{ limit }} or less. Cette valeur doit être inférieure ou égale à {{ limit }}. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractères. This value should be {{ limit }} or more. Cette valeur doit être supérieure ou égale à {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractères. This value should not be blank. Cette valeur ne doit pas être vide. This value should not be null. Cette valeur ne doit pas être nulle. This value should be null. Cette valeur doit être nulle. This value is not valid. Cette valeur n'est pas valide. This value is not a valid time. Cette valeur n'est pas une heure valide. This value is not a valid URL. Cette valeur n'est pas une URL valide. The two values should be equal. Les deux valeurs doivent être identiques. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Le fichier est trop volumineux. Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}. The file is too large. Le fichier est trop volumineux. The file could not be uploaded. Le téléchargement de ce fichier est impossible. This value should be a valid number. Cette valeur doit être un nombre. This file is not a valid image. Ce fichier n'est pas une image valide. This is not a valid IP address. Cette adresse IP n'est pas valide. This value is not a valid language. Cette langue n'est pas valide. This value is not a valid locale. Ce paramètre régional n'est pas valide. This value is not a valid country. Ce pays n'est pas valide. This value is already used. Cette valeur est déjà utilisée. The size of the image could not be detected. La taille de l'image n'a pas pu être détectée. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. La largeur de l'image est trop grande ({{ width }}px). La largeur maximale autorisée est de {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. La largeur de l'image est trop petite ({{ width }}px). La largeur minimale attendue est de {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. La hauteur de l'image est trop grande ({{ height }}px). La hauteur maximale autorisée est de {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. La hauteur de l'image est trop petite ({{ height }}px). La hauteur minimale attendue est de {{ min_height }}px. This value should be the user's current password. Cette valeur doit être le mot de passe actuel de l'utilisateur. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Cette chaine doit avoir exactement {{ limit }} caractère.|Cette chaine doit avoir exactement {{ limit }} caractères. The file was only partially uploaded. Le fichier a été partiellement transféré. No file was uploaded. Aucun fichier n'a été transféré. No temporary folder was configured in php.ini. Aucun répertoire temporaire n'a été configuré dans le php.ini. Cannot write temporary file to disk. Impossible d'écrire le fichier temporaire sur le disque. A PHP extension caused the upload to fail. Une extension PHP a empêché le transfert du fichier. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Cette collection doit contenir {{ limit }} élément ou plus.|Cette collection doit contenir {{ limit }} éléments ou plus. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Cette collection doit contenir {{ limit }} élément ou moins.|Cette collection doit contenir {{ limit }} éléments ou moins. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Cette collection doit contenir exactement {{ limit }} élément.|Cette collection doit contenir exactement {{ limit }} éléments. Invalid card number. Numéro de carte invalide. Unsupported card type or invalid card number. Type de carte non supporté ou numéro invalide. This is not a valid International Bank Account Number (IBAN). Le numéro IBAN (International Bank Account Number) saisi n'est pas valide. This value is not a valid ISBN-10. Cette valeur n'est pas un code ISBN-10 valide. This value is not a valid ISBN-13. Cette valeur n'est pas un code ISBN-13 valide. This value is neither a valid ISBN-10 nor a valid ISBN-13. Cette valeur n'est ni un code ISBN-10, ni un code ISBN-13 valide. This value is not a valid ISSN. Cette valeur n'est pas un code ISSN valide. This value is not a valid currency. Cette valeur n'est pas une devise valide. This value should be equal to {{ compared_value }}. Cette valeur doit être égale à {{ compared_value }}. This value should be greater than {{ compared_value }}. Cette valeur doit être supérieure à {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Cette valeur doit être supérieure ou égale à {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Cette valeur doit être identique à {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Cette valeur doit être inférieure à {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Cette valeur doit être inférieure ou égale à {{ compared_value }}. This value should not be equal to {{ compared_value }}. Cette valeur ne doit pas être égale à {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Cette valeur ne doit pas être identique à {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Le rapport largeur/hauteur de l'image est trop grand ({{ ratio }}). Le rapport maximal autorisé est {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Le rapport largeur/hauteur de l'image est trop petit ({{ ratio }}). Le rapport minimal attendu est {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. L'image est carrée ({{ width }}x{{ height }}px). Les images carrées ne sont pas autorisées. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. L'image est au format paysage ({{ width }}x{{ height }}px). Les images au format paysage ne sont pas autorisées. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. L'image est au format portrait ({{ width }}x{{ height }}px). Les images au format portrait ne sont pas autorisées. An empty file is not allowed. Un fichier vide n'est pas autorisé. This value does not match the expected {{ charset }} charset. Cette valeur ne correspond pas au jeu de caractères {{ charset }} attendu. This value should be false. This value should be false. This value should be true. This value should be true. This value should be of type {{ type }}. This value should be of type {{ type }}. This value should be blank. This value should be blank. The value you selected is not a valid choice. The value you selected is not a valid choice. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. One or more of the given values is invalid. One or more of the given values is invalid. This field was not expected. This field was not expected. This field is missing. This field is missing. This value is not a valid date. This value is not a valid date. This value is not a valid datetime. This value is not a valid datetime. This value is not a valid email address. This value is not a valid email address. The file could not be found. The file could not be found. The file is not readable. The file is not readable. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. This value should be {{ limit }} or less. This value should be {{ limit }} or less. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. This value should be {{ limit }} or more. This value should be {{ limit }} or more. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. This value should not be blank. This value should not be blank. This value should not be null. This value should not be null. This value should be null. This value should be null. This value is not valid. This value is not valid. This value is not a valid time. This value is not a valid time. This value is not a valid URL. This value is not a valid URL. The two values should be equal. The two values should be equal. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. The file is too large. The file is too large. The file could not be uploaded. The file could not be uploaded. This value should be a valid number. This value should be a valid number. This file is not a valid image. This file is not a valid image. This is not a valid IP address. This is not a valid IP address. This value is not a valid language. This value is not a valid language. This value is not a valid locale. This value is not a valid locale. This value is not a valid country. This value is not a valid country. This value is already used. This value is already used. The size of the image could not be detected. The size of the image could not be detected. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. This value should be the user's current password. This value should be the user's current password. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. The file was only partially uploaded. The file was only partially uploaded. No file was uploaded. No file was uploaded. No temporary folder was configured in php.ini. No temporary folder was configured in php.ini. Cannot write temporary file to disk. Cannot write temporary file to disk. A PHP extension caused the upload to fail. A PHP extension caused the upload to fail. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Invalid card number. Invalid card number. Unsupported card type or invalid card number. Unsupported card type or invalid card number. This is not a valid International Bank Account Number (IBAN). This is not a valid International Bank Account Number (IBAN). This value is not a valid ISBN-10. This value is not a valid ISBN-10. This value is not a valid ISBN-13. This value is not a valid ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. This value is not a valid ISSN. This value is not a valid ISSN. This value is not a valid currency. This value is not a valid currency. This value should be equal to {{ compared_value }}. This value should be equal to {{ compared_value }}. This value should be greater than {{ compared_value }}. This value should be greater than {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. This value should be less than {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. This value should not be equal to {{ compared_value }}. This value should not be equal to {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. An empty file is not allowed. An empty file is not allowed. This value does not match the expected {{ charset }} charset. This value does not match the expected {{ charset }} charset. This value should be false. Este valor deveria ser falso. This value should be true. Este valor deveria ser verdadeiro. This value should be of type {{ type }}. Este valor deveria ser do tipo {{ type }}. This value should be blank. Este valor deveria ser vazio. The value you selected is not a valid choice. O valor selecionado não é uma opção válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Você deveria selecionar {{ limit }} opção no mínimo.|Você deveria selecionar {{ limit }} opções no mínimo. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Você deve selecionar, no máximo {{ limit }} opção.|Você deve selecionar, no máximo {{ limit }} opções. One or more of the given values is invalid. Um ou mais dos valores introduzidos não são válidos. This field was not expected. Este campo não era esperado. This field is missing. Este campo está faltando. This value is not a valid date. Este valor não é uma data válida. This value is not a valid datetime. Este valor não é uma data-hora válida. This value is not a valid email address. Este valor não é um endereço de e-mail válido. The file could not be found. O arquivo não pôde ser encontrado. The file is not readable. O arquivo não pôde ser lido. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é de {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}. This value should be {{ limit }} or less. Este valor deveria ser {{ limit }} ou menor. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. O valor é muito longo. Deveria ter {{ limit }} caracteres ou menos. This value should be {{ limit }} or more. Este valor deveria ser {{ limit }} ou mais. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. O valor é muito curto. Deveria de ter {{ limit }} caractere ou mais.|O valor é muito curto. Deveria de ter {{ limit }} caracteres ou mais. This value should not be blank. Este valor não deveria ser branco/vazio. This value should not be null. Este valor não deveria ser nulo. This value should be null. Este valor deveria ser nulo. This value is not valid. Este valor não é válido. This value is not a valid time. Este valor não é uma hora válida. This value is not a valid URL. Este valor não é um URL válido. The two values should be equal. Os dois valores deveriam ser iguais. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}. The file is too large. O ficheiro é muito grande. The file could not be uploaded. Não foi possível carregar o ficheiro. This value should be a valid number. Este valor deveria de ser um número válido. This file is not a valid image. Este ficheiro não é uma imagem. This is not a valid IP address. Este endereço de IP não é válido. This value is not a valid language. Este valor não é uma linguagem válida. This value is not a valid locale. Este valor não é um 'locale' válido. This value is not a valid country. Este valor não é um País válido. This value is already used. Este valor já está a ser usado. The size of the image could not be detected. O tamanho da imagem não foi detetado. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A largura da imagem ({{ width }}px) é muito grande. A largura máxima da imagem é: {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A largura da imagem ({{ width }}px) é muito pequena. A largura miníma da imagem é de: {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A altura da imagem ({{ height }}px) é muito grande. A altura máxima da imagem é de: {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A altura da imagem ({{ height }}px) é muito pequena. A altura miníma da imagem é de: {{ min_height }}px. This value should be the user's current password. Este valor deveria de ser a password atual do utilizador. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor tem de ter exatamente {{ limit }} carateres. The file was only partially uploaded. Só foi enviado parte do ficheiro. No file was uploaded. Nenhum ficheiro foi enviado. No temporary folder was configured in php.ini. Não existe nenhum directório temporária configurado no ficheiro php.ini. Cannot write temporary file to disk. Não foi possível escrever ficheiros temporários no disco. A PHP extension caused the upload to fail. Uma extensão PHP causou a falha no envio. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos. Invalid card number. Número de cartão inválido. Unsupported card type or invalid card number. Tipo de cartão não suportado ou número de cartão inválido. This is not a valid International Bank Account Number (IBAN). Este não é um Número Internacional de Conta Bancária (IBAN) válido. This value is not a valid ISBN-10. Este valor não é um ISBN-10 válido. This value is not a valid ISBN-13. Este valor não é um ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor não é um ISBN-10 ou ISBN-13 válido. This value is not a valid ISSN. Este valor não é um ISSN válido. This value is not a valid currency. Este não é um valor monetário válido. This value should be equal to {{ compared_value }}. Este valor deve ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor deve ser superior a {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor deve ser igual ou superior a {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor deve ser inferior a {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor deve ser igual ou inferior a {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor não deve ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. O formato da imagem é muito grande ({{ ratio }}). O formato máximo é {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. O formato da imagem é muito pequeno ({{ ratio }}). O formato mínimo esperado é {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. A imagem é um quadrado ({{ width }}x{{ height }}px). Imagens quadradas não são permitidas. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. A imagem está orientada à paisagem ({{ width }}x{{ height }}px). Imagens orientadas à paisagem não são permitidas. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. A imagem está orientada ao retrato ({{ width }}x{{ height }}px). Imagens orientadas ao retrato não são permitidas. An empty file is not allowed. Ficheiro vazio não é permitido. This value should be false. Este valor deve ser falso. This value should be true. Este valor deve ser verdadeiro. This value should be of type {{ type }}. Este valor deve ser do tipo {{ type }}. This value should be blank. Este valor deve ser vazio. The value you selected is not a valid choice. O valor selecionado não é uma opção válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Você deve selecionar, no mínimo, {{ limit }} opção.|Você deve selecionar, no mínimo, {{ limit }} opções. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Você deve selecionar, no máximo, {{ limit }} opção.|Você deve selecionar, no máximo, {{ limit }} opções. One or more of the given values is invalid. Um ou mais valores informados são inválidos. This field was not expected. Este campo não era esperado. This field is missing. Este campo está ausente. This value is not a valid date. Este valor não é uma data válida. This value is not a valid datetime. Este valor não é uma data e hora válida. This value is not a valid email address. Este valor não é um endereço de e-mail válido. The file could not be found. O arquivo não foi encontrado. The file is not readable. O arquivo não pode ser lido. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}. This value should be {{ limit }} or less. Este valor deve ser {{ limit }} ou menos. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Este valor é muito longo. Deve ter {{ limit }} caractere ou menos.|Este valor é muito longo. Deve ter {{ limit }} caracteres ou menos. This value should be {{ limit }} or more. Este valor deve ser {{ limit }} ou mais. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Este valor é muito curto. Deve ter {{ limit }} caractere ou mais.|Este valor é muito curto. Deve ter {{ limit }} caracteres ou mais. This value should not be blank. Este valor não deve ser vazio. This value should not be null. Este valor não deve ser nulo. This value should be null. Este valor deve ser nulo. This value is not valid. Este valor não é válido. This value is not a valid time. Este valor não é uma hora válida. This value is not a valid URL. Este valor não é uma URL válida. The two values should be equal. Os dois valores devem ser iguais. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}. The file is too large. O arquivo é muito grande. The file could not be uploaded. O arquivo não pode ser enviado. This value should be a valid number. Este valor deve ser um número válido. This file is not a valid image. Este arquivo não é uma imagem válida. This is not a valid IP address. Este não é um endereço de IP válido. This value is not a valid language. Este valor não é um idioma válido. This value is not a valid locale. Este valor não é uma localidade válida. This value is not a valid country. Este valor não é um país válido. This value is already used. Este valor já está sendo usado. The size of the image could not be detected. O tamanho da imagem não pode ser detectado. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A largura da imagem é muito grande ({{ width }}px). A largura máxima permitida é de {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A largura da imagem é muito pequena ({{ width }}px). A largura mínima esperada é de {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A altura da imagem é muito grande ({{ height }}px). A altura máxima permitida é de {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A altura da imagem é muito pequena ({{ height }}px). A altura mínima esperada é de {{ min_height }}px. This value should be the user's current password. Este valor deve ser a senha atual do usuário. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor deve ter exatamente {{ limit }} caractere.|Este valor deve ter exatamente {{ limit }} caracteres. The file was only partially uploaded. O arquivo foi enviado apenas parcialmente. No file was uploaded. Nenhum arquivo foi enviado. No temporary folder was configured in php.ini. Nenhum diretório temporário foi configurado no php.ini. Cannot write temporary file to disk. Não foi possível escrever o arquivo temporário no disco. A PHP extension caused the upload to fail. Uma extensão PHP fez com que o envio falhasse. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos. Invalid card number. Número de cartão inválido. Unsupported card type or invalid card number. Tipo de cartão não suportado ou número de cartão inválido. This is not a valid International Bank Account Number (IBAN). Este não é um Número Internacional de Conta Bancária (IBAN) válido. This value is not a valid ISBN-10. Este valor não é um ISBN-10 válido. This value is not a valid ISBN-13. Este valor não é um ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor não é um ISBN-10 e nem um ISBN-13 válido. This value is not a valid ISSN. Este valor não é um ISSN válido. This value is not a valid currency. Este não é um valor monetário válido. This value should be equal to {{ compared_value }}. Este valor deve ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor deve ser maior que {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor deve ser maior ou igual a {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor deve ser menor que {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor deve ser menor ou igual a {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor não deve ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. A proporção da imagem é muito grande ({{ ratio }}). A proporção máxima permitida é {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. A proporção da imagem é muito pequena ({{ ratio }}). A proporção mínima esperada é {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. A imagem está num formato quadrado ({{ width }}x{{ height }}px). Imagens com formato quadrado não são permitidas. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. A imagem está orientada à paisagem ({{ width }}x{{ height }}px). Imagens orientadas à paisagem não são permitidas. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. A imagem está orientada ao retrato ({{ width }}x{{ height }}px). Imagens orientadas ao retrato não são permitidas. An empty file is not allowed. Arquivo vazio não é permitido. The host could not be resolved. O host não pôde ser resolvido. This value does not match the expected {{ charset }} charset. Este valor não corresponde ao charset {{ charset }} esperado. This value should be false. הערך צריך להיות שקר. This value should be true. הערך צריך להיות אמת. This value should be of type {{ type }}. הערך צריך להיות מסוג {{ type }}. This value should be blank. הערך צריך להיות ריק. The value you selected is not a valid choice. הערך שבחרת אינו חוקי. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. אתה צריך לבחור לפחות {{ limit }} אפשרויות.|אתה צריך לבחור לפחות {{ limit }} אפשרויות. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. אתה צריך לבחור לכל היותר {{ limit }} אפשרויות.|אתה צריך לבחור לכל היותר {{ limit }} אפשרויות. One or more of the given values is invalid. אחד או יותר מהערכים אינו חוקי. This field was not expected. שדה זה לא היה צפוי This field is missing. שדה זה חסר. This value is not a valid date. הערך אינו תאריך חוקי. This value is not a valid datetime. הערך אינו תאריך ושעה חוקיים. This value is not a valid email address. כתובת המייל אינה תקינה. The file could not be found. הקובץ לא נמצא. The file is not readable. לא ניתן לקרוא את הקובץ. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. הקובץ גדול מדי ({{ size }} {{ suffix }}). הגודל המרבי המותר הוא {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. סוג MIME של הקובץ אינו חוקי ({{ type }}). מותרים סוגי MIME {{ types }}. This value should be {{ limit }} or less. הערך צריל להכיל {{ limit }} תווים לכל היותר. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר.|הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר. This value should be {{ limit }} or more. הערך צריך להכיל {{ limit }} תווים לפחות. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות.|הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות. This value should not be blank. הערך לא אמור להיות ריק. This value should not be null. הערך לא אמור להיות ריק. This value should be null. הערך צריך להיות ריק. This value is not valid. הערך אינו חוקי. This value is not a valid time. הערך אינו זמן תקין. This value is not a valid URL. זאת אינה כתובת אתר תקינה. The two values should be equal. שני הערכים צריכים להיות שווים. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. הקובץ גדול מדי. הגודל המרבי המותר הוא {{ limit }} {{ suffix }}. The file is too large. הקובץ גדול מדי. The file could not be uploaded. לא ניתן לעלות את הקובץ. This value should be a valid number. הערך צריך להיות מספר חוקי. This file is not a valid image. הקובץ הזה אינו תמונה תקינה. This is not a valid IP address. זו אינה כתובת IP חוקית. This value is not a valid language. הערך אינו שפה חוקית. This value is not a valid locale. הערך אינו אזור תקף. This value is not a valid country. הערך אינו ארץ חוקית. This value is already used. הערך כבר בשימוש. The size of the image could not be detected. לא ניתן לקבוע את גודל התמונה. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. רוחב התמונה גדול מדי ({{ width }}px). הרוחב המקסימלי הוא {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. רוחב התמונה קטן מדי ({{ width }}px). הרוחב המינימלי הוא {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. גובה התמונה גדול מדי ({{ height }}px). הגובה המקסימלי הוא {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. גובה התמונה קטן מדי ({{ height }}px). הגובה המינימלי הוא {{ min_height }}px. This value should be the user's current password. הערך צריך להיות סיסמת המשתמש הנוכחי. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. הערך צריך להיות בדיוק {{ limit }} תווים.|הערך צריך להיות בדיוק {{ limit }} תווים. The file was only partially uploaded. הקובץ הועלה באופן חלקי. No file was uploaded. הקובץ לא הועלה. No temporary folder was configured in php.ini. לא הוגדרה תיקייה זמנית ב php.ini. Cannot write temporary file to disk. לא ניתן לכתוב קובץ זמני לדיסק. A PHP extension caused the upload to fail. סיומת PHP גרם להעלאה להיכשל. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. האוסף אמור להכיל {{ limit }} אלמנטים או יותר.|האוסף אמור להכיל {{ limit }} אלמנטים או יותר. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. האוסף אמור להכיל {{ limit }} אלמנטים או פחות.|האוסף אמור להכיל {{ limit }} אלמנטים או פחות. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. האוסף צריך להכיל בדיוק {{ limit }} אלמנטים.|האוסף צריך להכיל בדיוק {{ limit }} אלמנטים. Invalid card number. מספר הכרטיס אינו חוקי. Unsupported card type or invalid card number. סוג הכרטיס אינו נתמך או לא חוקי. This is not a valid International Bank Account Number (IBAN). This is not a valid International Bank Account Number (IBAN). This value is not a valid ISBN-10. This value is not a valid ISBN-10. This value is not a valid ISBN-13. This value is not a valid ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. This value is not a valid ISSN. This value is not a valid ISSN. This value is not a valid currency. This value is not a valid currency. This value should be equal to {{ compared_value }}. This value should be equal to {{ compared_value }}. This value should be greater than {{ compared_value }}. This value should be greater than {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. This value should be less than {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. This value should not be equal to {{ compared_value }}. This value should not be equal to {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. An empty file is not allowed. An empty file is not allowed. This value should be false. Ennek az értéknek hamisnak kell lennie. This value should be true. Ennek az értéknek igaznak kell lennie. This value should be of type {{ type }}. Ennek az értéknek {{ type }} típusúnak kell lennie. This value should be blank. Ennek az értéknek üresnek kell lennie. The value you selected is not a valid choice. A választott érték érvénytelen. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Legalább {{ limit }} értéket kell kiválasztani.|Legalább {{ limit }} értéket kell kiválasztani. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Legfeljebb {{ limit }} értéket lehet kiválasztani.|Legfeljebb {{ limit }} értéket lehet kiválasztani. One or more of the given values is invalid. A megadott értékek közül legalább egy érvénytelen. This field was not expected. Nem várt mező. This field is missing. Ez a mező hiányzik. This value is not a valid date. Ez az érték nem egy érvényes dátum. This value is not a valid datetime. Ez az érték nem egy érvényes időpont. This value is not a valid email address. Ez az érték nem egy érvényes e-mail cím. The file could not be found. A fájl nem található. The file is not readable. A fájl nem olvasható. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. A fájl túl nagy ({{ size }} {{ suffix }}). A legnagyobb megengedett méret {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. A fájl MIME típusa érvénytelen ({{ type }}). Az engedélyezett MIME típusok: {{ types }}. This value should be {{ limit }} or less. Ez az érték legfeljebb {{ limit }} lehet. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat.|Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat. This value should be {{ limit }} or more. Ez az érték legalább {{ limit }} kell, hogy legyen. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia.|Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia. This value should not be blank. Ez az érték nem lehet üres. This value should not be null. Ez az érték nem lehet null. This value should be null. Ennek az értéknek nullnak kell lennie. This value is not valid. Ez az érték nem érvényes. This value is not a valid time. Ez az érték nem egy érvényes időpont. This value is not a valid URL. Ez az érték nem egy érvényes URL. The two values should be equal. A két értéknek azonosnak kell lennie. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. A fájl túl nagy. A megengedett maximális méret: {{ limit }} {{ suffix }}. The file is too large. A fájl túl nagy. The file could not be uploaded. A fájl nem tölthető fel. This value should be a valid number. Ennek az értéknek érvényes számnak kell lennie. This file is not a valid image. Ez a fájl nem egy érvényes kép. This is not a valid IP address. Ez az érték nem egy érvényes IP cím. This value is not a valid language. Ez az érték nem egy érvényes nyelv. This value is not a valid locale. Ez az érték nem egy érvényes területi beállítás. This value is not a valid country. Ez az érték nem egy érvényes ország. This value is already used. Ez az érték már használatban van. The size of the image could not be detected. A kép méretét nem lehet megállapítani. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A kép szélessége túl nagy ({{ width }}px). A megengedett legnagyobb szélesség {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A kép szélessége túl kicsi ({{ width }}px). Az elvárt legkisebb szélesség {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A kép magassága túl nagy ({{ height }}px). A megengedett legnagyobb magasság {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A kép magassága túl kicsi ({{ height }}px). Az elvárt legkisebb magasság {{ min_height }}px. This value should be the user's current password. Ez az érték a felhasználó jelenlegi jelszavával kell megegyezzen. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia.|Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia. The file was only partially uploaded. A fájl csak részben lett feltöltve. No file was uploaded. Nem lett fájl feltöltve. No temporary folder was configured in php.ini. Nincs ideiglenes könyvtár beállítva a php.ini-ben. Cannot write temporary file to disk. Az ideiglenes fájl nem írható a lemezre. A PHP extension caused the upload to fail. Egy PHP bővítmény miatt a feltöltés nem sikerült. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat.|Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia. Invalid card number. Érvénytelen kártyaszám. Unsupported card type or invalid card number. Nem támogatott kártyatípus vagy érvénytelen kártyaszám. This is not a valid International Bank Account Number (IBAN). Érvénytelen nemzetközi bankszámlaszám (IBAN). This value is not a valid ISBN-10. Ez az érték nem egy érvényes ISBN-10. This value is not a valid ISBN-13. Ez az érték nem egy érvényes ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ez az érték nem egy érvényes ISBN-10 vagy ISBN-13. This value is not a valid ISSN. Ez az érték nem egy érvényes ISSN. This value is not a valid currency. Ez az érték nem egy érvényes pénznem. This value should be equal to {{ compared_value }}. Ez az érték legyen {{ compared_value }}. This value should be greater than {{ compared_value }}. Ez az érték nagyobb legyen, mint {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ez az érték nagyobb vagy egyenlő legyen, mint {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ez az érték ugyanolyan legyen, mint {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ez az érték kisebb legyen, mint {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ez az érték kisebb vagy egyenlő legyen, mint {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ez az érték ne legyen {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ez az érték ne legyen ugyanolyan, mint {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. A képarány túl nagy ({{ ratio }}). A megengedett legnagyobb képarány {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. A képarány túl kicsi ({{ ratio }}). A megengedett legkisebb képarány {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. A kép négyzet alakú ({{ width }}x{{ height }}px). A négyzet alakú képek nem engedélyezettek. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. A kép fekvő tájolású ({{ width }}x{{ height }}px). A fekvő tájolású képek nem engedélyezettek. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. A kép álló tájolású ({{ width }}x{{ height }}px). Az álló tájolású képek nem engedélyezettek. An empty file is not allowed. Üres fájl nem megengedett. This value does not match the expected {{ charset }} charset. Ez az érték nem az elvárt {{ charset }} karakterkódolást használja. This value should be false. Dieser Wert sollte false sein. This value should be true. Dieser Wert sollte true sein. This value should be of type {{ type }}. Dieser Wert sollte vom Typ {{ type }} sein. This value should be blank. Dieser Wert sollte leer sein. The value you selected is not a valid choice. Sie haben einen ungültigen Wert ausgewählt. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Sie müssen mindestens {{ limit }} Möglichkeit wählen.|Sie müssen mindestens {{ limit }} Möglichkeiten wählen. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Sie dürfen höchstens {{ limit }} Möglichkeit wählen.|Sie dürfen höchstens {{ limit }} Möglichkeiten wählen. One or more of the given values is invalid. Einer oder mehrere der angegebenen Werte sind ungültig. This field was not expected. Dieses Feld wurde nicht erwartet. This field is missing. Dieses Feld fehlt. This value is not a valid date. Dieser Wert entspricht keiner gültigen Datumsangabe. This value is not a valid datetime. Dieser Wert entspricht keiner gültigen Datums- und Zeitangabe. This value is not a valid email address. Dieser Wert ist keine gültige E-Mail-Adresse. The file could not be found. Die Datei wurde nicht gefunden. The file is not readable. Die Datei ist nicht lesbar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Die Datei ist zu groß ({{ size }} {{ suffix }}). Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Der Dateityp ist ungültig ({{ type }}). Erlaubte Dateitypen sind {{ types }}. This value should be {{ limit }} or less. Dieser Wert sollte kleiner oder gleich {{ limit }} sein. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben. This value should be {{ limit }} or more. Dieser Wert sollte größer oder gleich {{ limit }} sein. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben. This value should not be blank. Dieser Wert sollte nicht leer sein. This value should not be null. Dieser Wert sollte nicht null sein. This value should be null. Dieser Wert sollte null sein. This value is not valid. Dieser Wert ist nicht gültig. This value is not a valid time. Dieser Wert entspricht keiner gültigen Zeitangabe. This value is not a valid URL. Dieser Wert ist keine gültige URL. The two values should be equal. Die beiden Werte sollten identisch sein. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Die Datei ist zu groß. Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}. The file is too large. Die Datei ist zu groß. The file could not be uploaded. Die Datei konnte nicht hochgeladen werden. This value should be a valid number. Dieser Wert sollte eine gültige Zahl sein. This file is not a valid image. Diese Datei ist kein gültiges Bild. This is not a valid IP address. Dies ist keine gültige IP-Adresse. This value is not a valid language. Dieser Wert entspricht keiner gültigen Sprache. This value is not a valid locale. Dieser Wert entspricht keinem gültigen Gebietsschema. This value is not a valid country. Dieser Wert entspricht keinem gültigen Land. This value is already used. Dieser Wert wird bereits verwendet. The size of the image could not be detected. Die Größe des Bildes konnte nicht ermittelt werden. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Die Bildbreite ist zu groß ({{ width }}px). Die maximal zulässige Breite beträgt {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Die Bildbreite ist zu gering ({{ width }}px). Die erwartete Mindestbreite beträgt {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Die Bildhöhe ist zu groß ({{ height }}px). Die maximal zulässige Höhe beträgt {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Die Bildhöhe ist zu gering ({{ height }}px). Die erwartete Mindesthöhe beträgt {{ min_height }}px. This value should be the user's current password. Dieser Wert sollte dem aktuellen Benutzerpasswort entsprechen. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Dieser Wert sollte genau {{ limit }} Zeichen lang sein.|Dieser Wert sollte genau {{ limit }} Zeichen lang sein. The file was only partially uploaded. Die Datei wurde nur teilweise hochgeladen. No file was uploaded. Es wurde keine Datei hochgeladen. No temporary folder was configured in php.ini. Es wurde kein temporärer Ordner in der php.ini konfiguriert. Cannot write temporary file to disk. Kann die temporäre Datei nicht speichern. A PHP extension caused the upload to fail. Eine PHP-Erweiterung verhinderte den Upload. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Diese Sammlung sollte genau {{ limit }} Element beinhalten.|Diese Sammlung sollte genau {{ limit }} Elemente beinhalten. Invalid card number. Ungültige Kartennummer. Unsupported card type or invalid card number. Nicht unterstützer Kartentyp oder ungültige Kartennummer. This is not a valid International Bank Account Number (IBAN). Dieser Wert ist keine gültige IBAN-Kontonummer. This value is not a valid ISBN-10. Dieser Wert entspricht keiner gültigen ISBN-10. This value is not a valid ISBN-13. Dieser Wert entspricht keiner gültigen ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Dieser Wert ist weder eine gültige ISBN-10 noch eine gültige ISBN-13. This value is not a valid ISSN. Dieser Wert ist keine gültige ISSN. This value is not a valid currency. Dieser Wert ist keine gültige Währung. This value should be equal to {{ compared_value }}. Dieser Wert sollte gleich {{ compared_value }} sein. This value should be greater than {{ compared_value }}. Dieser Wert sollte größer als {{ compared_value }} sein. This value should be greater than or equal to {{ compared_value }}. Dieser Wert sollte größer oder gleich {{ compared_value }} sein. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Dieser Wert sollte identisch sein mit {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Dieser Wert sollte kleiner als {{ compared_value }} sein. This value should be less than or equal to {{ compared_value }}. Dieser Wert sollte kleiner oder gleich {{ compared_value }} sein. This value should not be equal to {{ compared_value }}. Dieser Wert sollte nicht {{ compared_value }} sein. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Dieser Wert sollte nicht identisch sein mit {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Das Seitenverhältnis des Bildes ist zu groß ({{ ratio }}). Der erlaubte Maximalwert ist {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Das Seitenverhältnis des Bildes ist zu klein ({{ ratio }}). Der erwartete Minimalwert ist {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. Das Bild ist quadratisch ({{ width }}x{{ height }}px). Quadratische Bilder sind nicht erlaubt. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. Das Bild ist im Querformat ({{ width }}x{{ height }}px). Bilder im Querformat sind nicht erlaubt. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. Das Bild ist im Hochformat ({{ width }}x{{ height }}px). Bilder im Hochformat sind nicht erlaubt. An empty file is not allowed. Eine leere Datei ist nicht erlaubt. This value does not match the expected {{ charset }} charset. Dieser Wert entspricht nicht dem erwarteten Zeichensatz {{ charset }}. This value should be false. 该变量的值应为 false 。 This value should be true. 该变量的值应为 true 。 This value should be of type {{ type }}. 该变量的类型应为 {{ type }} 。 This value should be blank. 该变量值应为空。 The value you selected is not a valid choice. 选定变量的值不是有效的选项。 You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. 您至少要选择 {{ limit }} 个选项。 You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. 您最多能选择 {{ limit }} 个选项。 One or more of the given values is invalid. 一个或者多个给定的值无效。 This field was not expected. 此字段是多余的。 This field is missing. 此字段缺失。 This value is not a valid date. 该值不是一个有效的日期(date)。 This value is not a valid datetime. 该值不是一个有效的日期时间(datetime)。 This value is not a valid email address. 该值不是一个有效的邮件地址。 The file could not be found. 文件未找到。 The file is not readable. 文件不可读。 The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. 文件太大 ({{ size }} {{ suffix }})。文件大小不可以超过 {{ limit }} {{ suffix }} 。 The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. 无效的文件类型 ({{ type }}) 。允许的文件类型有 {{ types }} 。 This value should be {{ limit }} or less. 这个变量的值应该小于或等于 {{ limit }}。 This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. 字符串太长,长度不可超过 {{ limit }} 个字符。 This value should be {{ limit }} or more. 该变量的值应该大于或等于 {{ limit }}。 This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. 字符串太短,长度不可少于 {{ limit }} 个字符。 This value should not be blank. 该变量不应为空。 This value should not be null. 该变量不应为 null 。 This value should be null. 该变量应为空 null 。 This value is not valid. 该变量值无效 。 This value is not a valid time. 该值不是一个有效的时间。 This value is not a valid URL. 该值不是一个有效的 URL 。 The two values should be equal. 这两个变量的值应该相等。 The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. 文件太大,文件大小不可以超过 {{ limit }} {{ suffix }}。 The file is too large. 文件太大。 The file could not be uploaded. 无法上传此文件。 This value should be a valid number. 该值应该为有效的数字。 This value is not a valid country. 该值不是有效的国家名。 This file is not a valid image. 该文件不是有效的图片。 This is not a valid IP address. 该值不是有效的IP地址。 This value is not a valid language. 该值不是有效的语言名。 This value is not a valid locale. 该值不是有效的区域值(locale)。 This value is already used. 该值已经被使用。 The size of the image could not be detected. 不能解析图片大小。 The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. 图片太宽 ({{ width }}px),最大宽度为 {{ max_width }}px 。 The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. 图片宽度不够 ({{ width }}px),最小宽度为 {{ min_width }}px 。 The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. 图片太高 ({{ height }}px),最大高度为 {{ max_height }}px 。 The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. 图片高度不够 ({{ height }}px),最小高度为 {{ min_height }}px 。 This value should be the user's current password. 该变量的值应为用户当前的密码。 This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. 该变量应为 {{ limit }} 个字符。 The file was only partially uploaded. 该文件的上传不完整。 No file was uploaded. 没有上传任何文件。 No temporary folder was configured in php.ini. php.ini 里没有配置临时文件目录。 Cannot write temporary file to disk. 临时文件写入磁盘失败。 A PHP extension caused the upload to fail. 某个 PHP 扩展造成上传失败。 This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. 该集合最少应包含 {{ limit }} 个元素。 This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. 该集合最多包含 {{ limit }} 个元素。 This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. 该集合应包含 {{ limit }} 个元素 element 。 Invalid card number. 无效的信用卡号。 Unsupported card type or invalid card number. 不支持的信用卡类型或无效的信用卡号。 This is not a valid International Bank Account Number (IBAN). 该值不是有效的国际银行帐号(IBAN)。 This value is not a valid ISBN-10. 该值不是有效的10位国际标准书号(ISBN-10)。 This value is not a valid ISBN-13. 该值不是有效的13位国际标准书号(ISBN-13)。 This value is neither a valid ISBN-10 nor a valid ISBN-13. 该值不是有效的国际标准书号(ISBN-10 或 ISBN-13)。 This value is not a valid ISSN. 该值不是有效的国际标准期刊号(ISSN)。 This value is not a valid currency. 该值不是有效的货币名(currency)。 This value should be equal to {{ compared_value }}. 该值应等于 {{ compared_value }} 。 This value should be greater than {{ compared_value }}. 该值应大于 {{ compared_value }} 。 This value should be greater than or equal to {{ compared_value }}. 该值应大于或等于 {{ compared_value }} 。 This value should be identical to {{ compared_value_type }} {{ compared_value }}. 该值应与 {{ compared_value_type }} {{ compared_value }} 相同。 This value should be less than {{ compared_value }}. 该值应小于 {{ compared_value }} 。 This value should be less than or equal to {{ compared_value }}. 该值应小于或等于 {{ compared_value }} 。 This value should not be equal to {{ compared_value }}. 该值不应先等于 {{ compared_value }} 。 This value should not be identical to {{ compared_value_type }} {{ compared_value }}. 该值不应与 {{ compared_value_type }} {{ compared_value }} 相同。 The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. 图片宽高比太大 ({{ ratio }})。允许的最大宽高比为 {{ max_ratio }}。 The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. 图片宽高比太小 ({{ ratio }})。允许的最大宽高比为 {{ min_ratio }}。 The image is square ({{ width }}x{{ height }}px). Square images are not allowed. 图片是方形的 ({{ width }}x{{ height }}px)。不允许使用方形的图片。 The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. 图片是横向的 ({{ width }}x{{ height }}px)。不允许使用横向的图片。 The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. 图片是纵向的 ({{ width }}x{{ height }}px)。不允许使用纵向的图片。 An empty file is not allowed. 不允许使用空文件。 The host could not be resolved. 主机名无法解析。 This value does not match the expected {{ charset }} charset. 该值不符合 {{ charset }} 编码。 This value should be false. Værdien skal være falsk. This value should be true. Værdien skal være sand. This value should be of type {{ type }}. Værdien skal være af typen {{ type }}. This value should be blank. Værdien skal være blank. The value you selected is not a valid choice. Værdien skal være en af de givne muligheder. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du skal vælge mindst {{ limit }} muligheder. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan højest vælge {{ limit }} muligheder. One or more of the given values is invalid. En eller flere af de oplyste værdier er ugyldige. This field was not expected. Feltet blev ikke forventet. This field is missing. Dette felt er mangler. This value is not a valid date. Værdien er ikke en gyldig dato. This value is not a valid datetime. Værdien er ikke en gyldig dato og tid. This value is not a valid email address. Værdien er ikke en gyldig e-mail adresse. The file could not be found. Filen kunne ikke findes. The file is not readable. Filen kan ikke læses. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor ({{ size }} {{ suffix }}). Tilladte maksimale størrelse {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mimetypen af filen er ugyldig ({{ type }}). Tilladte mimetyper er {{ types }}. This value should be {{ limit }} or less. Værdien skal være {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Værdien er for lang. Den skal have {{ limit }} bogstaver eller mindre. This value should be {{ limit }} or more. Værdien skal være {{ limit }} eller mere. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Værdien er for kort. Den skal have {{ limit }} tegn eller flere. This value should not be blank. Værdien må ikke være blank. This value should not be null. Værdien må ikke være tom (null). This value should be null. Værdien skal være tom (null). This value is not valid. Værdien er ikke gyldig. This value is not a valid time. Værdien er ikke en gyldig tid. This value is not a valid URL. Værdien er ikke en gyldig URL. The two values should be equal. De to værdier skal være ens. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}. The file is too large. Filen er for stor. The file could not be uploaded. Filen kunne ikke blive uploadet. This value should be a valid number. Værdien skal være et gyldigt tal. This file is not a valid image. Filen er ikke gyldigt billede. This is not a valid IP address. Dette er ikke en gyldig IP adresse. This value is not a valid language. Værdien er ikke et gyldigt sprog. This value is not a valid locale. Værdien er ikke en gyldig lokalitet. This value is not a valid country. Værdien er ikke et gyldigt land. This value is already used. Værdien er allerede i brug. The size of the image could not be detected. Størrelsen på billedet kunne ikke detekteres. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Billedbredden er for stor ({{ width }}px). Tilladt maksimumsbredde er {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Billedebredden er for lille ({{ width }}px). Forventet minimumshøjde er {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Billedhøjden er for stor ({{ height }}px). Tilladt maksimumshøjde er {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Billedhøjden er for lille ({{ height }}px). Forventet minimumshøjde er {{ min_height }}px. This value should be the user's current password. Værdien skal være brugerens nuværende password. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Værdien skal have præcis {{ limit }} tegn. The file was only partially uploaded. Filen var kun delvis uploadet. No file was uploaded. Ingen fil blev uploadet. No temporary folder was configured in php.ini. Ingen midlertidig mappe er konfigureret i php.ini. Cannot write temporary file to disk. Kan ikke skrive midlertidig fil til disk. A PHP extension caused the upload to fail. En PHP udvidelse forårsagede fejl i upload. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Denne samling skal indeholde {{ limit }} element eller flere.|Denne samling skal indeholde {{ limit }} elementer eller flere. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Denne samling skal indeholde {{ limit }} element eller mindre.|Denne samling skal indeholde {{ limit }} elementer eller mindre. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Denne samling skal indeholde præcis {{ limit }} element.|Denne samling skal indeholde præcis {{ limit }} elementer. Invalid card number. Ugyldigt kortnummer. Unsupported card type or invalid card number. Ikke-understøttet korttype eller ugyldigt kortnummer. This is not a valid International Bank Account Number (IBAN). Det er ikke en gyldig International Bank Account Number (IBAN). This value is not a valid ISBN-10. Værdien er ikke en gyldig ISBN-10. This value is not a valid ISBN-13. Værdien er ikke en gyldig ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Værdien er hverken en gyldig ISBN-10 eller en gyldig ISBN-13. This value is not a valid ISSN. Værdien er ikke en gyldig ISSN. This value should be false. Dëse Wäert sollt falsch sinn. This value should be true. Dëse Wäert sollt wouer sinn. This value should be of type {{ type }}. Dëse Wäert sollt vum Typ {{ type }} sinn. This value should be blank. Dëse Wäert sollt eidel sinn. The value you selected is not a valid choice. Dëse Wäert sollt enger vun de Wielméiglechkeeten entspriechen. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Dir sollt mindestens {{ limit }} Méiglechkeete wielen. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Dir sollt héchstens {{ limit }} Méiglechkeete wielen. One or more of the given values is invalid. Een oder méi vun de Wäerter ass ongëlteg. The fields {{ fields }} were not expected. D'Felder {{ fields }} goufen net erwaart. The fields {{ fields }} are missing. D'Felder {{ fields }} feelen. This value is not a valid date. Dëse Wäert entsprécht kenger gëlteger Datumsangab. This value is not a valid datetime. Dëse Wäert entsprécht kenger gëlteger Datums- an Zäitangab. This value is not a valid email address. Dëse Wäert ass keng gëlteg Email-Adress. The file could not be found. De Fichier gouf net fonnt. The file is not readable. De Fichier ass net liesbar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. De Fichier ass ze grouss ({{ size }} {{ suffix }}). Déi zougeloosse Maximalgréisst bedréit {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Den Typ vum Fichier ass ongëlteg ({{ type }}). Erlaabten Type sinn {{ types }}. This value should be {{ limit }} or less. Dëse Wäert soll méi kleng oder gläich {{ limit }} sinn. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Dës Zeecheketten ass ze laang. Se sollt héchstens {{ limit }} Zeechen hunn. This value should be {{ limit }} or more. Dëse Wäert sollt méi grouss oder gläich {{ limit }} sinn. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Dës Zeecheketten ass ze kuerz. Se sollt mindestens {{ limit }} Zeechen hunn. This value should not be blank. Dëse Wäert sollt net eidel sinn. This value should not be null. Dëst sollt keen Null-Wäert sinn. This value should be null. Dëst sollt keen Null-Wäert sinn. This value is not valid. Dëse Wäert ass net gëlteg. This value is not a valid time. Dëse Wäert entsprécht kenger gëlteger Zäitangab. This value is not a valid URL. Dëse Wäert ass keng gëlteg URL. The two values should be equal. Béid Wäerter sollten identesch sinn. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. De fichier ass ze grouss. Déi maximal Gréisst dierf {{ limit }} {{ suffix }} net depasséieren. The file is too large. De Fichier ass ze grouss. The file could not be uploaded. De Fichier konnt net eropgeluede ginn. This value should be a valid number. Dëse Wäert sollt eng gëlteg Zuel sinn. This file is not a valid image. Dëse Fichier ass kee gëltegt Bild. This is not a valid IP address. Dëst ass keng gëlteg IP-Adress. This value is not a valid language. Dëse Wäert aentsprécht kenger gëlteger Sprooch. This value is not a valid locale. Dëse Wäert entsprécht kengem gëltege Gebittsschema. This value is not a valid country. Dëse Wäert entsprécht kengem gëltege Land. This value is already used. Dëse Wäert gëtt scho benotzt. The size of the image could not be detected. D'Gréisst vum Bild konnt net detektéiert ginn. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. D'Breet vum Bild ass ze grouss ({{ width }}px). Déi erlaabte maximal Breet ass {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. D'Breet vum Bild ass ze kleng ({{ width }}px). Déi minimal Breet ass {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. D'Héicht vum Bild ass ze grouss ({{ height }}px). Déi erlaabte maximal Héicht ass {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. D'Héicht vum Bild ass ze kleng ({{ height }}px). Déi minimal Héicht ass {{ min_height }}px. This value should be the user's current password. Dëse Wäert sollt dem aktuelle Benotzerpasswuert entspriechen. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Dëse Wäert sollt exactly {{ limit }} Buschtaf hunn.|Dëse Wäert sollt exakt {{ limit }} Buschtawen hunn. The file was only partially uploaded. De Fichier gouf just deelweis eropgelueden. No file was uploaded. Et gouf kee Fichier eropgelueden. No temporary folder was configured in php.ini. Et gouf keen temporären Dossier an der php.ini konfiguréiert. Cannot write temporary file to disk. Den temporäre Fichier kann net gespäichert ginn. A PHP extension caused the upload to fail. Eng PHP-Erweiderung huet den Upload verhënnert. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Dës Sammlung sollt {{ limit }} oder méi Elementer hunn. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Dës Sammlung sollt {{ limit }} oder manner Elementer hunn. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Dës Sammlung sollt exakt {{ limit }} Element hunn.|Dës Sammlung sollt exakt {{ limit }} Elementer hunn. Invalid card number. Ongëlteg Kaartennummer. Unsupported card type or invalid card number. Net ënnerstëtzte Kaartentyp oder ongëlteg Kaartennummer. This is not a valid International Bank Account Number (IBAN). Dëst ass keng gëlteg IBAN-Kontonummer. This value is not a valid ISBN-10. Dëse Wäert ass keng gëlteg ISBN-10. This value is not a valid ISBN-13. Dëse Wäert ass keng gëlteg ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Dëse Wäert ass weder eng gëlteg ISBN-10 nach eng gëlteg ISBN-13. This value is not a valid ISSN. Dëse Wäert ass keng gëlteg ISSN. This value is not a valid currency. Dëse Wäert ass keng gëlteg Währung. This value should be equal to {{ compared_value }}. Dëse Wäert sollt {{ compared_value }} sinn. This value should be greater than {{ compared_value }}. Dëse Wäert sollt méi grouss wéi {{ compared_value }} sinn. This value should be greater than or equal to {{ compared_value }}. Dëse Wäert sollt méi grouss wéi oder gläich {{ compared_value }} sinn. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Dëse Wäert sollt identesch si mat {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Dëse Wäert sollt méi kleng wéi {{ compared_value }} sinn. This value should be less than or equal to {{ compared_value }}. Dëse Wäert sollt méi kleng wéi oder gläich {{ compared_value }} sinn. This value should not be equal to {{ compared_value }}. Dëse Wäert sollt net {{ compared_value }} sinn. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Dëse Wäert sollt net identesch si mat {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. D'Säiteverhältnis vum Bild ass ze grouss ({{ ratio }}). Den erlaabte Maximalwäert ass {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. D'Säiteverhältnis vum Bild ass ze kleng ({{ ratio }}). Den erwaarte Minimalwäert ass {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. D'Bild ass quadratesch ({{ width }}x{{ height }}px). Quadratesch Biller sinn net erlaabt. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. D'Bild ass am Queeschformat ({{ width }}x{{ height }}px). Biller am Queeschformat sinn net erlaabt. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. D'Bild ass am Héichformat ({{ width }}x{{ height }}px). Biller am Héichformat sinn net erlaabt. This value should be false. Verdien skulle ha vore tom/nei. This value should be true. Verdien skulla ha vore satt/ja. This value should be of type {{ type }}. Verdien må vere av typen {{ type }}. This value should be blank. Verdien skal vere blank. The value you selected is not a valid choice. Verdien du valgte er ikkje gyldig. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du må velge minst {{ limit }} valg. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan maksimalt gjere {{ limit }} valg. One or more of the given values is invalid. Ein eller fleire av dei opplyste verdiane er ugyldige. This field was not expected. Dette feltet var ikke forventet. This field is missing. Dette feltet mangler. This value is not a valid date. Verdien er ikkje ein gyldig dato. This value is not a valid datetime. Verdien er ikkje ein gyldig dato og tid. This value is not a valid email address. Verdien er ikkje ei gyldig e-postadresse. The file could not be found. Fila kunne ikkje finnes. The file is not readable. Fila kan ikkje lesast. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fila er for stor ({{ size }} {{ suffix }}). Tillatt maksimal størrelse er {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime-typen av fila er ugyldig ({{ type }}). Tillatte mime-typar er {{ types }}. This value should be {{ limit }} or less. Verdien må vere {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Verdien er for lang. Den må vere {{ limit }} bokstavar eller mindre. This value should be {{ limit }} or more. Verdien må vere {{ limit }} eller meir. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Verdien er for kort. Den må ha {{ limit }} teikn eller fleire. This value should not be blank. Verdien må ikkje vere blank. This value should not be null. Verdien må ikkje vere tom (null). This value should be null. Verdien må vere tom (null). This value is not valid. Verdien er ikkje gyldig. This value is not a valid time. Verdien er ikkje gyldig tidseining. This value is not a valid URL. Verdien er ikkje ein gyldig URL. The two values should be equal. Dei to verdiane må vere like. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fila er for stor. Den maksimale storleik er {{ limit }} {{ suffix }}. The file is too large. Fila er for stor. The file could not be uploaded. Fila kunne ikkje bli lasta opp. This value should be a valid number. Verdien må vere eit gyldig tal. This file is not a valid image. Fila er ikkje eit gyldig bilete. This is not a valid IP address. Dette er ikkje ei gyldig IP-adresse. This value is not a valid language. Verdien er ikkje eit gyldig språk. This value is not a valid locale. Verdien er ikkje ein gyldig lokalitet (språk/region). This value is not a valid country. Verdien er ikkje eit gyldig land. This value is already used. Verdien er allereie i bruk. The size of the image could not be detected. Storleiken på biletet kunne ikkje oppdagast. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Biletbreidda er for stor, ({{ width }} pikslar). Tillatt maksimumsbreidde er {{ max_width }} pikslar. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Biletbreidda er for liten, ({{ width }} pikslar). Forventa minimumsbreidde er {{ min_width }} pikslar. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Bilethøgda er for stor, ({{ height }} pikslar). Tillatt maksimumshøgde er {{ max_height }} pikslar. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Billethøgda er for låg, ({{ height }} pikslar). Forventa minimumshøgde er {{ min_height }} pikslar. This value should be the user's current password. Verdien må vere brukaren sitt noverande passord. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Verdien må vere nøyaktig {{ limit }} teikn. The file was only partially uploaded. Fila vart kun delvis opplasta. No file was uploaded. Inga fil vart lasta opp. No temporary folder was configured in php.ini. Førebels mappe (tmp) er ikkje konfigurert i php.ini. Cannot write temporary file to disk. Kan ikkje skrive førebels fil til disk. A PHP extension caused the upload to fail. Ei PHP-udviding forårsaka feil under opplasting. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Denne samlinga må innehalde {{ limit }} element eller meir.|Denne samlinga må innehalde {{ limit }} element eller meir. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Denne samlinga må innehalde {{ limit }} element eller færre.|Denne samlinga må innehalde {{ limit }} element eller færre. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Denne samlinga må innehalde nøyaktig {{ limit }} element.|Denne samlinga må innehalde nøyaktig {{ limit }} element. Invalid card number. Ugyldig kortnummer. Unsupported card type or invalid card number. Korttypen er ikkje støtta eller ugyldig kortnummer. This value should be false. falseでなければなりません。 This value should be true. trueでなければなりません。 This value should be of type {{ type }}. 型は{{ type }}でなければなりません。 This value should be blank. 空でなければなりません。 The value you selected is not a valid choice. 有効な選択肢ではありません。 You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. {{ limit }}個以上選択してください。 You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. {{ limit }}個以内で選択してください。 One or more of the given values is invalid. 無効な選択肢が含まれています。 This field was not expected. このフィールドは予期されていませんでした。 This field is missing. このフィールドは、欠落しています。 This value is not a valid date. 有効な日付ではありません。 This value is not a valid datetime. 有効な日時ではありません。 This value is not a valid email address. 有効なメールアドレスではありません。 The file could not be found. ファイルが見つかりません。 The file is not readable. ファイルを読み込めません。 The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. ファイルのサイズが大きすぎます({{ size }} {{ suffix }})。有効な最大サイズは{{ limit }} {{ suffix }}です。 The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. ファイルのMIMEタイプが無効です({{ type }})。有効なMIMEタイプは{{ types }}です。 This value should be {{ limit }} or less. {{ limit }}以下でなければなりません。 This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. 値が長すぎます。{{ limit }}文字以内でなければなりません。 This value should be {{ limit }} or more. {{ limit }}以上でなければなりません。 This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. 値が短すぎます。{{ limit }}文字以上でなければなりません。 This value should not be blank. 空であってはなりません。 This value should not be null. nullであってはなりません。 This value should be null. nullでなければなりません。 This value is not valid. 有効な値ではありません。 This value is not a valid time. 有効な時刻ではありません。 This value is not a valid URL. 有効なURLではありません。 The two values should be equal. 2つの値が同じでなければなりません。 The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. ファイルのサイズが大きすぎます。有効な最大サイズは{{ limit }} {{ suffix }}です。 The file is too large. ファイルのサイズが大きすぎます。 The file could not be uploaded. ファイルをアップロードできませんでした。 This value should be a valid number. 有効な数字ではありません。 This file is not a valid image. ファイルが画像ではありません。 This is not a valid IP address. 有効なIPアドレスではありません。 This value is not a valid language. 有効な言語名ではありません。 This value is not a valid locale. 有効なロケールではありません。 This value is not a valid country. 有効な国名ではありません。 This value is already used. 既に使用されています。 The size of the image could not be detected. 画像のサイズが検出できません。 The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. 画像の幅が大きすぎます({{ width }}ピクセル)。{{ max_width }}ピクセルまでにしてください。 The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. 画像の幅が小さすぎます({{ width }}ピクセル)。{{ min_width }}ピクセル以上にしてください。 The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. 画像の高さが大きすぎます({{ height }}ピクセル)。{{ max_height }}ピクセルまでにしてください。 The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. 画像の高さが小さすぎます({{ height }}ピクセル)。{{ min_height }}ピクセル以上にしてください。 This value should be the user current password. ユーザーの現在のパスワードでなければなりません。 This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. ちょうど{{ limit }}文字でなければなりません。 The file was only partially uploaded. ファイルのアップロードは完全ではありません。 No file was uploaded. ファイルがアップロードされていません。 No temporary folder was configured in php.ini. php.iniで一時フォルダが設定されていません。 Cannot write temporary file to disk. 一時ファイルをディスクに書き込むことができません。 A PHP extension caused the upload to fail. PHP拡張によってアップロードに失敗しました。 This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. {{ limit }}個以上の要素を含んでなければいけません。 This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. 要素は{{ limit }}個までです。 This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. 要素はちょうど{{ limit }}個でなければなりません。 Invalid card number. 無効なカード番号です。 Unsupported card type or invalid card number. 未対応のカード種類又は無効なカード番号です。 This is not a valid International Bank Account Number (IBAN). 有効なIBANコードではありません。 This value is not a valid ISBN-10. 有効なISBN-10コードではありません。 This value is not a valid ISBN-13. 有効なISBN-13コードではありません。 This value is neither a valid ISBN-10 nor a valid ISBN-13. 有効なISBN-10コード又はISBN-13コードではありません。 This value is not a valid ISSN. 有効なISSNコードではありません。 This value is not a valid currency. 有効な貨幣ではありません。 This value should be equal to {{ compared_value }}. {{ compared_value }}と等しくなければなりません。 This value should be greater than {{ compared_value }}. {{ compared_value }}より大きくなければなりません。 This value should be greater than or equal to {{ compared_value }}. {{ compared_value }}以上でなければなりません。 This value should be identical to {{ compared_value_type }} {{ compared_value }}. {{ compared_value_type }}としての{{ compared_value }}と等しくなければなりません。 This value should be less than {{ compared_value }}. {{ compared_value }}未満でなければなりません。 This value should be less than or equal to {{ compared_value }}. {{ compared_value }}以下でなければなりません。 This value should not be equal to {{ compared_value }}. {{ compared_value }}と等しくてはいけません。 This value should not be identical to {{ compared_value_type }} {{ compared_value }}. {{ compared_value_type }}としての{{ compared_value }}と等しくてはいけません。 The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. 画像のアスペクト比が大きすぎます({{ ratio }})。{{ max_ratio }}までにしてください。 The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. 画像のアスペクト比が小さすぎます({{ ratio }})。{{ min_ratio }}以上にしてください。 The image is square ({{ width }}x{{ height }}px). Square images are not allowed. 画像が正方形になっています({{ width }}x{{ height }}ピクセル)。正方形の画像は許可されていません。 The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. 画像が横向きになっています({{ width }}x{{ height }}ピクセル)。横向きの画像は許可されていません。 The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. 画像が縦向きになっています({{ width }}x{{ height }}ピクセル)。縦向きの画像は許可されていません。 An empty file is not allowed. 空のファイルは許可されていません。 The host could not be resolved. ホストを解決できませんでした。 This value does not match the expected {{ charset }} charset. この値は予期される文字コード({{ charset }})と異なります。 This value should be false. Táto hodnota by mala byť nastavená na false. This value should be true. Táto hodnota by mala byť nastavená na true. This value should be of type {{ type }}. Táto hodnota by mala byť typu {{ type }}. This value should be blank. Táto hodnota by mala byť prázdna. The value you selected is not a valid choice. Táto hodnota by mala byť jednou z poskytnutých možností. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Mali by ste vybrať minimálne {{ limit }} možnosť.|Mali by ste vybrať minimálne {{ limit }} možnosti.|Mali by ste vybrať minimálne {{ limit }} možností. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Mali by ste vybrať najviac {{ limit }} možnosť.|Mali by ste vybrať najviac {{ limit }} možnosti.|Mali by ste vybrať najviac {{ limit }} možností. One or more of the given values is invalid. Niektoré z uvedených hodnôt sú neplatné. This field was not expected. Toto pole sa neočakáva. This field is missing. Toto pole chýba. This value is not a valid date. Tato hodnota nemá platný formát dátumu. This value is not a valid datetime. Táto hodnota nemá platný formát dátumu a času. This value is not a valid email address. Táto hodnota nie je platná emailová adresa. The file could not be found. Súbor sa nenašiel. The file is not readable. Súbor nie je čitateľný. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Súbor je príliš veľký ({{ size }} {{ suffix }}). Maximálna povolená veľkosť je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Súbor typu ({{ type }}) nie je podporovaný. Podporované typy sú {{ types }}. This value should be {{ limit }} or less. Táto hodnota by mala byť {{ limit }} alebo menej. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znak.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znaky.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znakov. This value should be {{ limit }} or more. Táto hodnota by mala byť viac ako {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znak.|Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znaky.|Táto hodnota je príliš krátka. Minimálny počet znakov je {{ limit }}. This value should not be blank. Táto hodnota by mala byť vyplnená. This value should not be null. Táto hodnota by nemala byť null. This value should be null. Táto hodnota by mala byť null. This value is not valid. Táto hodnota nie je platná. This value is not a valid time. Tato hodnota nemá správny formát času. This value is not a valid URL. Táto hodnota nie je platnou URL adresou. The two values should be equal. Tieto dve hodnoty by mali byť rovnaké. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Súbor je príliš veľký. Maximálna povolená veľkosť je {{ limit }} {{ suffix }}. The file is too large. Súbor je príliš veľký. The file could not be uploaded. Súbor sa nepodarilo nahrať. This value should be a valid number. Táto hodnota by mala byť číslo. This file is not a valid image. Tento súbor nie je obrázok. This is not a valid IP address. Toto nie je platná IP adresa. This value is not a valid language. Tento jazyk neexistuje. This value is not a valid locale. Táto lokalizácia neexistuje. This value is not a valid country. Táto krajina neexistuje. This value is already used. Táto hodnota sa už používa. The size of the image could not be detected. Nepodarilo sa zistiť rozmery obrázku. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Obrázok je príliš široký ({{ width }}px). Maximálna povolená šírka obrázku je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Obrázok je príliš úzky ({{ width }}px). Minimálna šírka obrázku by mala byť {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. >Obrázok je príliš vysoký ({{ height }}px). Maximálna povolená výška obrázku je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Obrázok je príliš nízky ({{ height }}px). Minimálna výška obrázku by mala byť {{ min_height }}px. This value should be the user's current password. Táto hodnota by mala byť aktuálne heslo používateľa. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Táto hodnota by mala mať presne {{ limit }} znak.|Táto hodnota by mala mať presne {{ limit }} znaky.|Táto hodnota by mala mať presne {{ limit }} znakov. The file was only partially uploaded. Bola nahraná len časť súboru. No file was uploaded. Žiadny súbor nebol nahraný. No temporary folder was configured in php.ini. V php.ini nie je nastavená cesta k adresáru pre dočasné súbory. Cannot write temporary file to disk. Dočasný súbor sa nepodarilo zapísať na disk. A PHP extension caused the upload to fail. Rozšírenie PHP zabránilo nahraniu súboru. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Táto kolekcia by mala obsahovať aspoň {{ limit }} prvok alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvky alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvkov alebo viac. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Táto kolekcia by mala maximálne {{ limit }} prvok.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvky.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvkov. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Táto kolekcia by mala obsahovať presne {{ limit }} prvok.|Táto kolekcia by mala obsahovať presne {{ limit }} prvky.|Táto kolekcia by mala obsahovať presne {{ limit }} prvkov. Invalid card number. Neplatné číslo karty. Unsupported card type or invalid card number. Nepodporovaný typ karty alebo neplatné číslo karty. This is not a valid International Bank Account Number (IBAN). Toto je neplatný IBAN. This value is not a valid ISBN-10. Táto hodnota je neplatné ISBN-10. This value is not a valid ISBN-13. Táto hodnota je neplatné ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Táto hodnota nie je platné ISBN-10 ani ISBN-13. This value is not a valid ISSN. Táto hodnota nie je platné ISSN. This value is not a valid currency. Táto hodnota nie je platná mena. This value should be equal to {{ compared_value }}. Táto hodnota by mala byť rovná {{ compared_value }}. This value should be greater than {{ compared_value }}. Táto hodnota by mala byť väčšia ako {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Táto hodnota by mala byť väčšia alebo rovná {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Táto hodnota by mala byť typu {{ compared_value_type }} a zároveň by mala byť rovná {{ compared_value }}. This value should be less than {{ compared_value }}. Táto hodnota by mala byť menšia ako {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Táto hodnota by mala byť menšia alebo rovná {{ compared_value }}. This value should not be equal to {{ compared_value }}. Táto hodnota by nemala byť rovná {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Táto hodnota by nemala byť typu {{ compared_value_type }} a zároveň by nemala byť rovná {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Pomer strán obrázku je príliš veľký ({{ ratio }}). Maximálny povolený pomer strán obrázku je {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Pomer strán obrázku je príliš malý ({{ ratio }}). Minimálny povolený pomer strán obrázku je {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. Strany obrázku sú štvorcové ({{ width }}x{{ height }}px). Štvorcové obrázky nie sú povolené. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. Obrázok je orientovaný na šírku ({{ width }}x{{ height }}px). Obrázky orientované na šírku nie sú povolené. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. Obrázok je orientovaný na výšku ({{ width }}x{{ height }}px). Obrázky orientované na výšku nie sú povolené. An empty file is not allowed. Súbor nesmie byť prázdny. This value should be false. Este valor debería ser falso. This value should be true. Este valor debería ser verdadero. This value should be of type {{ type }}. Este valor debería ser de tipo {{ type }}. This value should be blank. Este valor debería estar vacío. The value you selected is not a valid choice. El valor seleccionado no es una opción válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Debe seleccionar al menos {{ limit }} opción.|Debe seleccionar al menos {{ limit }} opciones. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opciones. One or more of the given values is invalid. Uno o más de los valores indicados no son válidos. This field was not expected. Este campo no se esperaba. This field is missing. Este campo está desaparecido. This value is not a valid date. Este valor no es una fecha válida. This value is not a valid datetime. Este valor no es una fecha y hora válidas. This value is not a valid email address. Este valor no es una dirección de email válida. The file could not be found. No se pudo encontrar el archivo. The file is not readable. No se puede leer el archivo. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. El archivo es demasiado grande ({{ size }} {{ suffix }}). El tamaño máximo permitido es {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. El tipo mime del archivo no es válido ({{ type }}). Los tipos mime válidos son {{ types }}. This value should be {{ limit }} or less. Este valor debería ser {{ limit }} o menos. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Este valor es demasiado largo. Debería tener {{ limit }} carácter o menos.|Este valor es demasiado largo. Debería tener {{ limit }} caracteres o menos. This value should be {{ limit }} or more. Este valor debería ser {{ limit }} o más. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Este valor es demasiado corto. Debería tener {{ limit }} carácter o más.|Este valor es demasiado corto. Debería tener {{ limit }} caracteres o más. This value should not be blank. Este valor no debería estar vacío. This value should not be null. Este valor no debería ser nulo. This value should be null. Este valor debería ser nulo. This value is not valid. Este valor no es válido. This value is not a valid time. Este valor no es una hora válida. This value is not a valid URL. Este valor no es una URL válida. The two values should be equal. Los dos valores deberían ser iguales. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. El archivo es demasiado grande. El tamaño máximo permitido es {{ limit }} {{ suffix }}. The file is too large. El archivo es demasiado grande. The file could not be uploaded. No se pudo subir el archivo. This value should be a valid number. Este valor debería ser un número válido. This file is not a valid image. El archivo no es una imagen válida. This is not a valid IP address. Esto no es una dirección IP válida. This value is not a valid language. Este valor no es un idioma válido. This value is not a valid locale. Este valor no es una localización válida. This value is not a valid country. Este valor no es un país válido. This value is already used. Este valor ya se ha utilizado. The size of the image could not be detected. No se pudo determinar el tamaño de la imagen. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. El ancho de la imagen es demasiado grande ({{ width }}px). El ancho máximo permitido es de {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. El ancho de la imagen es demasiado pequeño ({{ width }}px). El ancho mínimo requerido es {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. La altura de la imagen es demasiado grande ({{ height }}px). La altura máxima permitida es de {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. La altura de la imagen es demasiado pequeña ({{ height }}px). La altura mínima requerida es de {{ min_height }}px. This value should be the user's current password. Este valor debería ser la contraseña actual del usuario. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor debería tener exactamente {{ limit }} carácter.|Este valor debería tener exactamente {{ limit }} caracteres. The file was only partially uploaded. El archivo fue sólo subido parcialmente. No file was uploaded. Ningún archivo fue subido. No temporary folder was configured in php.ini. Ninguna carpeta temporal fue configurada en php.ini. Cannot write temporary file to disk. No se pudo escribir el archivo temporal en el disco. A PHP extension caused the upload to fail. Una extensión de PHP hizo que la subida fallara. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta colección debe contener {{ limit }} elemento o más.|Esta colección debe contener {{ limit }} elementos o más. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta colección debe contener {{ limit }} elemento o menos.|Esta colección debe contener {{ limit }} elementos o menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta colección debe contener exactamente {{ limit }} elemento.|Esta colección debe contener exactamente {{ limit }} elementos. Invalid card number. Número de tarjeta inválido. Unsupported card type or invalid card number. Tipo de tarjeta no soportado o número de tarjeta inválido. This is not a valid International Bank Account Number (IBAN). Esto no es un International Bank Account Number (IBAN) válido. This value is not a valid ISBN-10. Este valor no es un ISBN-10 válido. This value is not a valid ISBN-13. Este valor no es un ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor no es ni un ISBN-10 válido ni un ISBN-13 válido. This value is not a valid ISSN. Este valor no es un ISSN válido. This value is not a valid currency. Este valor no es una divisa válida. This value should be equal to {{ compared_value }}. Este valor debería ser igual que {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor debería ser mayor que {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor debería ser mayor o igual que {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor debería ser idéntico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor debería ser menor que {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor debería ser menor o igual que {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor debería ser distinto de {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor no debería ser idéntico a {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. La proporción de la imagen es demasiado grande ({{ ratio }}). La máxima proporción permitida es {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. La proporción de la imagen es demasiado pequeña ({{ ratio }}). La mínima proporción permitida es {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. La imagen es cuadrada ({{ width }}x{{ height }}px). Las imágenes cuadradas no están permitidas. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. La imagen está orientada horizontalmente ({{ width }}x{{ height }}px). Las imágenes orientadas horizontalmente no están permitidas. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. La imagen está orientada verticalmente ({{ width }}x{{ height }}px). Las imágenes orientadas verticalmente no están permitidas. An empty file is not allowed. No está permitido un archivo vacío. This value does not match the expected {{ charset }} charset. La codificación de caracteres para este valor debería ser {{ charset }}. This value should be false. Kjo vlerë duhet të jetë e pavërtetë (false). This value should be true. Kjo vlerë duhet të jetë e vërtetë (true). This value should be of type {{ type }}. Kjo vlerë duhet të jetë e llojit {{ type }}. This value should be blank. Kjo vlerë duhet të jetë e zbrazët. The value you selected is not a valid choice. Vlera që keni zgjedhur nuk është alternativë e vlefshme. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Duhet të zgjedhni së paku {{ limit }} alternativa.|Duhet të zgjedhni së paku {{ limit }} alternativa. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Duhet të zgjedhni më së shumti {{ limit }} alternativa.|Duhet të zgjedhni më së shumti {{ limit }} alternativa. One or more of the given values is invalid. Një apo më shumë nga vlerat e dhëna nuk janë të sakta. This field was not expected. Kjo fushë nuk pritej. This field is missing. Kjo fushë është zhdukur. This value is not a valid date. Kjo vlerë nuk është datë e vlefshme. This value is not a valid datetime. Kjo vlerë nuk është datë-kohë e vlefshme. This value is not a valid email address. Kjo vlerë nuk është e-mail adresë e vlefshme. The file could not be found. File nuk mund të gjindej. The file is not readable. File nuk është i lexueshëm. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. File është shumë i madh ({{ size }} {{ suffix }}). Madhësia më e madhe e lejuar është {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Lloji mime i files nuk është i vlefshëm ({{ type }}). Llojet mime të lejuara janë {{ types }}. This value should be {{ limit }} or less. Kjo vlerë duhet të jetë {{ limit }} ose më pak. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere.|Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere. This value should be {{ limit }} or more. Kjo vlerë duhet të jetë {{ limit }} ose më shumë. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere.|Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere. This value should not be blank. Kjo vlerë nuk duhet të jetë e zbrazët. This value should not be null. Kjo vlerë nuk duhet të jetë null. This value should be null. Kjo vlerë duhet të jetë null. This value is not valid. Kjo vlerë nuk është e vlefshme. This value is not a valid time. Kjo vlerë nuk është kohë e vlefshme. This value is not a valid URL. Kjo vlerë nuk është URL e vlefshme. The two values should be equal. Këto dy vlera duhet të jenë të barabarta. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ky file është shumë i madh. Madhësia maksimale e lejuar është {{ limit }} {{ suffix }}. The file is too large. Ky file është shumë i madh. The file could not be uploaded. Ky file nuk mund të ngarkohet. This value should be a valid number. Kjo vlerë duhet të jetë numër i vlefshëm. This file is not a valid image. Ky file nuk është imazh i vlefshëm. This is not a valid IP address. Kjo vlerë nuk është IP adresë e vlefshme. This value is not a valid language. Kjo vlerë nuk është gjuhë e vlefshme. This value is not a valid locale. Kjo vlerë nuk është përcaktim rajonal i vlefshëm. This value is not a valid country. Kjo vlerë nuk është shtet i vlefshëm. This value is already used. Kjo vlerë është tashmë në përdorim. The size of the image could not be detected. Madhësia e këtij imazhi nuk mund të zbulohet. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Gjerësia e imazhit është shumë e madhe ({{ width }}px). Gjerësia maksimale e lejuar është {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Gjerësia e imazhit është shumë e vogël ({{ width }}px). Gjerësia minimale e pritur është {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Gjatësia e imazhit është shumë e madhe ({{ height }}px). Gjatësia maksimale e lejuar është {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Gjatësia e imazhit është shumë e vogël ({{ height }}px). Gjatësia minimale e pritur është {{ min_height }}px. This value should be the user's current password. Kjo vlerë duhet të jetë fjalëkalimi aktual i përdoruesit. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere.|Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere. The file was only partially uploaded. Ky file është ngarkuar pjesërisht. No file was uploaded. Nuk është ngarkuar ndonjë file. No temporary folder was configured in php.ini. Asnjë folder i përkohshëm nuk është konfiguruar në php.ini. Cannot write temporary file to disk. Nuk mund të shkruhet file i përkohshëm në disk. A PHP extension caused the upload to fail. Një ekstenzion i PHP-së bëri të dështojë ngarkimi i files. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente.|Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente. Invalid card number. Numër kartele i pavlefshëm. Unsupported card type or invalid card number. Lloj kartele i pambështetur ose numër kartele i pavlefshëm. This value should be false. Giá trị này phải là sai. This value should be true. Giá trị này phải là đúng. This value should be of type {{ type }}. Giá trị này phải là kiểu {{ type }}. This value should be blank. Giá trị này phải rỗng. The value you selected is not a valid choice. Giá trị bạn vừa chọn không hợp lệ. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Bạn phải chọn ít nhất {{ limit }} lựa chọn.|Bạn phải chọn ít nhất {{ limit }} lựa chọn. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Bạn phải chọn nhiều nhất {{ limit }} lựa chọn.|Bạn phải chọn nhiều nhất {{ limit }} lựa chọn. One or more of the given values is invalid. Một hoặc nhiều giá trị được chọn không hợp lệ. This field was not expected. Lĩnh vực này không được dự kiến. This field is missing. Lĩnh vực này là mất tích. This value is not a valid date. Giá trị không phải là ngày hợp lệ. This value is not a valid datetime. Giá trị không phải là ngày tháng hợp lệ. This value is not a valid email address. Giá trị này không phải là email hợp lệ. The file could not be found. Tập tin không tìm thấy. The file is not readable. Tập tin không thể đọc được. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Tập tin quá lớn ({{ size }} {{ suffix }}). Kích thước tối đa cho phép {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Kiểu mime của tập tin không hợp lệ ({{ type }}). Kiểu hợp lệ là {{ types }}. This value should be {{ limit }} or less. Giá trị phải bằng hoặc nhỏ hơn {{ limit }}. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Giá trị quá dài. Phải bằng hoặc ít hơn {{ limit }} kí tự.|Giá trị quá dài. Phải bằng hoặc ít hơn {{ limit }} kí tự. This value should be {{ limit }} or more. Giá trị phải lớn hơn hoặc bằng {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Giá trị quá ngắn. Phải hơn hoặc bằng {{ limit }} kí tự.|Giá trị quá ngắn. Phải hơn hoặc bằng {{ limit }} kí tự. This value should not be blank. Giá trị không được phép để trống. This value should not be null. Giá trị không được phép rỗng. This value should be null. Giá trị phải rỗng. This value is not valid. Giá trị không hợp lệ. This value is not a valid time. Giá trị không phải là thời gian hợp lệ. This value is not a valid URL. Giá trị không phải là địa chỉ URL hợp lệ. The two values should be equal. Hai giá trị phải bằng nhau. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Tập tin quá lớn. Kích thước tối đa cho phép là {{ limit }} {{ suffix }}. The file is too large. Tập tin quá lớn. The file could not be uploaded. Tập tin không thể tải lên. This value should be a valid number. Giá trị phải là con số. This file is not a valid image. Tập tin không phải là hình ảnh. This is not a valid IP address. Địa chỉ IP không hợp lệ. This value is not a valid language. Giá trị không phải là ngôn ngữ hợp lệ. This value is not a valid locale. Giá trị không phải là một bản địa địa phương hợp lệ. This value is not a valid country. Giá trị không phải là nước hợp lệ. This value is already used. Giá trị đã được sử dụng. The size of the image could not be detected. Kích thước của hình ảnh không thể xác định. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Chiều rộng của hình quá lớn ({{ width }}px). Chiều rộng tối đa phải là {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Chiều rộng của hình quá thấp ({{ width }}px). Chiều rộng tối thiểu phải là {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Chiều cao của hình quá cao ({{ height }}px). Chiều cao tối đa phải là {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Chiều cao của hình quá thấp ({{ height }}px). Chiều cao tối thiểu phải là {{ min_height }}px. This value should be the user's current password. Giá trị này phải là mật khẩu hiện tại của người dùng. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Giá trị phải có chính xác {{ limit }} kí tự.|Giá trị phải có chính xác {{ limit }} kí tự. The file was only partially uploaded. Tập tin chỉ được tải lên một phần. No file was uploaded. Tập tin không được tải lên. No temporary folder was configured in php.ini. Thư mục tạm không được định nghĩa trong php.ini. Cannot write temporary file to disk. Không thể ghi tập tin tạm ra đĩa. A PHP extension caused the upload to fail. Một PHP extension đã phá hỏng quá trình tải lên của tập tin. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Danh sách phải chứa chính xác {{ limit }} thành phần.|Danh sách phải chứa chính xác {{ limit }} thành phần. Invalid card number. Số thẻ không hợp lệ. Unsupported card type or invalid card number. Thẻ không được hỗ trợ hoặc số thẻ không hợp lệ. This is not a valid International Bank Account Number (IBAN). Giá trị không phải là International Bank Account Number (IBAN) hợp lệ. This value is not a valid ISBN-10. Giá trị không phải là ISBN-10 hợp lệ. This value is not a valid ISBN-13. Giá trị không phải là ISBN-13 hợp lệ. This value is neither a valid ISBN-10 nor a valid ISBN-13. Giá trị không phải là ISBN-10 hoặc ISBN-13 hợp lệ. This value is not a valid ISSN. Giá trị không là ISSN hợp lệ. This value is not a valid currency. Giá trị không phải là đơn vi tiền tệ hợp lệ. This value should be equal to {{ compared_value }}. Giá trị phải bằng {{ compared_value }}. This value should be greater than {{ compared_value }}. Giá trị phải lớn hơn {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Giá trị phải lớn hơn hoặc bằng {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Giá trị phải giống {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Giá trị phải bé hơn {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Giá trị không được phép nhỏ hơn hoặc bằng {{ compared_value }}. This value should not be equal to {{ compared_value }}. Giá trị không được phép bằng {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Giá trị không được phép giống như {{ compared_value_type }} {{ compared_value }}. This value should be false. 該變數的值應為 false 。 This value should be true. 該變數的值應為 true 。 This value should be of type {{ type }}. 該變數的類型應為 {{ type }} 。 This value should be blank. 該變數應為空。 The value you selected is not a valid choice. 選定變數的值不是有效的選項。 You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. 您至少要選擇 {{ limit }} 個選項。 You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. 您最多能選擇 {{ limit }} 個選項。 One or more of the given values is invalid. 一個或者多個給定的值無效。 This field was not expected. 此字段是沒有預料到。 This field is missing. 此字段缺失。 This value is not a valid date. 該值不是一個有效的日期(date)。 This value is not a valid datetime. 該值不是一個有效的日期時間(datetime)。 This value is not a valid email address. 該值不是一個有效的郵件地址。 The file could not be found. 找不到檔案。 The file is not readable. 無法讀取檔案。 The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. 檔案太大 ({{ size }} {{ suffix }})。檔案大小不可以超過 {{ limit }} {{ suffix }} 。 The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. 無效的檔案類型 ({{ type }}) 。允許的檔案類型有 {{ types }} 。 This value should be {{ limit }} or less. 這個變數的值應該小於或等於 {{ limit }}。 This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. 字串太長,長度不可超過 {{ limit }} 個字元。 This value should be {{ limit }} or more. 該變數的值應該大於或等於 {{ limit }}。 This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. 字串太短,長度不可少於 {{ limit }} 個字元。 This value should not be blank. 該變數不應為空白。 This value should not be null. 該值不應為 null 。 This value should be null. 該值應為 null 。 This value is not valid. 無效的數值 。 This value is not a valid time. 該值不是一個有效的時間。 This value is not a valid URL. 該值不是一個有效的 URL 。 The two values should be equal. 這兩個變數的值應該相等。 The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. 檔案太大,檔案大小不可以超過 {{ limit }} {{ suffix }}。 The file is too large. 檔案太大。 The file could not be uploaded. 無法上傳此檔案。 This value should be a valid number. 該值應該為有效的數字。 This value is not a valid country. 該值不是有效的國家名。 This file is not a valid image. 該檔案不是有效的圖片。 This is not a valid IP address. 該值不是有效的IP地址。 This value is not a valid language. 該值不是有效的語言名。 This value is not a valid locale. 該值不是有效的區域值(locale)。 This value is already used. 該值已經被使用。 The size of the image could not be detected. 不能解析圖片大小。 The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. 圖片太寬 ({{ width }}px),最大寬度為 {{ max_width }}px 。 The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. 圖片寬度不夠 ({{ width }}px),最小寬度為 {{ min_width }}px 。 The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. 圖片太高 ({{ height }}px),最大高度為 {{ max_height }}px 。 The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. 圖片高度不夠 ({{ height }}px),最小高度為 {{ min_height }}px 。 This value should be the user's current password. 該變數的值應為用戶目前的密碼。 This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. 該變數應為 {{ limit }} 個字元。 The file was only partially uploaded. 該檔案的上傳不完整。 No file was uploaded. 沒有上傳任何檔案。 No temporary folder was configured in php.ini. php.ini 裡沒有配置臨時目錄。 Cannot write temporary file to disk. 暫存檔寫入磁碟失敗。 A PHP extension caused the upload to fail. 某個 PHP 擴展造成上傳失敗。 This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. 該集合最少應包含 {{ limit }} 個元素。 This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. 該集合最多包含 {{ limit }} 個元素。 This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. 該集合應包含 {{ limit }} 個元素 element 。 Invalid card number. 無效的信用卡號。 Unsupported card type or invalid card number. 不支援的信用卡類型或無效的信用卡號。 This is not a valid International Bank Account Number (IBAN). 該值不是有效的國際銀行帳號(IBAN)。 This value is not a valid ISBN-10. 該值不是有效的10位國際標準書號(ISBN-10)。 This value is not a valid ISBN-13. 該值不是有效的13位國際標準書號(ISBN-13)。 This value is neither a valid ISBN-10 nor a valid ISBN-13. 該值不是有效的國際標準書號(ISBN-10 或 ISBN-13)。 This value is not a valid ISSN. 該值不是有效的國際標準期刊號(ISSN)。 This value is not a valid currency. 該值不是有效的貨幣名(currency)。 This value should be equal to {{ compared_value }}. 該值應等於 {{ compared_value }} 。 This value should be greater than {{ compared_value }}. 該值應大於 {{ compared_value }} 。 This value should be greater than or equal to {{ compared_value }}. 該值應大於或等於 {{ compared_value }} 。 This value should be identical to {{ compared_value_type }} {{ compared_value }}. 該值應與 {{ compared_value_type }} {{ compared_value }} 相同。 This value should be less than {{ compared_value }}. 該值應小於 {{ compared_value }} 。 This value should be less than or equal to {{ compared_value }}. 該值應小於或等於 {{ compared_value }} 。 This value should not be equal to {{ compared_value }}. 該值應不等於 {{ compared_value }} 。 This value should not be identical to {{ compared_value_type }} {{ compared_value }}. 該值不應與 {{ compared_value_type }} {{ compared_value }} 相同。 This value should be false. Стойността трябва да бъде лъжа (false). This value should be true. Стойността трябва да бъде истина (true). This value should be of type {{ type }}. Стойността трябва да бъде от тип {{ type }}. This value should be blank. Стойността трябва да бъде празна. The value you selected is not a valid choice. Избраната стойност е невалидна. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Трябва да изберете поне {{ limit }} опция.|Трябва да изберете поне {{ limit }} опции. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Трябва да изберете най-много {{ limit }} опция.|Трябва да изберете най-много {{ limit }} опции. One or more of the given values is invalid. Една или повече от зададените стойности е невалидна. This field was not expected. Това поле не се е очаквало. This field is missing. Това поле липсва. This value is not a valid date. Стойността не е валидна дата (date). This value is not a valid datetime. Стойността не е валидна дата (datetime). This value is not a valid email address. Стойността не е валиден email адрес. The file could not be found. Файлът не беше открит. The file is not readable. Файлът не може да бъде прочетен. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файлът е твърде голям ({{ size }} {{ suffix }}). Максималният размер е {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Майм типа на файла е невалиден ({{ type }}). Разрешени майм типове са {{ types }}. This value should be {{ limit }} or less. Стойността трябва да бъде {{ limit }} или по-малко. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символ.|Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символа. This value should be {{ limit }} or more. Стойността трябва да бъде {{ limit }} или повече. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символ.|Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символа. This value should not be blank. Стойността не трябва да бъде празна. This value should not be null. Стойността не трябва да бъде null. This value should be null. Стойността трябва да бъде null. This value is not valid. Стойността не е валидна. This value is not a valid time. Стойността не е валидно време (time). This value is not a valid URL. Стойността не е валиден URL. The two values should be equal. Двете стойности трябва да бъдат равни. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файлът е твърде голям. Разрешеният максимален размер е {{ limit }} {{ suffix }}. The file is too large. Файлът е твърде голям. The file could not be uploaded. Файлът не може да бъде качен. This value should be a valid number. Стойността трябва да бъде валиден номер. This file is not a valid image. Файлът не е валидно изображение. This is not a valid IP address. Това не е валиден IP адрес. This value is not a valid language. Стойността не е валиден език. This value is not a valid locale. Стойността не е валидна локализация. This value is not a valid country. Стойността не е валидна държава. This value is already used. Стойността вече е в употреба. The size of the image could not be detected. Размера на изображението не може да бъде определен. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Изображението е твърде широко ({{ width }}px). Широчината трябва да бъде максимум {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Изображението е с твърде малка широчина ({{ width }}px). Широчината трябва да бъде минимум {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Изображението е с твърде голяма височина ({{ height }}px). Височината трябва да бъде максимум {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Изображението е с твърде малка височина ({{ height }}px). Височина трябва да бъде минимум {{ min_height }}px. This value should be the user's current password. Стойността трябва да бъде текущата потребителска парола. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Стойността трябва да бъде точно {{ limit }} символ.|Стойността трябва да бъде точно {{ limit }} символа. The file was only partially uploaded. Файлът е качен частично. No file was uploaded. Файлът не беше качен. No temporary folder was configured in php.ini. Не е посочена директория за временни файлове в php.ini. Cannot write temporary file to disk. Не може да запише временен файл на диска. A PHP extension caused the upload to fail. PHP разширение предизвика прекъсване на качването. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Колекцията трябва да съдържа поне {{ limit }} елемент.|Колекцията трябва да съдържа поне {{ limit }} елемента. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Колекцията трябва да съдържа най-много {{ limit }} елемент.|Колекцията трябва да съдържа най-много {{ limit }} елемента. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Колекцията трябва да съдържа точно {{ limit }} елемент.|Колекцията трябва да съдържа точно {{ limit }} елемента. Invalid card number. Невалиден номер на картата. Unsupported card type or invalid card number. Неподдържан тип карта или невалиден номер на картата. This is not a valid International Bank Account Number (IBAN). Невалиден Международен номер на банкова сметка (IBAN). This value is not a valid ISBN-10. Невалиден ISBN-10. This value is not a valid ISBN-13. Невалиден ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Невалидна стойност както за ISBN-10, така и за ISBN-13 . This value is not a valid ISSN. Невалиден Международен стандартен сериен номер (ISSN). This value is not a valid currency. Невалидна валута. This value should be equal to {{ compared_value }}. Стойността трябва да бъде равна на {{ compared_value }}. This value should be greater than {{ compared_value }}. Стойността трябва да бъде по-голяма от {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Стойността трябва да бъде по-голяма или равна на {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Стойността трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Стойността трябва да бъде по-малка {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Стойността трябва да бъде по-малка или равна на {{ compared_value }}. This value should not be equal to {{ compared_value }}. Стойността не трябва да бъде равна на {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Стойността не трябва да бъде идентична с {{ compared_value_type }} {{ compared_value }}.  This value should be false. Значение должно быть ложным. This value should be true. Значение должно быть истинным. This value should be of type {{ type }}. Тип значения должен быть {{ type }}. This value should be blank. Значение должно быть пустым. The value you selected is not a valid choice. Выбранное Вами значение недопустимо. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Вы должны выбрать хотя бы {{ limit }} вариант.|Вы должны выбрать хотя бы {{ limit }} варианта.|Вы должны выбрать хотя бы {{ limit }} вариантов. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Вы должны выбрать не более чем {{ limit }} вариант.|Вы должны выбрать не более чем {{ limit }} варианта.|Вы должны выбрать не более чем {{ limit }} вариантов. One or more of the given values is invalid. Одно или несколько заданных значений недопустимо. This field was not expected. Это поле не ожидалось. This field is missing. Это поле отсутствует. This value is not a valid date. Значение не является правильной датой. This value is not a valid datetime. Значение даты и времени недопустимо. This value is not a valid email address. Значение адреса электронной почты недопустимо. The file could not be found. Файл не может быть найден. The file is not readable. Файл не может быть прочитан. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файл слишком большой ({{ size }} {{ suffix }}). Максимально допустимый размер {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. MIME-тип файла недопустим ({{ type }}). Допустимы MIME-типы файлов {{ types }}. This value should be {{ limit }} or less. Значение должно быть {{ limit }} или меньше. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Значение слишком длинное. Должно быть равно {{ limit }} символу или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше. This value should be {{ limit }} or more. Значение должно быть {{ limit }} или больше. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Значение слишком короткое. Должно быть равно {{ limit }} символу или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше. This value should not be blank. Значение не должно быть пустым. This value should not be null. Значение не должно быть null. This value should be null. Значение должно быть null. This value is not valid. Значение недопустимо. This value is not a valid time. Значение времени недопустимо. This value is not a valid URL. Значение не является допустимым URL. The two values should be equal. Оба значения должны быть одинаковыми. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файл слишком большой. Максимально допустимый размер {{ limit }} {{ suffix }}. The file is too large. Файл слишком большой. The file could not be uploaded. Файл не может быть загружен. This value should be a valid number. Значение должно быть числом. This value is not a valid country. Значение не является допустимой страной. This file is not a valid image. Файл не является допустимым форматом изображения. This is not a valid IP address. Значение не является допустимым IP адресом. This value is not a valid language. Значение не является допустимым языком. This value is not a valid locale. Значение не является допустимой локалью. This value is already used. Это значение уже используется. The size of the image could not be detected. Не удалось определить размер изображения. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Ширина изображения слишком велика ({{ width }}px). Максимально допустимая ширина {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Ширина изображения слишком мала ({{ width }}px). Минимально допустимая ширина {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Высота изображения слишком велика ({{ height }}px). Максимально допустимая высота {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Высота изображения слишком мала ({{ height }}px). Минимально допустимая высота {{ min_height }}px. This value should be the user's current password. Значение должно быть текущим паролем пользователя. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Значение должно быть равно {{ limit }} символу.|Значение должно быть равно {{ limit }} символам.|Значение должно быть равно {{ limit }} символам. The file was only partially uploaded. Файл был загружен только частично. No file was uploaded. Файл не был загружен. No temporary folder was configured in php.ini. Не настроена временная директория в php.ini. Cannot write temporary file to disk. Невозможно записать временный файл на диск. A PHP extension caused the upload to fail. Расширение PHP вызвало ошибку при загрузке. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Эта коллекция должна содержать {{ limit }} элемент или больше.|Эта коллекция должна содержать {{ limit }} элемента или больше.|Эта коллекция должна содержать {{ limit }} элементов или больше. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Эта коллекция должна содержать {{ limit }} элемент или меньше.|Эта коллекция должна содержать {{ limit }} элемента или меньше.|Эта коллекция должна содержать {{ limit }} элементов или меньше. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Эта коллекция должна содержать ровно {{ limit }} элемент.|Эта коллекция должна содержать ровно {{ limit }} элемента.|Эта коллекция должна содержать ровно {{ limit }} элементов. Invalid card number. Неверный номер карты. Unsupported card type or invalid card number. Неподдерживаемый тип или неверный номер карты. This is not a valid International Bank Account Number (IBAN). Значение не является допустимым международным номером банковского счета (IBAN). This value is not a valid ISBN-10. Значение имеет неверный формат ISBN-10. This value is not a valid ISBN-13. Значение имеет неверный формат ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Значение не соответствует форматам ISBN-10 и ISBN-13. This value is not a valid ISSN. Значение не соответствует формату ISSN. This value is not a valid currency. Некорректный формат валюты. This value should be equal to {{ compared_value }}. Значение должно быть равно {{ compared_value }}. This value should be greater than {{ compared_value }}. Значение должно быть больше чем {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Значение должно быть больше или равно {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Значение должно быть идентичным {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Значение должно быть меньше чем {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Значение должно быть меньше или равно {{ compared_value }}. This value should not be equal to {{ compared_value }}. Значение не должно быть равно {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Значение не должно быть идентичным {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Соотношение сторон изображения слишком велико ({{ ratio }}). Максимальное соотношение сторон {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Соотношение сторон изображения слишком мало ({{ ratio }}). Минимальное соотношение сторон {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. Изображение квадратное ({{ width }}x{{ height }}px). Квадратные изображения не разрешены. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. Изображение в альбомной ориентации ({{ width }}x{{ height }}px). Изображения в альбомной ориентации не разрешены. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. Изображение в портретной ориентации ({{ width }}x{{ height }}px). Изображения в портретной ориентации не разрешены. An empty file is not allowed. Пустые файлы не разрешены. This value does not match the expected {{ charset }} charset. Значение не совпадает с ожидаемой {{ charset }} кодировкой. This value should be false. Balio hau faltsua izan beharko litzateke. This value should be true. Balio hau egia izan beharko litzateke. This value should be of type {{ type }}. Balio hau {{ type }} motakoa izan beharko litzateke. This value should be blank. Balio hau hutsik egon beharko litzateke. The value you selected is not a valid choice. Hautatu duzun balioa ez da aukera egoki bat. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Gutxienez aukera {{ limit }} hautatu behar duzu.|Gutxienez {{ limit }} aukera hautatu behar dituzu. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Gehienez aukera {{ limit }} hautatu behar duzu.|Gehienez {{ limit }} aukera hautatu behar dituzu. One or more of the given values is invalid. Emandako balioetatik gutxienez bat ez da egokia. This field was not expected. Eremu hau ez zen espero. This field is missing. Eremu hau falta da. This value is not a valid date. Balio hau ez da data egoki bat. This value is not a valid datetime. Balio hau ez da data-ordu egoki bat. This value is not a valid email address. Balio hau ez da posta elektroniko egoki bat. The file could not be found. Ezin izan da fitxategia aurkitu. The file is not readable. Fitxategia ez da irakurgarria. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fitxategia handiegia da ({{ size }} {{ suffix }}). Baimendutako tamaina handiena {{ limit }} {{ suffix }} da. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Fitxategiaren mime mota ez da egokia ({{ type }}). Hauek dira baimendutako mime motak: {{ types }}. This value should be {{ limit }} or less. Balio hau gehienez {{ limit }} izan beharko litzateke. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Balio hau luzeegia da. Gehienez karaktere {{ limit }} eduki beharko luke.|Balio hau luzeegia da. Gehienez {{ limit }} karaktere eduki beharko lituzke. This value should be {{ limit }} or more. Balio hau gutxienez {{ limit }} izan beharko litzateke. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Balio hau motzegia da. Karaktere {{ limit }} gutxienez eduki beharko luke.|Balio hau motzegia da. Gutxienez {{ limit }} karaktere eduki beharko lituzke. This value should not be blank. Balio hau ez litzateke hutsik egon behar. This value should not be null. Balio hau ez litzateke nulua izan behar. This value should be null. Balio hau nulua izan beharko litzateke. This value is not valid. Balio hau ez da egokia. This value is not a valid time. Balio hau ez da ordu egoki bat. This value is not a valid URL. Balio hau ez da baliabideen kokatzaile uniforme (URL) egoki bat. The two values should be equal. Bi balioak berdinak izan beharko lirateke. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fitxategia handiegia da. Baimendutako tamaina handiena {{ limit }} {{ suffix }} da. The file is too large. Fitxategia handiegia da. The file could not be uploaded. Ezin izan da fitxategia igo. This value should be a valid number. Balio hau zenbaki egoki bat izan beharko litzateke. This file is not a valid image. Fitxategi hau ez da irudi egoki bat. This is not a valid IP address. Honako hau ez da IP helbide egoki bat. This value is not a valid language. Balio hau ez da hizkuntza egoki bat. This value is not a valid locale. Balio hau ez da kokapen egoki bat. This value is not a valid country. Balio hau ez da herrialde egoki bat. This value is already used. Balio hau jadanik erabilia izan da. The size of the image could not be detected. Ezin izan da irudiaren tamaina detektatu. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Irudiaren zabalera handiegia da ({{ width }}px). Onartutako gehienezko zabalera {{ max_width }}px dira. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Irudiaren zabalera txikiegia da ({{ width }}px). Onartutako gutxieneko zabalera {{ min_width }}px dira. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Irudiaren altuera handiegia da ({{ height }}px). Onartutako gehienezko altuera {{ max_height }}px dira. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Irudiaren altuera txikiegia da ({{ height }}px). Onartutako gutxieneko altuera {{ min_height }}px dira. This value should be the user's current password. Balio hau uneko erabiltzailearen pasahitza izan beharko litzateke. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Balio honek zehazki karaktere {{ limit }} izan beharko luke.|Balio honek zehazki {{ limit }} karaktere izan beharko lituzke. The file was only partially uploaded. Fitxategiaren zati bat bakarrik igo da. No file was uploaded. Ez da fitxategirik igo. No temporary folder was configured in php.ini. Ez da aldi baterako karpetarik konfiguratu php.ini fitxategian. Cannot write temporary file to disk. Ezin izan da aldi baterako fitxategia diskoan idatzi. A PHP extension caused the upload to fail. PHP luzapen batek igoeraren hutsa eragin du. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Bilduma honek gutxienez elementu {{ limit }} eduki beharko luke.|Bilduma honek gutxienez {{ limit }} elementu eduki beharko lituzke. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Bilduma honek gehienez elementu {{ limit }} eduki beharko luke.|Bilduma honek gehienez {{ limit }} elementu eduki beharko lituzke. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Bilduma honek zehazki elementu {{ limit }} eduki beharko luke.|Bilduma honek zehazki {{ limit }} elementu eduki beharko lituzke. Invalid card number. Txartel zenbaki baliogabea. Unsupported card type or invalid card number. Txartel mota onartezina edo txartel zenbaki baliogabea. This is not a valid International Bank Account Number (IBAN). Hau ez da baliozko banku internazionaleko kontu zenbaki (IBAN) bat. This value is not a valid ISBN-10. Balio hau ez da onartutako ISBN-10 bat. This value is not a valid ISBN-13. Balio hau ez da onartutako ISBN-13 bat. This value is neither a valid ISBN-10 nor a valid ISBN-13. Balio hau ez da onartutako ISBN-10 edo ISBN-13 bat. This value is not a valid ISSN. Balio hau ez da onartutako ISSN bat. This value is not a valid currency. Balio hau ez da baliozko moneta bat. This value should be equal to {{ compared_value }}. Balio hau {{ compared_value }}-(r)en berbera izan beharko litzateke. This value should be greater than {{ compared_value }}. Balio hau {{ compared_value }} baino handiagoa izan beharko litzateke. This value should be greater than or equal to {{ compared_value }}. Balio hau {{ compared_value }}-(r)en berdina edota handiagoa izan beharko litzateke. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Balio hau {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan beharko litzateke. This value should be less than {{ compared_value }}. Balio hau {{ compared_value }} baino txikiagoa izan beharko litzateke. This value should be less than or equal to {{ compared_value }}. Balio hau {{ compared_value }}-(r)en berdina edota txikiagoa izan beharko litzateke. This value should not be equal to {{ compared_value }}. Balio hau ez litzateke {{ compared_value }}-(r)en berdina izan behar. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Balio hau ez litzateke {{ compared_value_type }} {{ compared_value }}-(r)en berbera izan behar. This value should be false. Această valoare ar trebui să fie falsă (false). This value should be true. Această valoare ar trebui să fie adevărată (true). This value should be of type {{ type }}. Această valoare ar trebui să fie de tipul {{ type }}. This value should be blank. Această valoare ar trebui sa fie goală. The value you selected is not a valid choice. Valoarea selectată nu este o opțiune validă. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Trebuie să selectați cel puțin {{ limit }} opțiune.|Trebuie să selectați cel puțin {{ limit }} opțiuni.|Trebuie să selectați cel puțin {{ limit }} de opțiuni You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Trebuie să selectați cel mult {{ limit }} opțiune.|Trebuie să selectați cel mult {{ limit }} opțiuni.|Trebuie să selectați cel mult {{ limit }} de opțiuni. One or more of the given values is invalid. Una sau mai multe dintre valorile furnizate sunt invalide. This field was not expected. Acest câmp nu era de aşteptat. This field is missing. Acest câmp este lipsă. This value is not a valid date. Această valoare nu reprezintă o dată validă. This value is not a valid datetime. Această valoare nu reprezintă o dată și oră validă. This value is not a valid email address. Această valoare nu reprezintă o adresă de e-mail validă. The file could not be found. Fișierul nu a putut fi găsit. The file is not readable. Fișierul nu poate fi citit. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fișierul este prea mare ({{ size }} {{ suffix }}). Dimensiunea maximă permisă este {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Tipul fișierului este invalid ({{ type }}). Tipurile permise de fișiere sunt ({{ types }}). This value should be {{ limit }} or less. Această valoare ar trebui să fie cel mult {{ limit }}. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caracter.|Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caractere.|Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} de caractere. This value should be {{ limit }} or more. Această valoare ar trebui să fie cel puțin {{ limit }}. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caracter.|Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caractere.|Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} de caractere. This value should not be blank. Această valoare nu ar trebui să fie goală. This value should not be null. Această valoare nu ar trebui să fie nulă (null). This value should be null. Această valoare ar trebui să fie nulă (null). This value is not valid. Această valoare nu este validă. This value is not a valid time. Această valoare nu reprezintă o oră validă. This value is not a valid URL. Această valoare nu reprezintă un URL (link) valid. The two values should be equal. Cele două valori ar trebui să fie egale. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fișierul este prea mare. Mărimea maximă permisă este {{ limit }} {{ suffix }}. The file is too large. Fișierul este prea mare. The file could not be uploaded. Fișierul nu a putut fi încărcat. This value should be a valid number. Această valoare nu reprezintă un număr valid. This file is not a valid image. Acest fișier nu este o imagine validă. This is not a valid IP address. Această valoare nu este o adresă IP validă. This value is not a valid language. Această valoare nu reprezintă o limbă corectă. This value is not a valid locale. Această valoare nu reprezintă un dialect (o limbă) corect. This value is not a valid country. Această valoare nu este o țară validă. This value is already used. Această valoare este folosită deja. The size of the image could not be detected. Mărimea imaginii nu a putut fi detectată. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Lățimea imaginii este prea mare ({{ width }}px). Lățimea maximă permisă este de {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Lățimea imaginii este prea mică ({{ width }}px). Lățimea minimă permisă este de {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Înălțimea imaginii este prea mare ({{ height }}px). Înălțimea maximă permisă este de {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Înălțimea imaginii este prea mică ({{ height }}px). Înălțimea minimă permisă este de {{ min_height }}px. This value should be the user's current password. Această valoare trebuie să fie parola curentă a utilizatorului. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Această valoare trebuie să conțină exact {{ limit }} caracter.|Această valoare trebuie să conțină exact {{ limit }} caractere.|Această valoare trebuie să conțină exact {{ limit }} de caractere. The file was only partially uploaded. Fișierul a fost încărcat parțial. No file was uploaded. Nu a fost încărcat nici un fișier. No temporary folder was configured in php.ini. Nu este configurat nici un director temporar in php.ini. Cannot write temporary file to disk. Nu a fost posibilă scrierea fișierului temporar pe disk. A PHP extension caused the upload to fail. O extensie PHP a prevenit încărcarea cu succes a fișierului. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Această colecție trebuie să conțină cel puțin {{ limit }} element.|Această colecție trebuie să conțină cel puțin {{ limit }} elemente.|Această colecție trebuie să conțină cel puțin {{ limit }} de elemente. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Această colecție trebuie să conțină cel mult {{ limit }} element.|Această colecție trebuie să conțină cel mult {{ limit }} elemente.|Această colecție trebuie să conțină cel mult {{ limit }} de elemente. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Această colecție trebuie să conțină {{ limit }} element.|Această colecție trebuie să conțină {{ limit }} elemente.|Această colecție trebuie să conțină {{ limit }} de elemente. Invalid card number. Numărul card invalid. Unsupported card type or invalid card number. Tipul sau numărul cardului nu sunt valide. This is not a valid International Bank Account Number (IBAN). Acesta nu este un cod IBAN (International Bank Account Number) valid. This value is not a valid ISBN-10. Această valoare nu este un cod ISBN-10 valid. This value is not a valid ISBN-13. Această valoare nu este un cod ISBN-13 valid. This value is neither a valid ISBN-10 nor a valid ISBN-13. Această valoare nu este un cod ISBN-10 sau ISBN-13 valid. This value is not a valid ISSN. Această valoare nu este un cod ISSN valid. This value is not a valid currency. Această valoare nu este o monedă validă. This value should be equal to {{ compared_value }}. Această valoare trebuie să fie egală cu {{ compared_value }}. This value should be greater than {{ compared_value }}. Această valoare trebuie să fie mai mare de {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Această valoare trebuie să fie mai mare sau egală cu {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Această valoare trebuie identică cu {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Această valoare trebuie să fie mai mică de {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Această valoare trebuie să fie mai mică sau egală cu {{ compared_value }}. This value should not be equal to {{ compared_value }}. Această valoare nu trebuie să fie egală cu {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Această valoare nu trebuie să fie identică cu {{ compared_value_type }} {{ compared_value }}. This value should be false. Este valor debería ser falso. This value should be true. Este valor debería ser verdadeiro. This value should be of type {{ type }}. Este valor debería ser de tipo {{ type }}. This value should be blank. Este valor debería estar baleiro. The value you selected is not a valid choice. O valor seleccionado non é unha opción válida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Debe seleccionar polo menos {{ limit }} opción.|Debe seleccionar polo menos {{ limit }} opcions. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opcions. One or more of the given values is invalid. Un ou máis dos valores indicados non son válidos. This field was not expected. Este campo non era esperado. This field is missing. Este campo falta. This value is not a valid date. Este valor non é unha data válida. This value is not a valid datetime. Este valor non é unha data e hora válidas. This value is not a valid email address. Este valor non é unha dirección de correo electrónico válida. The file could not be found. Non se puido atopar o arquivo. The file is not readable. O arquivo non se pode ler. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é demasiado grande ({{ size }} {{ suffix }}). O tamaño máximo permitido é {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. O tipo mime do arquivo non é válido ({{ type }}). Os tipos mime válidos son {{ types }}. This value should be {{ limit }} or less. Este valor debería ser {{ limit }} ou menos. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Este valor é demasiado longo. Debería ter {{ limit }} carácter ou menos.|Este valor é demasiado longo. Debería ter {{ limit }} caracteres ou menos. This value should be {{ limit }} or more. Este valor debería ser {{ limit }} ou máis. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Este valor é demasiado curto. Debería ter {{ limit }} carácter ou máis.|Este valor é demasiado corto. Debería ter {{ limit }} caracteres ou máis. This value should not be blank. Este valor non debería estar baleiro. This value should not be null. Este valor non debería ser null. This value should be null. Este valor debería ser null. This value is not valid. Este valor non é válido. This value is not a valid time. Este valor non é unha hora válida. This value is not a valid URL. Este valor non é unha URL válida. The two values should be equal. Os dous valores deberían ser iguais. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. O arquivo é demasiado grande. O tamaño máximo permitido é {{ limit }} {{ suffix }}. The file is too large. O arquivo é demasiado grande. The file could not be uploaded. No se puido cargar o arquivo. This value should be a valid number. Este valor debería ser un número válido. This file is not a valid image. O arquivo non é unha imaxe válida. This is not a valid IP address. Isto non é unha dirección IP válida. This value is not a valid language. Este valor non é un idioma válido. This value is not a valid locale. Este valor non é unha localización válida. This value is not a valid country. Este valor non é un país válido. This value is already used. Este valor xa está a ser empregado. The size of the image could not be detected. Non se puido determinar o tamaño da imaxe. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. A largura da imaxe é demasiado grande ({{ width }}px). A largura máxima permitida son {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. A largura da imaxe é demasiado pequena ({{ width }}px). A largura mínima requerida son {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. A altura da imaxe é demasiado grande ({{ height }}px). A altura máxima permitida son {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. A altura da imaxe é demasiado pequena ({{ height }}px). A altura mínima requerida son {{ min_height }}px. This value should be the user's current password. Este valor debería ser a contrasinal actual do usuario. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Este valor debería ter exactamente {{ limit }} carácter.|Este valor debería ter exactamente {{ limit }} caracteres. The file was only partially uploaded. O arquivo foi só subido parcialmente. No file was uploaded. Non se subiu ningún arquivo. No temporary folder was configured in php.ini. Ningunha carpeta temporal foi configurada en php.ini. Cannot write temporary file to disk. Non se puido escribir o arquivo temporal no disco. A PHP extension caused the upload to fail. Unha extensión de PHP provocou que a subida fallara. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Esta colección debe conter {{ limit }} elemento ou máis.|Esta colección debe conter {{ limit }} elementos ou máis. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Esta colección debe conter {{ limit }} elemento ou menos.|Esta colección debe conter {{ limit }} elementos ou menos. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Esta colección debe conter exactamente {{ limit }} elemento.|Esta colección debe conter exactamente {{ limit }} elementos. Invalid card number. Número de tarxeta non válido. Unsupported card type or invalid card number. Tipo de tarxeta non soportado ou número de tarxeta non válido. This is not a valid International Bank Account Number (IBAN). Este valor non é un International Bank Account Number (IBAN) válido. This value is not a valid ISBN-10. Este valor non é un ISBN-10 válido. This value is not a valid ISBN-13. Este valor non é un ISBN-13 válido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Este valor non é nin un ISBN-10 válido nin un ISBN-13 válido. This value is not a valid ISSN. Este valor non é un ISSN válido. This value is not a valid currency. Este valor non é unha moeda válida. This value should be equal to {{ compared_value }}. Este valor debería ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Este valor debería ser maior que {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Este valor debería ser maior ou igual que {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Este valor debería ser identico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Este valor debería ser menor que {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Este valor debería ser menor ou igual que {{ compared_value }}. This value should not be equal to {{ compared_value }}. Este valor non debería ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Este valor non debería ser identico a {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. A proporción da imaxe é demasiado grande ({{ ratio }}). A proporción máxima permitida é {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. A proporción da é demasiado pequena ({{ ratio }}). A proporción mínima permitida é {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. A imaxe é cadrada ({{ width }}x{{ height }}px). As imáxenes cadradas non están permitidas. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. A imaxe está orientada horizontalmente ({{ width }}x{{ height }}px). As imáxenes orientadas horizontalmente non están permitidas. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. A imaxe está orientada verticalmente ({{ width }}x{{ height }}px). As imáxenes orientadas verticalmente non están permitidas. An empty file is not allowed. Non está permitido un arquivo baleiro. The host could not be resolved. Non se puido resolver o host. This value does not match the expected {{ charset }} charset. A codificación de caracteres para este valor debería ser {{ charset }}. This value should be false. هذه القيمة يجب أن تكون خاطئة. This value should be true. هذه القيمة يجب أن تكون حقيقية. This value should be of type {{ type }}. هذه القيمة يجب ان تكون من نوع {{ type }}. This value should be blank. هذه القيمة يجب ان تكون فارغة. The value you selected is not a valid choice. القيمة المختارة ليست خيارا صحيحا. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيارات على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيارات على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر. One or more of the given values is invalid. واحد أو أكثر من القيم المعطاه خاطئ. This field was not expected. لم يكن من المتوقع هذا المجال. This field is missing. هذا المجال مفقود. This value is not a valid date. هذه القيمة ليست تاريخا صالحا. This value is not a valid datetime. هذه القيمة ليست تاريخا و وقتا صالحا. This value is not a valid email address. هذه القيمة ليست عنوان بريد إلكتروني صحيح. The file could not be found. لا يمكن العثور على الملف. The file is not readable. الملف غير قابل للقراءة. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. الملف كبير جدا ({{ size }} {{ suffix }}).اقصى مساحه مسموح بها ({{ limit }} {{ suffix }}). The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. نوع الملف غير صحيح ({{ type }}). الانواع المسموح بها هى {{ types }}. This value should be {{ limit }} or less. هذه القيمة يجب ان تكون {{ limit }} او اقل. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حروف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل. This value should be {{ limit }} or more. هذه القيمة يجب ان تكون {{ limit }} او اكثر. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حروف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر. This value should not be blank. هذه القيمة يجب الا تكون فارغة. This value should not be null. هذه القيمة يجب الا تكون فارغة. This value should be null. هذه القيمة يجب ان تكون فارغة. This value is not valid. هذه القيمة غير صحيحة. This value is not a valid time. هذه القيمة ليست وقت صحيح. This value is not a valid URL. هذه القيمة ليست رابط الكترونى صحيح. The two values should be equal. القيمتان يجب ان تكونا متساويتان. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. الملف كبير جدا. اقصى مساحه مسموح بها {{ limit }} {{ suffix }}. The file is too large. الملف كبير جدا. The file could not be uploaded. لم استطع استقبال الملف. This value should be a valid number. هذه القيمة يجب ان تكون رقم. This file is not a valid image. هذا الملف ليس صورة صحيحة. This is not a valid IP address. هذه القيمة ليست عنوان رقمى صحيح. This value is not a valid language. هذه القيمة ليست لغة صحيحة. This value is not a valid locale. هذه القيمة ليست موقع صحيح. This value is not a valid country. هذه القيمة ليست بلدا صالحا. This value is already used. هذه القيمة مستخدمة بالفعل. The size of the image could not be detected. لم استطع معرفة حجم الصورة. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. عرض الصورة كبير جدا ({{ width }}px). اقصى عرض مسموح به هو{{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. عرض الصورة صغير جدا ({{ width }}px). اقل عرض مسموح به هو{{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. طول الصورة كبير جدا ({{ height }}px). اقصى طول مسموح به هو{{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. طول الصورة صغير جدا ({{ height }}px). اقل طول مسموح به هو{{ min_height }}px. This value should be the user's current password. هذه القيمة يجب ان تكون كلمة سر المستخدم الحالية. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حروف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط. The file was only partially uploaded. تم استقبال جزء من الملف فقط. No file was uploaded. لم يتم ارسال اى ملف. No temporary folder was configured in php.ini. لم يتم تهيئة حافظة مؤقتة فى ملف php.ini. Cannot write temporary file to disk. لم استطع كتابة الملف المؤقت. A PHP extension caused the upload to fail. احد اضافات PHP تسببت فى فشل استقبال الملف. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط. Invalid card number. رقم البطاقه غير صحيح. Unsupported card type or invalid card number. نوع البطاقه غير مدعوم او الرقم غير صحيح. This is not a valid International Bank Account Number (IBAN). الرقم IBAN (رقم الحساب المصرفي الدولي) الذي تم إدخاله غير صالح. This value is not a valid ISBN-10. هذه القيمة ليست ISBN-10 صالحة. This value is not a valid ISBN-13. هذه القيمة ليست ISBN-13 صالحة. This value is neither a valid ISBN-10 nor a valid ISBN-13. هذه القيمة ليست ISBN-10 صالحة ولا ISBN-13 صالحة. This value is not a valid ISSN. هذه القيمة ليست ISSN صالحة. This value is not a valid currency. العُملة غير صحيحة. This value should be equal to {{ compared_value }}. القيمة يجب ان تساوي {{ compared_value }}. This value should be greater than {{ compared_value }}. القيمة يجب ان تكون اعلي من {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. القيمة يجب ان تكون مساوية او اعلي من {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. القيمة يجب ان تطابق {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. القيمة يجب ان تكون اقل من {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. القيمة يجب ان تساوي او تقل عن {{ compared_value }}. This value should not be equal to {{ compared_value }}. القيمة يجب ان لا تساوي {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. القيمة يجب ان لا تطابق {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. نسبة العرض على الارتفاع للصورة كبيرة جدا ({{ ratio }}). الحد الأقصى للنسبة المسموح به هو {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. نسبة العرض على الارتفاع للصورة صغيرة جدا ({{ ratio }}). الحد الأدنى للنسبة المسموح به هو {{ max_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. الصورة مربعة ({{ width }}x{{ height }}px). الصور المربعة غير مسموح بها. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. الصورة في وضع أفقي ({{ width }}x{{ height }}px). الصور في وضع أفقي غير مسموح بها. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. الصورة في وضع عمودي ({{ width }}x{{ height }}px). الصور في وضع عمودي غير مسموح بها. An empty file is not allowed. ملف فارغ غير مسموح به. The host could not be resolved. يتعذر الإتصال بالنطاق. This value does not match the expected {{ charset }} charset. هذه القيمة غير متطابقة مع صيغة التحويل {{ charset }}. This value should be false. Verdien skal være falsk. This value should be true. Verdien skal være sann. This value should be of type {{ type }}. Verdien skal være av typen {{ type }}. This value should be blank. Verdien skal være blank. The value you selected is not a valid choice. Verdien skal være en av de gitte valg. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du skal velge minst {{ limit }} valg. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan maks velge {{ limit }} valg. One or more of the given values is invalid. En eller flere av de oppgitte verdier er ugyldige. This field was not expected. Dette feltet ikke var forventet. This field is missing. Dette feltet mangler. This value is not a valid date. Verdien er ikke en gyldig dato. This value is not a valid datetime. Verdien er ikke en gyldig dato og tid. This value is not a valid email address. Verdien er ikke en gyldig e-mail adresse. The file could not be found. Filen kunne ikke finnes. The file is not readable. Filen kan ikke leses. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}. This value should be {{ limit }} or less. Verdien skal være {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Verdien er for lang. Den skal ha {{ limit }} bokstaver eller mindre. This value should be {{ limit }} or more. Verdien skal være {{ limit }} eller mer. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Verdien er for kort. Den skal ha {{ limit }} tegn eller flere. This value should not be blank. Verdien må ikke være blank. This value should not be null. Verdien må ikke være tom (null). This value should be null. Verdien skal være tom (null). This value is not valid. Verdien er ikke gyldig. This value is not a valid time. Verdien er ikke en gyldig tid. This value is not a valid URL. Verdien er ikke en gyldig URL. The two values should be equal. De to verdier skal være ens. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}. The file is too large. Filen er for stor. The file could not be uploaded. Filen kunne ikke lastes opp. This value should be a valid number. Denne verdi skal være et gyldig tall. This file is not a valid image. Denne filen er ikke et gyldig bilde. This is not a valid IP address. Dette er ikke en gyldig IP adresse. This value is not a valid language. Denne verdi er ikke et gyldig språk. This value is not a valid locale. Denne verdi er ikke en gyldig lokalitet. This value is not a valid country. Denne verdi er ikke et gyldig land.  This value should be false. Reikšmė turi būti neigiama. This value should be true. Reikšmė turi būti teigiama. This value should be of type {{ type }}. Šios reikšmės tipas turi būti {{ type }}. This value should be blank. Ši reikšmė turi būti tuščia. The value you selected is not a valid choice. Neteisingas pasirinkimas. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Turite pasirinkti bent {{ limit }} variantą.|Turite pasirinkti bent {{ limit }} variantus.|Turite pasirinkti bent {{ limit }} variantų. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Turite pasirinkti ne daugiau kaip {{ limit }} variantą.|Turite pasirinkti ne daugiau kaip {{ limit }} variantus.|Turite pasirinkti ne daugiau kaip {{ limit }} variantų. One or more of the given values is invalid. Viena ar daugiau įvestų reikšmių yra netinkamos. This field was not expected. Nebuvo tikimasi Šis laukas. This field is missing. Šiame lauke yra dingęs. This value is not a valid date. Ši reikšmė nėra data. This value is not a valid datetime. Ši reikšmė nera data ir laikas. This value is not a valid email address. Ši reikšmė nėra tinkamas el. pašto adresas. The file could not be found. Byla nerasta. The file is not readable. Negalima nuskaityti bylos. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Byla yra per didelė ({{ size }} {{ suffix }}). Maksimalus dydis {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Netinkamas bylos tipas (mime type) ({{ type }}). Galimi bylų tipai {{ types }}. This value should be {{ limit }} or less. Reikšmė turi būti {{ limit }} arba mažiau. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių. This value should be {{ limit }} or more. Reikšmė turi būti {{ limit }} arba daugiau. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių. This value should not be blank. Ši reikšmė negali būti tuščia. This value should not be null. Ši reikšmė negali būti null. This value should be null. Ši reikšmė turi būti null. This value is not valid. Netinkama reikšmė. This value is not a valid time. Ši reikšmė nėra laikas. This value is not a valid URL. Ši reikšmė nėra tinkamas interneto adresas. The two values should be equal. Abi reikšmės turi būti identiškos. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Byla yra per didelė. Maksimalus dydis yra {{ limit }} {{ suffix }}. The file is too large. Byla per didelė. The file could not be uploaded. Byla negali būti įkelta. This value should be a valid number. Ši reikšmė turi būti skaičius. This value is not a valid country. Ši reikšmė nėra tinkama šalis. This file is not a valid image. Byla nėra paveikslėlis. This is not a valid IP address. Ši reikšmė nėra tinkamas IP adresas. This value is not a valid language. Ši reikšmė nėra tinkama kalba. This value is not a valid locale. Ši reikšmė nėra tinkama lokalė. This value is already used. Ši reikšmė jau yra naudojama. The size of the image could not be detected. Nepavyko nustatyti nuotraukos dydžio. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Nuotraukos plotis per didelis ({{ width }}px). Maksimalus leidžiamas plotis yra {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Nuotraukos plotis per mažas ({{ width }}px). Minimalus leidžiamas plotis yra {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Nuotraukos aukštis per didelis ({{ height }}px). Maksimalus leidžiamas aukštis yra {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Nuotraukos aukštis per mažas ({{ height }}px). Minimalus leidžiamas aukštis yra {{ min_height }}px. This value should be the user's current password. Ši reikšmė turi sutapti su dabartiniu naudotojo slaptažodžiu. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ši reikšmė turi turėti lygiai {{ limit }} simbolį.|Ši reikšmė turi turėti lygiai {{ limit }} simbolius.|Ši reikšmė turi turėti lygiai {{ limit }} simbolių. The file was only partially uploaded. Failas buvo tik dalinai įkeltas. No file was uploaded. Nebuvo įkelta jokių failų. No temporary folder was configured in php.ini. Nėra sukonfiguruoto jokio laikino katalogo php.ini faile. Cannot write temporary file to disk. Nepavyko išsaugoti laikino failo. A PHP extension caused the upload to fail. PHP plėtinys sutrukdė failo įkėlimą ir jis nepavyko. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Sąraše turi būti lygiai {{ limit }} įrašas.|Sąraše turi būti lygiai {{ limit }} įrašai.|Sąraše turi būti lygiai {{ limit }} įrašų. Invalid card number. Klaidingas kortelės numeris. Unsupported card type or invalid card number. Kortelės tipas nepalaikomas arba klaidingas kortelės numeris. This is not a valid International Bank Account Number (IBAN). Ši reišmė neatitinka tarptautinio banko sąskaitos numerio formato (IBAN). This value is not a valid ISBN-10. Ši reikšmė neatitinka ISBN-10 formato. This value is not a valid ISBN-13. Ši reikšmė neatitinka ISBN-13 formato. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ši reikšmė neatitinka nei ISBN-10, nei ISBN-13 formato. This value is not a valid ISSN. Ši reišmė neatitinka ISSN formato. This value is not a valid currency. Netinkamas valiutos formatas. This value should be equal to {{ compared_value }}. Ši reikšmė turi būti lygi {{ compared_value }}. This value should be greater than {{ compared_value }}. Ši reikšmė turi būti didesnė už {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ši reikšmė turi būti didesnė už arba lygi {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ši reikšmė turi būti identiška {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ši reikšmė turi būti mažesnė už {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ši reikšmė turi būti mažesnė už arba lygi {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ši reikšmė neturi būti lygi {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ši reikšmė neturi būti identiška {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Nuotraukos santykis yra per didelis ({{ ratio }}). Didžiausias leistinas santykis yra {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Nuotraukos santykis yra per mažas ({{ ratio }}). Mažiausias leistinas santykis yra {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. Nuotrauka yra kvadratinė ({{ width }}x{{ height }}px). Kvadratinės nuotraukos nėra leistinos. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. Nuotrauka orientuota į plotį ({{ width }}x{{ height }}px). Nuotraukos orientuotos į plotį nėra leistinos. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. Nuotrauka orientuota į aukštį ({{ width }}x{{ height }}px). Nuotraukos orientuotos į aukštį nėra leistinos. An empty file is not allowed. Failas negali būti tuščias. This value should be false. Вредност треба да буде нетачна. This value should be true. Вредност треба да буде тачна. This value should be of type {{ type }}. Вредност треба да буде типа {{ type }}. This value should be blank. Вредност треба да буде празна. The value you selected is not a valid choice. Вредност треба да буде једна од понуђених. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Изаберите бар {{ limit }} могућност.|Изаберите бар {{ limit }} могућности.|Изаберите бар {{ limit }} могућности. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Изаберите највише {{ limit }} могућност.|Изаберите највише {{ limit }} могућности.|Изаберите највише {{ limit }} могућности. One or more of the given values is invalid. Једна или више вредности је невалидна. This field was not expected. Ово поље не очекује. This field is missing. Ово поље недостаје. This value is not a valid date. Вредност није валидан датум. This value is not a valid datetime. Вредност није валидан датум-време. This value is not a valid email address. Вредност није валидна адреса електронске поште. The file could not be found. Датотека не може бити пронађена. The file is not readable. Датотека није читљива. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Датотека је превелика ({{ size }} {{ suffix }}). Највећа дозвољена величина је {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Миме тип датотеке није валидан ({{ type }}). Дозвољени миме типови су {{ types }}. This value should be {{ limit }} or less. Вредност треба да буде {{ limit }} или мање. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Вредност је предугачка. Треба да има {{ limit }} карактер или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање. This value should be {{ limit }} or more. Вредност треба да буде {{ limit }} или више. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Вредност је прекратка. Треба да има {{ limit }} карактер или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више. This value should not be blank. Вредност не треба да буде празна. This value should not be null. Вредност не треба да буде null. This value should be null. Вредност треба да буде null. This value is not valid. Вредност је невалидна. This value is not a valid time. Вредност није валидно време. This value is not a valid URL. Вредност није валидан URL. The two values should be equal. Обе вредности треба да буду једнаке. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Датотека је превелика. Највећа дозвољена величина је {{ limit }} {{ suffix }}. The file is too large. Датотека је превелика. The file could not be uploaded. Датотека не може бити отпремљена. This value should be a valid number. Вредност треба да буде валидан број. This file is not a valid image. Ова датотека није валидна слика. This is not a valid IP address. Ово није валидна ИП адреса. This value is not a valid language. Вредност није валидан језик. This value is not a valid locale. Вредност није валидан локал. This value is not a valid country. Вредност није валидна земља. This value is already used. Вредност је већ искоришћена. The size of the image could not be detected. Величина слике не може бити одређена. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Ширина слике је превелика ({{ width }}px). Најећа дозвољена ширина је {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Ширина слике је премала ({{ width }}px). Најмања дозвољена ширина је {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Висина слике је превелика ({{ height }}px). Најећа дозвољена висина је {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Висина слике је премала ({{ height }}px). Најмања дозвољена висина је {{ min_height }}px. This value should be the user's current password. Вредност треба да буде тренутна корисничка лозинка. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Вредност треба да има тачно {{ limit }} карактер.|Вредност треба да има тачно {{ limit }} карактера.|Вредност треба да има тачно {{ limit }} карактера. The file was only partially uploaded. Датотека је само парцијално отпремљена. No file was uploaded. Датотека није отпремљена. No temporary folder was configured in php.ini. Привремени директоријум није конфигурисан у php.ini. Cannot write temporary file to disk. Немогуће писање привремене датотеке на диск. A PHP extension caused the upload to fail. PHP екстензија је проузроковала неуспех отпремања датотеке. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ова колекција треба да садржи тачно {{ limit }} елемент.|Ова колекција треба да садржи тачно {{ limit }} елемента.|Ова колекција треба да садржи тачно {{ limit }} елемената. Invalid card number. Невалидан број картице. Unsupported card type or invalid card number. Невалидан број картице или тип картице није подржан. This is not a valid International Bank Account Number (IBAN). Ово није валидан међународни број банковног рачуна (IBAN). This value is not a valid ISBN-10. Ово није валидан ISBN-10. This value is not a valid ISBN-13. Ово није валидан ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ово није валидан ISBN-10 или ISBN-13. This value is not a valid ISSN. Ово није валидан ISSN. This value is not a valid currency. Ово није валидна валута. This value should be equal to {{ compared_value }}. Ова вредност треба да буде {{ compared_value }}. This value should be greater than {{ compared_value }}. Ова вредност треба да буде већа од {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ова вредност треба да буде већа или једнака {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ова вредност треба да буде идентична са {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ова вредност треба да буде мања од {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ова вредност треба да буде мања или једнака {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ова вредност не треба да буде једнака {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ова вредност не треба да буде идентична са {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Размера ове слике је превелика ({{ ratio }}). Максимална дозвољена размера је {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Размера ове слике је премала ({{ ratio }}). Минимална очекивана размера је {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. Слика је квадратна ({{ width }}x{{ height }}px). Квадратне слике нису дозвољене. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. Слика је оријентације пејзажа ({{ width }}x{{ height }}px). Пејзажна оријентација слика није дозвољена. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. Слика је оријантације портрета ({{ width }}x{{ height }}px). Портретна оријентација слика није дозвољена. This value should be false. Vrednost bi morala biti nepravilna (false). This value should be true. Vrednost bi morala biti pravilna (true). This value should be of type {{ type }}. Vrednost mora biti naslednjega tipa {{ type }}. This value should be blank. Vrednost mora biti prazna. The value you selected is not a valid choice. Vrednost, ki ste jo izbrali, ni veljavna možnost. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Izbrati morate vsaj {{ limit }} možnost.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Izberete lahko največ {{ limit }} možnost.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti. One or more of the given values is invalid. Ena ali več podanih vrednosti ni veljavnih. This field was not expected. To polje ni bilo pričakovati. This field is missing. To polje manjka. This value is not a valid date. Ta vrednost ni veljaven datum. This value is not a valid datetime. Ta vrednost ni veljaven datum in čas. This value is not a valid email address. Ta vrednost ni veljaven e-poštni naslov. The file could not be found. Datoteke ni mogoče najti. The file is not readable. Datoteke ni mogoče prebrati. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika ({{ size }} {{ suffix }}). Največja dovoljena velikost je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime tip datoteke je neveljaven ({{ type }}). Dovoljeni mime tipi so {{ types }}. This value should be {{ limit }} or less. Ta vrednost bi morala biti {{ limit }} ali manj. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ta vrednost je predolga. Morala bi imeti {{ limit }} znak ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znaka ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znake ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znakov ali manj. This value should be {{ limit }} or more. Ta vrednost bi morala biti {{ limit }} ali več. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ta vrednost je prekratka. Morala bi imeti {{ limit }} znak ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znaka ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znake ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znakov ali več. This value should not be blank. Ta vrednost ne bi smela biti prazna. This value should not be null. Ta vrednost ne bi smela biti nedefinirana (null). This value should be null. Ta vrednost bi morala biti nedefinirana (null). This value is not valid. Ta vrednost ni veljavna. This value is not a valid time. Ta vrednost ni veljaven čas. This value is not a valid URL. Ta vrednost ni veljaven URL. The two values should be equal. Ti dve vrednosti bi morali biti enaki. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika. Največja dovoljena velikost je {{ limit }} {{ suffix }}. The file is too large. Datoteka je prevelika. The file could not be uploaded. Datoteke ni bilo mogoče naložiti. This value should be a valid number. Ta vrednost bi morala biti veljavna številka. This file is not a valid image. Ta datoteka ni veljavna slika. This is not a valid IP address. To ni veljaven IP naslov. This value is not a valid language. Ta vrednost ni veljaven jezik. This value is not a valid locale. Ta vrednost ni veljavna lokalnost. This value is not a valid country. Ta vrednost ni veljavna država. This value is already used. Ta vrednost je že uporabljena. The size of the image could not be detected. Velikosti slike ni bilo mogoče zaznati. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Širina slike je preširoka ({{ width }}px). Največja dovoljena širina je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Širina slike je premajhna ({{ width }}px). Najmanjša predvidena širina je {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Višina slike je prevelika ({{ height }}px). Največja dovoljena višina je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Višina slike je premajhna ({{ height }}px). Najmanjša predvidena višina je {{ min_height }}px. This value should be the user's current password. Ta vrednost bi morala biti trenutno uporabnikovo geslo. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ta vrednost bi morala imeti točno {{ limit }} znak.|Ta vrednost bi morala imeti točno {{ limit }} znaka.|Ta vrednost bi morala imeti točno {{ limit }} znake.|Ta vrednost bi morala imeti točno {{ limit }} znakov. The file was only partially uploaded. Datoteka je bila le delno naložena. No file was uploaded. Nobena datoteka ni bila naložena. No temporary folder was configured in php.ini. Začasna mapa ni nastavljena v php.ini. Cannot write temporary file to disk. Začasne datoteke ni bilo mogoče zapisati na disk. A PHP extension caused the upload to fail. PHP razširitev je vzrok, da nalaganje ni uspelo. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ta zbirka bi morala vsebovati {{ limit }} element ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali več.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali več. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ta zbirka bi morala vsebovati {{ limit }} element ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali manj. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ta zbirka bi morala vsebovati točno {{ limit }} element.|Ta zbirka bi morala vsebovati točno {{ limit }} elementa.|Ta zbirka bi morala vsebovati točno {{ limit }} elemente.|Ta zbirka bi morala vsebovati točno {{ limit }} elementov. Invalid card number. Neveljavna številka kartice. Unsupported card type or invalid card number. Nepodprti tip kartice ali neveljavna številka kartice. This is not a valid International Bank Account Number (IBAN). To ni veljavna mednarodna številka bančnega računa (IBAN). This value is not a valid ISBN-10. Neveljavna vrednost po ISBN-10. This value is not a valid ISBN-13. Neveljavna vrednost po ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Neveljavna vrednost po ISBN-10 ali po ISBN-13. This value is not a valid ISSN. Neveljavna vrednost ISSN. This value is not a valid currency. Ta vrednost ni veljavna valuta. This value should be equal to {{ compared_value }}. Ta vrednost bi morala biti enaka {{ compared_value }}. This value should be greater than {{ compared_value }}. Ta vrednost bi morala biti večja od {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ta vrednost bi morala biti večja ali enaka {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ta vrednost bi morala biti identična {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ta vrednost bi morala biti manjša od {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ta vrednost bi morala biti manjša ali enaka {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ta vrednost ne bi smela biti enaka {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ta vrednost ne bi smela biti identična {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Razmerje slike je preveliko ({{ ratio }}). Največje dovoljeno razmerje je {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Razmerje slike je premajhno ({{ ratio }}). Najmanjše pričakovano razmerje je {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. Slika je kvadrat ({{ width }}x{{ height }}px). Kvadratne slike niso dovoljene. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. Slika je ležeče usmerjena ({{ width }}x{{ height }}px). Ležeče usmerjene slike niso dovoljene. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. Slika je pokončno usmerjena ({{ width }}x{{ height }}px). Pokončno usmerjene slike niso dovoljene. An empty file is not allowed. Prazna datoteka ni dovoljena. This value does not match the expected {{ charset }} charset. Ta vrednost se ne ujema s pričakovanim naborom znakov {{ charset }}. This value should be false. Aquest valor hauria de ser fals. This value should be true. Aquest valor hauria de ser cert. This value should be of type {{ type }}. Aquest valor hauria de ser del tipus {{ type }}. This value should be blank. Aquest valor hauria d'estar buit. The value you selected is not a valid choice. El valor seleccionat no és una opció vàlida. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Ha de seleccionar almenys {{ limit }} opció.|Ha de seleccionar almenys {{ limit }} opcions. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Ha de seleccionar com a màxim {{ limit }} opció.|Ha de seleccionar com a màxim {{ limit }} opcions. One or more of the given values is invalid. Un o més dels valors facilitats són incorrectes. This field was not expected. Aquest camp no s'esperava. This field is missing. Aquest camp està desaparegut. This value is not a valid date. Aquest valor no és una data vàlida. This value is not a valid datetime. Aquest valor no és una data i hora vàlida. This value is not a valid email address. Aquest valor no és una adreça d'email vàlida. The file could not be found. No s'ha pogut trobar l'arxiu. The file is not readable. No es pot llegir l'arxiu. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. L'arxiu és massa gran ({{ size }} {{ suffix }}). La grandària màxima permesa és {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. El tipus mime de l'arxiu no és vàlid ({{ type }}). Els tipus mime vàlids són {{ types }}. This value should be {{ limit }} or less. Aquest valor hauria de ser {{ limit }} o menys. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcter o menys.|Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcters o menys. This value should be {{ limit }} or more. Aquest valor hauria de ser {{ limit }} o més. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Aquest valor és massa curt. Hauria de tenir {{ limit }} caràcters o més. This value should not be blank. Aquest valor no hauria d'estar buit. This value should not be null. Aquest valor no hauria de ser null. This value should be null. Aquest valor hauria de ser null. This value is not valid. Aquest valor no és vàlid. This value is not a valid time. Aquest valor no és una hora vàlida. This value is not a valid URL. Aquest valor no és una URL vàlida. The two values should be equal. Els dos valors haurien de ser iguals. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. L'arxiu és massa gran. El tamany màxim permés és {{ limit }} {{ suffix }}. The file is too large. L'arxiu és massa gran. The file could not be uploaded. No es pot pujar l'arxiu. This value should be a valid number. Aquest valor hauria de ser un nombre vàlid. This file is not a valid image. L'arxiu no és una imatge vàlida. This is not a valid IP address. Això no és una adreça IP vàlida. This value is not a valid language. Aquest valor no és un idioma vàlid. This value is not a valid locale. Aquest valor no és una localització vàlida. This value is not a valid country. Aquest valor no és un país vàlid. This value is already used. Aquest valor ja s'ha utilitzat. The size of the image could not be detected. No s'ha pogut determinar la grandària de la imatge. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. L'amplària de la imatge és massa gran ({{ width }}px). L'amplària màxima permesa són {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. L'amplària de la imatge és massa petita ({{ width }}px). L'amplària mínima requerida són {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. L'altura de la imatge és massa gran ({{ height }}px). L'altura màxima permesa són {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. L'altura de la imatge és massa petita ({{ height }}px). L'altura mínima requerida són {{ min_height }}px. This value should be the user's current password. Aquest valor hauria de ser la contrasenya actual de l'usuari. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Aquest valor hauria de tenir exactament {{ limit }} caràcter.|Aquest valor hauria de tenir exactament {{ limit }} caràcters. The file was only partially uploaded. L'arxiu va ser només pujat parcialment. No file was uploaded. Cap arxiu va ser pujat. No temporary folder was configured in php.ini. Cap carpeta temporal va ser configurada en php.ini. Cannot write temporary file to disk. No es va poder escriure l'arxiu temporal en el disc. A PHP extension caused the upload to fail. Una extensió de PHP va fer que la pujada fallara. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Aquesta col·lecció ha de contenir {{ limit }} element o més.|Aquesta col·lecció ha de contenir {{ limit }} elements o més. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Aquesta col·lecció ha de contenir {{ limit }} element o menys.|Aquesta col·lecció ha de contenir {{ limit }} elements o menys. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Aquesta col·lecció ha de contenir exactament {{ limit }} element.|Aquesta col·lecció ha de contenir exactament {{ limit }} elements. Invalid card number. Número de targeta invàlid. Unsupported card type or invalid card number. Tipus de targeta no suportada o número de targeta invàlid. This is not a valid International Bank Account Number (IBAN). Això no és un nombre de compte bancari internacional (IBAN) vàlid. This value is not a valid ISBN-10. Aquest valor no és un ISBN-10 vàlid. This value is not a valid ISBN-13. Aquest valor no és un ISBN-13 vàlid. This value is neither a valid ISBN-10 nor a valid ISBN-13. Aquest valor no és ni un ISBN-10 vàlid ni un ISBN-13 vàlid. This value is not a valid ISSN. Aquest valor no és un ISSN vàlid. This value is not a valid currency. Aquest valor no és una divisa vàlida. This value should be equal to {{ compared_value }}. Aquest valor hauria de ser igual a {{ compared_value }}. This value should be greater than {{ compared_value }}. Aquest valor hauria de ser més gran a {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Aquest valor hauria de ser major o igual a {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Aquest valor hauria de ser idèntic a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Aquest valor hauria de ser menor a {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Aquest valor hauria de ser menor o igual a {{ compared_value }}. This value should not be equal to {{ compared_value }}. Aquest valor no hauria de ser igual a {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Aquest valor no hauria de idèntic a {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. La proporció de l'imatge és massa gran ({{ ratio }}). La màxima proporció permesa és {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. La proporció de l'imatge és massa petita ({{ ratio }}). La mínima proporció permesa és {{ max_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. L'imatge és quadrada({{ width }}x{{ height }}px). Les imatges quadrades no estan permeses. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. L'imatge està orientada horitzontalment ({{ width }}x{{ height }}px). Les imatges orientades horitzontalment no estan permeses. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. L'imatge està orientada verticalment ({{ width }}x{{ height }}px). Les imatges orientades verticalment no estan permeses. An empty file is not allowed. No està permès un fixter buit. This value should be false. Deze waarde mag niet waar zijn. This value should be true. Deze waarde moet waar zijn. This value should be of type {{ type }}. Deze waarde moet van het type {{ type }} zijn. This value should be blank. Deze waarde moet leeg zijn. The value you selected is not a valid choice. De geselecteerde waarde is geen geldige optie. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Selecteer ten minste {{ limit }} optie.|Selecteer ten minste {{ limit }} opties. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Selecteer maximaal {{ limit }} optie.|Selecteer maximaal {{ limit }} opties. One or more of the given values is invalid. Eén of meer van de ingegeven waarden zijn ongeldig. This field was not expected. Dit veld was niet verwacht. This field is missing. Dit veld ontbreekt. This value is not a valid date. Deze waarde is geen geldige datum. This value is not a valid datetime. Deze waarde is geen geldige datum en tijd. This value is not a valid email address. Deze waarde is geen geldig e-mailadres. The file could not be found. Het bestand is niet gevonden. The file is not readable. Het bestand is niet leesbaar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Het bestand is te groot ({{ size }} {{ suffix }}). Toegestane maximum grootte is {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Het mime type van het bestand is ongeldig ({{ type }}). Toegestane mime types zijn {{ types }}. This value should be {{ limit }} or less. Deze waarde moet {{ limit }} of minder zijn. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Deze waarde is te lang. Hij mag maximaal {{ limit }} teken bevatten.|Deze waarde is te lang. Hij mag maximaal {{ limit }} tekens bevatten. This value should be {{ limit }} or more. Deze waarde moet {{ limit }} of meer zijn. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Deze waarde is te kort. Hij moet tenminste {{ limit }} teken bevatten.|Deze waarde is te kort. Hij moet tenminste {{ limit }} tekens bevatten. This value should not be blank. Deze waarde mag niet leeg zijn. This value should not be null. Deze waarde mag niet null zijn. This value should be null. Deze waarde moet null zijn. This value is not valid. Deze waarde is ongeldig. This value is not a valid time. Deze waarde is geen geldige tijd. This value is not a valid URL. Deze waarde is geen geldige URL. The two values should be equal. De twee waarden moeten gelijk zijn. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Het bestand is te groot. Toegestane maximum grootte is {{ limit }} {{ suffix }}. The file is too large. Het bestand is te groot. The file could not be uploaded. Het bestand kon niet geüpload worden. This value should be a valid number. Deze waarde moet een geldig getal zijn. This file is not a valid image. Dit bestand is geen geldige afbeelding. This is not a valid IP address. Dit is geen geldig IP-adres. This value is not a valid language. Deze waarde representeert geen geldige taal. This value is not a valid locale. Deze waarde representeert geen geldige lokalisering. This value is not a valid country. Deze waarde representeert geen geldig land. This value is already used. Deze waarde wordt al gebruikt. The size of the image could not be detected. De grootte van de afbeelding kon niet bepaald worden. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. De afbeelding is te breed ({{ width }}px). De maximaal toegestane breedte is {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. De afbeelding is niet breed genoeg ({{ width }}px). De minimaal verwachte breedte is {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. De afbeelding is te hoog ({{ height }}px). De maximaal toegestane hoogte is {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. De afbeelding is niet hoog genoeg ({{ height }}px). De minimaal verwachte hoogte is {{ min_height }}px. This value should be the user's current password. Deze waarde moet het huidige wachtwoord van de gebruiker zijn. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Deze waarde moet exact {{ limit }} teken lang zijn.|Deze waarde moet exact {{ limit }} tekens lang zijn. The file was only partially uploaded. Het bestand is niet geheel geüpload. No file was uploaded. Er is geen bestand geüpload. No temporary folder was configured in php.ini. Er is geen tijdelijke map geconfigureerd in php.ini. Cannot write temporary file to disk. Kan het tijdelijke bestand niet wegschrijven op disk. A PHP extension caused the upload to fail. De upload is mislukt vanwege een PHP-extensie. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Deze collectie moet {{ limit }} element of meer bevatten.|Deze collectie moet {{ limit }} elementen of meer bevatten. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Deze collectie moet {{ limit }} element of minder bevatten.|Deze collectie moet {{ limit }} elementen of minder bevatten. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Deze collectie moet exact {{ limit }} element bevatten.|Deze collectie moet exact {{ limit }} elementen bevatten. Invalid card number. Ongeldig creditcardnummer. Unsupported card type or invalid card number. Niet-ondersteund type creditcard of ongeldig nummer. This is not a valid International Bank Account Number (IBAN). Dit is geen geldig internationaal bankrekeningnummer (IBAN). This value is not a valid ISBN-10. Deze waarde is geen geldige ISBN-10. This value is not a valid ISBN-13. Deze waarde is geen geldige ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Deze waarde is geen geldige ISBN-10 of ISBN-13 waarde. This value is not a valid ISSN. Deze waarde is geen geldige ISSN waarde. This value is not a valid currency. Deze waarde is geen geldige valuta. This value should be equal to {{ compared_value }}. Deze waarde moet gelijk zijn aan {{ compared_value }}. This value should be greater than {{ compared_value }}. Deze waarde moet groter zijn dan {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Deze waarde moet groter dan of gelijk aan {{ compared_value }} zijn. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Deze waarde moet identiek zijn aan {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Deze waarde moet minder zijn dan {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Deze waarde moet minder dan of gelijk aan {{ compared_value }} zijn. This value should not be equal to {{ compared_value }}. Deze waarde mag niet gelijk zijn aan {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Deze waarde mag niet identiek zijn aan {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. De afbeeldingsverhouding is te groot ({{ ratio }}). Maximale verhouding is {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. De afbeeldingsverhouding is te klein ({{ ratio }}). Minimale verhouding is {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. De afbeelding is vierkant ({{ width }}x{{ height }}px). Vierkante afbeeldingen zijn niet toegestaan. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. De afbeelding is liggend ({{ width }}x{{ height }}px). Liggende afbeeldingen zijn niet toegestaan. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. De afbeelding is staand ({{ width }}x{{ height }}px). Staande afbeeldingen zijn niet toegestaan. An empty file is not allowed. Lege bestanden zijn niet toegestaan. This value does not match the expected {{ charset }} charset. Deze waarde is niet in de verwachte tekencodering {{ charset }}. This value should be false. Ova vrijednost treba biti netočna (false). This value should be true. Ova vrijednost treba biti točna (true). This value should be of type {{ type }}. Ova vrijednost treba biti tipa {{ type }}. This value should be blank. Ova vrijednost treba biti prazna. The value you selected is not a valid choice. Ova vrijednost treba biti jedna od ponuđenih. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Izaberite barem {{ limit }} mogućnosti. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Izaberite najviše {{ limit }} mogućnosti. One or more of the given values is invalid. Jedna ili više danih vrijednosti nije ispravna. This field was not expected. Ovo polje nije očekivalo. This field is missing. Ovo polje nedostaje. This value is not a valid date. Ova vrijednost nije ispravan datum. This value is not a valid datetime. Ova vrijednost nije ispravan datum-vrijeme. This value is not a valid email address. Ova vrijednost nije ispravna e-mail adresa. The file could not be found. Datoteka ne može biti pronađena. The file is not readable. Datoteka nije čitljiva. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime tip datoteke nije ispravan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}. This value should be {{ limit }} or less. Ova vrijednost treba biti {{ limit }} ili manje. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ova vrijednost je predugačka. Treba imati {{ limit }} znakova ili manje. This value should be {{ limit }} or more. Ova vrijednost treba biti {{ limit }} ili više. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ova vrijednost je prekratka. Treba imati {{ limit }} znakova ili više. This value should not be blank. Ova vrijednost ne smije biti prazna. This value should not be null. Ova vrijednost ne smije biti null. This value should be null. Ova vrijednost treba biti null. This value is not valid. Ova vrijednost nije ispravna. This value is not a valid time. Ova vrijednost nije ispravno vrijeme. This value is not a valid URL. Ova vrijednost nije ispravan URL. The two values should be equal. Obje vrijednosti trebaju biti jednake. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ova datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The file is too large. Ova datoteka je prevelika. The file could not be uploaded. Ova datoteka ne može biti prenesena. This value should be a valid number. Ova vrijednost treba biti ispravan broj. This file is not a valid image. Ova datoteka nije ispravna slika. This is not a valid IP address. Ovo nije ispravna IP adresa. This value is not a valid language. Ova vrijednost nije ispravan jezik. This value is not a valid locale. Ova vrijednost nije ispravana regionalna oznaka. This value is not a valid country. Ova vrijednost nije ispravna zemlja. This value is already used. Ova vrijednost je već iskorištena. The size of the image could not be detected. Veličina slike se ne može odrediti. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Širina slike je prevelika ({{ width }}px). Najveća dozvoljena širina je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Visina slike je prevelika ({{ height }}px). Najveća dozvoljena visina je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px. This value should be the user's current password. Ova vrijednost treba biti trenutna korisnička lozinka. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ova vrijednost treba imati točno {{ limit }} znakova. The file was only partially uploaded. Datoteka je samo djelomično prenesena. No file was uploaded. Niti jedna datoteka nije prenesena. No temporary folder was configured in php.ini. U php.ini datoteci nije konfiguriran privremeni folder. Cannot write temporary file to disk. Ne mogu zapisati privremenu datoteku na disk. A PHP extension caused the upload to fail. Prijenos datoteke nije uspio zbog PHP ekstenzije. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ova kolekcija treba sadržavati točno {{ limit }} element.|Ova kolekcija treba sadržavati točno {{ limit }} elementa.|Ova kolekcija treba sadržavati točno {{ limit }} elemenata. Invalid card number. Neispravan broj kartice. Unsupported card type or invalid card number. Neispravan broj kartice ili tip kartice nije podržan. This is not a valid International Bank Account Number (IBAN). Ova vrijednost nije ispravan međunarodni broj bankovnog računa (IBAN). This value is not a valid ISBN-10. Ova vrijednost nije ispravan ISBN-10. This value is not a valid ISBN-13. Ova vrijednost nije ispravan ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ova vrijednost nije ispravan ISBN-10 niti ISBN-13. This value is not a valid ISSN. Ova vrijednost nije ispravan ISSN. This value is not a valid currency. Ova vrijednost nije ispravna valuta. This value should be equal to {{ compared_value }}. Ova vrijednost bi trebala biti jednaka {{ compared_value }}. This value should be greater than {{ compared_value }}. Ova vrijednost bi trebala biti veća od {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ova vrijednost bi trebala biti veća ili jednaka od {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ova vrijednost bi trebala biti {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ova vrijednost bi trebala biti manja od {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ova vrijednost bi trebala biti manja ili jednaka {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ova vrijednost ne bi trebala biti {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ova vrijednost ne bi trebala biti {{ compared_value_type }} {{ compared_value }}. This value should be false. Αυτή η τιμή πρέπει να είναι ψευδής. This value should be true. Αυτή η τιμή πρέπει να είναι αληθής. This value should be of type {{ type }}. Αυτή η τιμή πρέπει να είναι τύπου {{ type }}. This value should be blank. Αυτή η τιμή πρέπει να είναι κενή. The value you selected is not a valid choice. Η τιμή που επιλέχθηκε δεν αντιστοιχεί σε έγκυρη επιλογή. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογή.|Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογές. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογή.|Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογές. One or more of the given values is invalid. Μια ή περισσότερες τιμές δεν είναι έγκυρες. This field was not expected. Αυτό το πεδίο δεν ήταν αναμενόμενο. This field is missing. Λείπει αυτό το πεδίο. This value is not a valid date. Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία. This value is not a valid datetime. Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία και ώρα. This value is not a valid email address. Η τιμή δεν αντιστοιχεί σε έγκυρο email. The file could not be found. Το αρχείο δε μπορεί να βρεθεί. The file is not readable. Το αρχείο δεν είναι αναγνώσιμο. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Το αρχείο είναι πολύ μεγάλο ({{ size }} {{ suffix }}). Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Ο τύπος mime του αρχείου δεν είναι έγκυρος ({{ type }}). Οι έγκρυοι τύποι mime είναι {{ types }}. This value should be {{ limit }} or less. Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή λιγότερο. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή λιγότερο.|Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή λιγότερο. This value should be {{ limit }} or more. Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή περισσότερο. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή περισσότερο.|Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή περισσότερο. This value should not be blank. Αυτή η τιμή δεν πρέπει να είναι κενή. This value should not be null. Αυτή η τιμή δεν πρέπει να είναι μηδενική. This value should be null. Αυτή η τιμή πρέπει να είναι μηδενική. This value is not valid. Αυτή η τιμή δεν είναι έκγυρη. This value is not a valid time. Αυτή η τιμή δεν αντιστοιχεί σε έγκυρη ώρα. This value is not a valid URL. Αυτή η τιμή δεν αντιστοιχεί σε έγκυρο URL. The two values should be equal. Οι δύο τιμές θα πρέπει να είναι ίδιες. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Το αρχείο είναι πολύ μεγάλο. Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}. The file is too large. Το αρχείο είναι πολύ μεγάλο. The file could not be uploaded. Το αρχείο δε μπορεί να ανέβει. This value should be a valid number. Αυτή η τιμή θα πρέπει να είναι ένας έγκυρος αριθμός. This file is not a valid image. Το αρχείο δεν αποτελεί έγκυρη εικόνα. This is not a valid IP address. Αυτό δεν είναι μια έκγυρη διεύθυνση IP. This value is not a valid language. Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη γλώσσα. This value is not a valid locale. Αυτή η τιμή δεν αντιστοιχεί σε έκγυρο κωδικό τοποθεσίας. This value is not a valid country. Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη χώρα. This value is already used. Αυτή η τιμή χρησιμοποιείται ήδη. The size of the image could not be detected. Το μέγεθος της εικόνας δεν ήταν δυνατό να ανιχνευθεί. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Το πλάτος της εικόνας είναι πολύ μεγάλο ({{ width }}px). Το μέγιστο επιτρεπτό πλάτος είναι {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Το πλάτος της εικόνας είναι πολύ μικρό ({{ width }}px). Το ελάχιστο επιτρεπτό πλάτος είναι {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Το ύψος της εικόνας είναι πολύ μεγάλο ({{ height }}px). Το μέγιστο επιτρεπτό ύψος είναι {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Το ύψος της εικόνας είναι πολύ μικρό ({{ height }}px). Το ελάχιστο επιτρεπτό ύψος είναι {{ min_height }}px. This value should be the user's current password. Αυτή η τιμή θα έπρεπε να είναι ο τρέχων κωδικός. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρα.|Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρες. The file was only partially uploaded. Το αρχείο δεν ανέβηκε ολόκληρο. No file was uploaded. Δεν ανέβηκε κανένα αρχείο. No temporary folder was configured in php.ini. Κανένας προσωρινός φάκελος δεν έχει ρυθμιστεί στο php.ini. Cannot write temporary file to disk. Αδυναμία εγγραφής προσωρινού αρχείου στο δίσκο. A PHP extension caused the upload to fail. Μια επέκταση PHP προκάλεσε αδυναμία ανεβάσματος. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείο ή περισσότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή περισσότερα. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείo ή λιγότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή λιγότερα. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχείo.|Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχεία. Invalid card number. Μη έγκυρος αριθμός κάρτας. Unsupported card type or invalid card number. Μη υποστηριζόμενος τύπος κάρτας ή μη έγκυρος αριθμός κάρτας. This is not a valid International Bank Account Number (IBAN). Αυτό δεν αντιστοιχεί σε έκγυρο διεθνή αριθμό τραπεζικού λογαριασμού (IBAN). This value is not a valid ISBN-10. Αυτό δεν είναι έγκυρος κωδικός ISBN-10. This value is not a valid ISBN-13. Αυτό δεν είναι έγκυρος κωδικός ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Αυτό δεν είναι ούτε έγκυρος κωδικός ISBN-10 ούτε έγκυρος κωδικός ISBN-13. This value is not a valid ISSN. Αυτό δεν είναι έγκυρος κωδικός ISSN. This value is not a valid currency. Αυτό δεν αντιστοιχεί σε έγκυρο νόμισμα. This value should be equal to {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι ίση με {{ compared_value }}. This value should be greater than {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη από {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη ή ίση με {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μικρότερη από {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Αυτή η τιμή θα πρέπει να είναι μικρότερη ή ίση με {{ compared_value }}. This value should not be equal to {{ compared_value }}. Αυτή η τιμή δεν θα πρέπει να είναι ίση με {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Αυτή η τιμή δεν πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}. This value should be false. Vrednost treba da bude netačna. This value should be true. Vrednost treba da bude tačna. This value should be of type {{ type }}. Vrednost treba da bude tipa {{ type }}. This value should be blank. Vrednost treba da bude prazna. The value you selected is not a valid choice. Vrednost treba da bude jedna od ponuđenih. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Izaberite bar {{ limit }} mogućnost.|Izaberite bar {{ limit }} mogućnosti.|Izaberite bar {{ limit }} mogućnosti. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Izaberite najviše {{ limit }} mogućnost.|Izaberite najviše {{ limit }} mogućnosti.|Izaberite najviše {{ limit }} mogućnosti. One or more of the given values is invalid. Jedna ili više vrednosti je nevalidna. This field was not expected. Ovo polje ne očekuje. This field is missing. Ovo polje nedostaje. This value is not a valid date. Vrednost nije validan datum. This value is not a valid datetime. Vrednost nije validan datum-vreme. This value is not a valid email address. Vrednost nije validna adresa elektronske pošte. The file could not be found. Datoteka ne može biti pronađena. The file is not readable. Datoteka nije čitljiva. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime tip datoteke nije validan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}. This value should be {{ limit }} or less. Vrednost treba da bude {{ limit }} ili manje. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Vrednost je predugačka. Treba da ima {{ limit }} karakter ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje. This value should be {{ limit }} or more. Vrednost treba da bude {{ limit }} ili više. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Vrednost je prekratka. Treba da ima {{ limit }} karakter ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više. This value should not be blank. Vrednost ne treba da bude prazna. This value should not be null. Vrednost ne treba da bude null. This value should be null. Vrednost treba da bude null. This value is not valid. Vrednost je nevalidna. This value is not a valid time. Vrednost nije validno vreme. This value is not a valid URL. Vrednost nije validan URL. The two values should be equal. Obe vrednosti treba da budu jednake. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}. The file is too large. Datoteka je prevelika. The file could not be uploaded. Datoteka ne može biti otpremljena. This value should be a valid number. Vrednost treba da bude validan broj. This file is not a valid image. Ova datoteka nije validna slika. This is not a valid IP address. Ovo nije validna IP adresa. This value is not a valid language. Vrednost nije validan jezik. This value is not a valid locale. Vrednost nije validan lokal. This value is not a valid country. Vrednost nije validna zemlja. This value is already used. Vrednost je već iskorišćena. The size of the image could not be detected. Veličina slike ne može biti određena. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Širina slike je prevelika ({{ width }}px). Najeća dozvoljena širina je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Visina slike je prevelika ({{ height }}px). Najeća dozvoljena visina je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px. This value should be the user's current password. Vrednost treba da bude trenutna korisnička lozinka. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Vrednost treba da ima tačno {{ limit }} karakter.|Vrednost treba da ima tačno {{ limit }} karaktera.|Vrednost treba da ima tačno {{ limit }} karaktera. The file was only partially uploaded. Datoteka je samo parcijalno otpremljena. No file was uploaded. Datoteka nije otpremljena. No temporary folder was configured in php.ini. Privremeni direktorijum nije konfigurisan u php.ini. Cannot write temporary file to disk. Nemoguće pisanje privremene datoteke na disk. A PHP extension caused the upload to fail. PHP ekstenzija je prouzrokovala neuspeh otpremanja datoteke. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ova kolekcija treba da sadrži tačno {{ limit }} element.|Ova kolekcija treba da sadrži tačno {{ limit }} elementa.|Ova kolekcija treba da sadrži tačno {{ limit }} elemenata. Invalid card number. Nevalidan broj kartice. Unsupported card type or invalid card number. Nevalidan broj kartice ili tip kartice nije podržan. This is not a valid International Bank Account Number (IBAN). Ovo nije validan međunarodni broj bankovnog računa (IBAN). This value is not a valid ISBN-10. Ovo nije validan ISBN-10. This value is not a valid ISBN-13. Ovo nije validan ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ovo nije validan ISBN-10 ili ISBN-13. This value is not a valid ISSN. Ovo nije validan ISSN. This value is not a valid currency. Ovo nije validna valuta. This value should be equal to {{ compared_value }}. Ova vrednost treba da bude {{ compared_value }}. This value should be greater than {{ compared_value }}. Ova vrednost treba da bude veća od {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ova vrednost treba da bude veća ili jednaka {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ova vrednost treba da bude identična sa {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Ova vrednost treba da bude manja od {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ova vrednost treba da bude manja ili jednaka {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ova vrednost ne treba da bude jednaka {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ova vrednost ne treba da bude identična sa {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Razmera ove slike je prevelika ({{ ratio }}). Maksimalna dozvoljena razmera je {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Razmera ove slike je premala ({{ ratio }}). Minimalna očekivana razmera je {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. Slika je kvadratna ({{ width }}x{{ height }}px). Kvadratne slike nisu dozvoljene. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. Slika je orijentacije pejzaža ({{ width }}x{{ height }}px). Pejzažna orijentacija slika nije dozvoljena. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. Slika je orijantacije portreta ({{ width }}x{{ height }}px). Portretna orijentacija slika nije dozvoljena.  This value should be false. Значення повинно бути Ні. This value should be true. Значення повинно бути Так. This value should be of type {{ type }}. Тип значення повинен бути {{ type }}. This value should be blank. Значення повинно бути пустим. The value you selected is not a valid choice. Обране вами значення недопустиме. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Ви повинні обрати хоча б {{ limit }} варіант.|Ви повинні обрати хоча б {{ limit }} варіанти.|Ви повинні обрати хоча б {{ limit }} варіантів. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Ви повинні обрати не більше ніж {{ limit }} варіантів. One or more of the given values is invalid. Одне або кілька заданих значень є недопустимі. This field was not expected. Це поле не очікується. This field is missing. Це поле не вистачає. This value is not a valid date. Дане значення не є вірною датою. This value is not a valid datetime. Дане значення дати та часу недопустиме. This value is not a valid email address. Значення адреси электронної пошти недопустиме. The file could not be found. Файл не знайдено. The file is not readable. Файл не читається. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файл занадто великий ({{ size }} {{ suffix }}). Дозволений максимальний розмір {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. MIME-тип файлу недопустимий ({{ type }}). Допустимі MIME-типи файлів {{ types }}. This value should be {{ limit }} or less. Значення повинно бути {{ limit }} або менше. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Значення занадто довге. Повинно бути рівне {{ limit }} символу або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше. This value should be {{ limit }} or more. Значення повинно бути {{ limit }} або більше. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Значення занадто коротке. Повинно бути рівне {{ limit }} символу або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше. This value should not be blank. Значення не повинно бути пустим. This value should not be null. Значення не повинно бути null. This value should be null. Значення повинно бути null. This value is not valid. Значення недопустиме. This value is not a valid time. Значення часу недопустиме. This value is not a valid URL. Значення URL недопустиме. The two values should be equal. Обидва занчення повинні бути одинаковими. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файл занадто великий. Максимальний допустимий розмір {{ limit }} {{ suffix }}. The file is too large. Файл занадто великий. The file could not be uploaded. Файл не можливо завантажити. This value should be a valid number. Значення має бути допустимим числом. This file is not a valid image. Цей файл не є допустимим форматом зображення. This is not a valid IP address. Це некоректна IP адреса. This value is not a valid language. Це некоректна мова. This value is not a valid locale. Це некоректна локалізація. This value is not a valid country. Це некоректна країна. This value is already used. Це значення вже використовується. The size of the image could not be detected. Не вдалося визначити розмір зображення. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Ширина зображення занадто велика ({{ width }}px). Максимально допустима ширина {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Ширина зображення занадто мала ({{ width }}px). Мінімально допустима ширина {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Висота зображення занадто велика ({{ height }}px). Максимально допустима висота {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Висота зображення занадто мала ({{ height }}px). Мінімально допустима висота {{ min_height }}px. This value should be the user's current password. Значення має бути поточним паролем користувача. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Значення повиино бути рівним {{ limit }} символу.|Значення повиино бути рівним {{ limit }} символам.|Значення повиино бути рівним {{ limit }} символам. The file was only partially uploaded. Файл був завантажений лише частково. No file was uploaded. Файл не був завантажений. No temporary folder was configured in php.ini. Не налаштована тимчасова директорія в php.ini. Cannot write temporary file to disk. Неможливо записати тимчасовий файл на диск. A PHP extension caused the upload to fail. Розширення PHP викликало помилку при завантаженні. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ця колекція повинна містити {{ limit }} елемент чи більше.|Ця колекція повинна містити {{ limit }} елемента чи більше.|Ця колекція повинна містити {{ limit }} елементів чи більше. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ця колекція повинна містити {{ limit }} елемент чи менше.|Ця колекція повинна містити {{ limit }} елемента чи менше.|Ця колекція повинна містити {{ limit }} елементов чи менше. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ця колекція повинна містити рівно {{ limit }} елемент.|Ця колекція повинна містити рівно {{ limit }} елемента.|Ця колекція повинна містити рівно {{ limit }} елементів. Invalid card number. Невірний номер карти. Unsupported card type or invalid card number. Непідтримуваний тип карти або невірний номер карти. This is not a valid International Bank Account Number (IBAN). Це не дійсний міжнародний номер банківського рахунку (IBAN). This value is not a valid ISBN-10. Значення не у форматі ISBN-10. This value is not a valid ISBN-13. Значення не у форматі ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Значення не відповідає форматам ISBN-10 та ISBN-13. This value is not a valid ISSN. Значення має невірний формат ISSN. This value is not a valid currency. Значення має невірний формат валюти. This value should be equal to {{ compared_value }}. Значення повинно дорівнювати {{ compared_value }}. This value should be greater than {{ compared_value }}. Значення має бути більше ніж {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Значення має бути більше або дорівнювати {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Значення має бути ідентичним {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Значення повинно бути менше ніж {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Значення повинно бути менше або дорівнювати {{ compared_value }}. This value should not be equal to {{ compared_value }}. Значення не повинно дорівнювати {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Значення не повинно бути ідентичним {{ compared_value_type }} {{ compared_value }}. This value should be false. Värdet ska vara falskt. This value should be true. Värdet ska vara sant. This value should be of type {{ type }}. Värdet ska vara av typen {{ type }}. This value should be blank. Värdet ska vara tomt. The value you selected is not a valid choice. Värdet ska vara ett av de givna valen. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Du måste välja minst {{ limit }} val.|Du måste välja minst {{ limit }} val. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Du kan som mest välja {{ limit }} val.|Du kan som mest välja {{ limit }} val. One or more of the given values is invalid. Ett eller fler av de angivna värdena är ogiltigt. This field was not expected. Det här fältet förväntades inte. This field is missing. Det här fältet saknas. This value is not a valid date. Värdet är inte ett giltigt datum. This value is not a valid datetime. Värdet är inte ett giltigt datum med tid. This value is not a valid email address. Värdet är inte en giltig epost-adress. The file could not be found. Filen kunde inte hittas. The file is not readable. Filen är inte läsbar. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Filen är för stor ({{ size }} {{ suffix }}). Största tillåtna storlek är {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Filens MIME-typ ({{ type }}) är ogiltig. De tillåtna typerna är {{ types }}. This value should be {{ limit }} or less. Värdet ska vara {{ limit }} eller mindre. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Värdet är för långt. Det ska ha {{ limit }} tecken eller färre.|Värdet är för långt. Det ska ha {{ limit }} tecken eller färre. This value should be {{ limit }} or more. Värdet ska vara {{ limit }} eller mer. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Värdet är för kort. Det ska ha {{ limit }} tecken eller mer.|Värdet är för kort. Det ska ha {{ limit }} tecken eller mer. This value should not be blank. Värdet kan inte vara tomt. This value should not be null. Värdet kan inte vara null. This value should be null. Värdet ska vara null. This value is not valid. Värdet är inte giltigt. This value is not a valid time. Värdet är inte en giltig tid. This value is not a valid URL. Värdet är inte en giltig URL. The two values should be equal. De två värdena måste vara lika. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Filen är för stor. Tillåten maximal storlek är {{ limit }} {{ suffix }}. The file is too large. Filen är för stor. The file could not be uploaded. Filen kunde inte laddas upp. This value should be a valid number. Värdet ska vara ett giltigt nummer. This file is not a valid image. Filen är ingen giltig bild. This is not a valid IP address. Det här är inte en giltig IP-adress. This value is not a valid language. Värdet är inte ett giltigt språk. This value is not a valid locale. Värdet är inte en giltig plats. This value is not a valid country. Värdet är inte ett giltigt land. This value is already used. Värdet används redan. The size of the image could not be detected. Det gick inte att fastställa storleken på bilden. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Bildens bredd är för stor ({{ width }}px). Tillåten maximal bredd är {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Bildens bredd är för liten ({{ width }}px). Minsta förväntade bredd är {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Bildens höjd är för stor ({{ height }}px). Tillåten maximal bredd är {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Bildens höjd är för liten ({{ height }}px). Minsta förväntade höjd är {{ min_height }}px. This value should be the user's current password. Värdet ska vara användarens nuvarande lösenord. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Värdet ska ha exakt {{ limit }} tecken.|Värdet ska ha exakt {{ limit }} tecken. The file was only partially uploaded. Filen laddades bara upp delvis. No file was uploaded. Ingen fil laddades upp. No temporary folder was configured in php.ini. Det finns ingen temporär mapp konfigurerad i php.ini. Cannot write temporary file to disk. Kan inte skriva temporär fil till disken. A PHP extension caused the upload to fail. En PHP extension gjorde att uppladdningen misslyckades. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Den här samlingen ska innehålla {{ limit }} element eller mer.|Den här samlingen ska innehålla {{ limit }} element eller mer. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Den här samlingen ska innehålla {{ limit }} element eller mindre.|Den här samlingen ska innehålla {{ limit }} element eller mindre. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Den här samlingen ska innehålla exakt {{ limit }} element.|Den här samlingen ska innehålla exakt {{ limit }} element. Invalid card number. Ogiltigt kortnummer. Unsupported card type or invalid card number. Okänd korttyp eller ogiltigt kortnummer. This is not a valid International Bank Account Number (IBAN). Det här är inte en giltig International Bank Account Number (IBANK). This value is not a valid ISBN-10. Värdet är inte en giltig ISBN-10. This value is not a valid ISBN-13. Värdet är inte en giltig ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Värdet är varken en giltig ISBN-10 eller en giltig ISBN-13. This value is not a valid ISSN. Värdet är inte en giltig ISSN. This value is not a valid currency. Värdet är inte en giltig valuta. This value should be equal to {{ compared_value }}. Värdet ska vara detsamma som {{ compared_value }}. This value should be greater than {{ compared_value }}. Värdet ska vara större än {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Värdet ska bara större än eller detsamma som {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Värdet ska vara identiskt till {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Värdet ska vara mindre än {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Värdet ska vara mindre än eller detsamma som {{ compared_value }}. This value should not be equal to {{ compared_value }}. Värdet ska inte vara detsamma som {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Värdet ska inte vara identiskt med {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Förhållandet mellan bildens bredd och höjd är för stort ({{ ratio }}). Högsta tillåtna förhållande är {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Förhållandet mellan bildens bredd och höjd är för litet ({{ ratio }}). Minsta tillåtna förhållande är {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. Bilden är kvadratisk ({{ width }}x{{ height }}px). Kvadratiska bilder tillåts inte. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. Bilden är landskapsorienterad ({{ width }}x{{ height }}px). Landskapsorienterade bilder tillåts inte. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. Bilden är porträttsorienterad ({{ width }}x{{ height }}px). Porträttsorienterade bilder tillåts inte. An empty file is not allowed. En tom fil är inte tillåten. This value should be false. Hierdie waarde moet vals wees. This value should be true. Hierdie waarde moet waar wees. This value should be of type {{ type }}. Hierdie waarde moet van die soort {{type}} wees. This value should be blank. Hierdie waarde moet leeg wees. The value you selected is not a valid choice. Die waarde wat jy gekies het is nie 'n geldige keuse nie. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Jy moet ten minste {{ limit }} kies.|Jy moet ten minste {{ limit }} keuses kies. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Jy moet by die meeste {{ limit }} keuse kies.|Jy moet by die meeste {{ limit }} keuses kies. One or more of the given values is invalid. Een of meer van die gegewe waardes is ongeldig. This field was not expected. Die veld is nie verwag nie. This field is missing. Hierdie veld ontbreek. This value is not a valid date. Hierdie waarde is nie 'n geldige datum nie. This value is not a valid datetime. Hierdie waarde is nie 'n geldige datum en tyd nie. This value is not a valid email address. Hierdie waarde is nie 'n geldige e-pos adres nie. The file could not be found. Die lêer kon nie gevind word nie. The file is not readable. Die lêer kan nie gelees word nie. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Die lêer is te groot ({{ size }} {{ suffix }}). Toegelaat maksimum grootte is {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Die MIME-tipe van die lêer is ongeldig ({{ type }}). Toegelaat MIME-tipes is {{ types }}. This value should be {{ limit }} or less. Hierdie waarde moet {{ limit }} of minder wees. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Hierdie waarde is te lank. Dit moet {{ limit }} karakter of minder wees.|Hierdie waarde is te lank. Dit moet {{ limit }} karakters of minder wees. This value should be {{ limit }} or more. Hierdie waarde moet {{ limit }} of meer wees. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Hierdie waarde is te kort. Dit moet {{ limit }} karakter of meer wees.|Hierdie waarde is te kort. Dit moet {{ limit }} karakters of meer wees. This value should not be blank. Hierdie waarde moet nie leeg wees nie. This value should not be null. Hierdie waarde moet nie nul wees nie. This value should be null. Hierdie waarde moet nul wees. This value is not valid. Hierdie waarde is nie geldig nie. This value is not a valid time. Hierdie waarde is nie 'n geldige tyd nie. This value is not a valid URL. Hierdie waarde is nie 'n geldige URL nie. The two values should be equal. Die twee waardes moet gelyk wees. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Die lêer is te groot. Toegelaat maksimum grootte is {{ limit }} {{ suffix }}. The file is too large. Die lêer is te groot. The file could not be uploaded. Die lêer kan nie opgelaai word nie. This value should be a valid number. Hierdie waarde moet 'n geldige nommer wees. This file is not a valid image. Hierdie lêer is nie 'n geldige beeld nie. This is not a valid IP address. Hierdie is nie 'n geldige IP-adres nie. This value is not a valid language. Hierdie waarde is nie 'n geldige taal nie. This value is not a valid locale. Hierdie waarde is nie 'n geldige land instelling nie. This value is not a valid country. Hierdie waarde is nie 'n geldige land nie. This value is already used. Hierdie waarde word reeds gebruik. The size of the image could not be detected. Die grootte van die beeld kon nie opgespoor word nie. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Die beeld breedte is te groot ({{ width }}px). Toegelaat maksimum breedte is {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Die beeld breedte is te klein ({{ width }}px). Minimum breedte verwag is {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Die beeld hoogte is te groot ({{ height }}px). Toegelaat maksimum hoogte is {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Die beeld hoogte is te klein ({{ height }}px). Minimum hoogte verwag is {{ min_height }}px. This value should be the user's current password. Hierdie waarde moet die huidige wagwoord van die gebruiker wees. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Hierdie waarde moet presies {{ limit }} karakter wees.|Hierdie waarde moet presies {{ limit }} karakters wees. The file was only partially uploaded. Die lêer is slegs gedeeltelik opgelaai. No file was uploaded. Geen lêer is opgelaai nie. No temporary folder was configured in php.ini. Geen tydelike lêer is ingestel in php.ini nie. Cannot write temporary file to disk. Kan nie tydelike lêer skryf op skyf nie. A PHP extension caused the upload to fail. 'n PHP-uitbreiding veroorsaak die oplaai van die lêer om te misluk. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Hierdie versameling moet {{ limit }} element of meer bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Hierdie versameling moet {{ limit }} element of minder bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Hierdie versameling moet presies {{ limit }} element bevat.|Hierdie versameling moet presies {{ limit }} elemente bevat. Invalid card number. Ongeldige kredietkaart nommer. Unsupported card type or invalid card number. Nie-ondersteunde tipe kaart of ongeldige kredietkaart nommer. This value should be false. Arvon tulee olla epätosi. This value should be true. Arvon tulee olla tosi. This value should be of type {{ type }}. Arvon tulee olla tyyppiä {{ type }}. This value should be blank. Arvon tulee olla tyhjä. The value you selected is not a valid choice. Arvon tulee olla yksi annetuista vaihtoehdoista. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Sinun tulee valita vähintään {{ limit }} vaihtoehtoa. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Sinun tulee valitan enintään {{ limit }} vaihtoehtoa. One or more of the given values is invalid. Yksi tai useampi annetuista arvoista on virheellinen. This field was not expected. Tässä kentässä ei odotettu. This field is missing. Tämä kenttä puuttuu. This value is not a valid date. Annettu arvo ei ole kelvollinen päivämäärä. This value is not a valid datetime. Annettu arvo ei ole kelvollinen päivämäärä ja kellonaika. This value is not a valid email address. Annettu arvo ei ole kelvollinen sähköpostiosoite. The file could not be found. Tiedostoa ei löydy. The file is not readable. Tiedostoa ei voida lukea. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Tiedostonkoko ({{ size }} {{ suffix }}) on liian iso. Suurin sallittu tiedostonkoko on {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Tiedostotyyppi ({{ type }}) on virheellinen. Sallittuja tiedostotyyppejä ovat {{ types }}. This value should be {{ limit }} or less. Arvon tulee olla {{ limit }} tai vähemmän. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Liian pitkä syöte. Syöte saa olla enintään {{ limit }} merkkiä. This value should be {{ limit }} or more. Arvon tulee olla {{ limit }} tai enemmän. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Liian lyhyt syöte. Syötteen tulee olla vähintään {{ limit }} merkkiä. This value should not be blank. Kenttä ei voi olla tyhjä. This value should not be null. Syöte ei voi olla null. This value should be null. Syötteen tulee olla null. This value is not valid. Virheellinen arvo. This value is not a valid time. Annettu arvo ei ole kelvollinen kellonaika. This value is not a valid URL. Annettu arvo ei ole kelvollinen URL-osoite. The two values should be equal. Kahden annetun arvon tulee olla samat. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Annettu tiedosto on liian iso. Suurin sallittu tiedostokoko on {{ limit }} {{ suffix }}. The file is too large. Tiedosto on liian iso. The file could not be uploaded. Tiedoston siirto epäonnistui. This value should be a valid number. Tämän arvon tulee olla numero. This file is not a valid image. Tämä tiedosto ei ole kelvollinen kuva. This is not a valid IP address. Tämä ei ole kelvollinen IP-osoite. This value is not a valid language. Tämä arvo ei ole kelvollinen kieli. This value is not a valid locale. Tämä arvo ei ole kelvollinen kieli- ja alueasetus (locale). This value is not a valid country. Tämä arvo ei ole kelvollinen maa. This value is already used. Tämä arvo on jo käytetty. The size of the image could not be detected. Kuvan kokoa ei voitu tunnistaa. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Kuva on liian leveä ({{ width }}px). Sallittu maksimileveys on {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Kuva on liian kapea ({{ width }}px). Leveyden tulisi olla vähintään {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Kuva on liian korkea ({{ width }}px). Sallittu maksimikorkeus on {{ max_width }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Kuva on liian matala ({{ height }}px). Korkeuden tulisi olla vähintään {{ min_height }}px. This value should be the user's current password. Tämän arvon tulisi olla käyttäjän tämänhetkinen salasana. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Tämän arvon tulisi olla tasan yhden merkin pituinen.|Tämän arvon tulisi olla tasan {{ limit }} merkkiä pitkä. The file was only partially uploaded. Tiedosto ladattiin vain osittain. No file was uploaded. Tiedostoa ei ladattu. No temporary folder was configured in php.ini. Väliaikaishakemistoa ei ole asetettu php.ini -tiedostoon. Cannot write temporary file to disk. Väliaikaistiedostoa ei voitu kirjoittaa levylle. A PHP extension caused the upload to fail. PHP-laajennoksen vuoksi tiedoston lataus epäonnistui. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Tässä ryhmässä tulisi olla yksi tai useampi elementti.|Tässä ryhmässä tulisi olla vähintään {{ limit }} elementtiä. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Tässä ryhmässä tulisi olla enintään yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Tässä ryhmässä tulisi olla tasan yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä. Invalid card number. Virheellinen korttinumero. Unsupported card type or invalid card number. Tätä korttityyppiä ei tueta tai korttinumero on virheellinen. This value should be false. Ta wartość powinna być fałszem. This value should be true. Ta wartość powinna być prawdą. This value should be of type {{ type }}. Ta wartość powinna być typu {{ type }}. This value should be blank. Ta wartość powinna być pusta. The value you selected is not a valid choice. Ta wartość powinna być jedną z podanych opcji. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Powinieneś wybrać co najmniej {{ limit }} opcję.|Powinieneś wybrać co najmniej {{ limit }} opcje.|Powinieneś wybrać co najmniej {{ limit }} opcji. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Powinieneś wybrać maksymalnie {{ limit }} opcję.|Powinieneś wybrać maksymalnie {{ limit }} opcje.|Powinieneś wybrać maksymalnie {{ limit }} opcji. One or more of the given values is invalid. Jedna lub więcej z podanych wartości jest nieprawidłowa. This field was not expected. To pole nie spodziewano. This field is missing. To pole jest chybianie. This value is not a valid date. Ta wartość nie jest prawidłową datą. This value is not a valid datetime. Ta wartość nie jest prawidłową datą i czasem. This value is not a valid email address. Ta wartość nie jest prawidłowym adresem email. The file could not be found. Plik nie mógł zostać odnaleziony. The file is not readable. Nie można odczytać pliku. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Plik jest za duży ({{ size }} {{ suffix }}). Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Nieprawidłowy typ mime pliku ({{ type }}). Dozwolone typy mime to {{ types }}. This value should be {{ limit }} or less. Ta wartość powinna wynosić {{ limit }} lub mniej. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków. This value should be {{ limit }} or more. Ta wartość powinna wynosić {{ limit }} lub więcej. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków. This value should not be blank. Ta wartość nie powinna być pusta. This value should not be null. Ta wartość nie powinna być nullem. This value should be null. Ta wartość powinna być nullem. This value is not valid. Ta wartość jest nieprawidłowa. This value is not a valid time. Ta wartość nie jest prawidłowym czasem. This value is not a valid URL. Ta wartość nie jest prawidłowym adresem URL. The two values should be equal. Obie wartości powinny być równe. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Plik jest za duży. Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}. The file is too large. Plik jest za duży. The file could not be uploaded. Plik nie mógł być wgrany. This value should be a valid number. Ta wartość powinna być prawidłową liczbą. This file is not a valid image. Ten plik nie jest obrazem. This is not a valid IP address. To nie jest prawidłowy adres IP. This value is not a valid language. Ta wartość nie jest prawidłowym językiem. This value is not a valid locale. Ta wartość nie jest prawidłową lokalizacją. This value is not a valid country. Ta wartość nie jest prawidłową nazwą kraju. This value is already used. Ta wartość jest już wykorzystywana. The size of the image could not be detected. Nie można wykryć rozmiaru obrazka. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Szerokość obrazka jest zbyt duża ({{ width }}px). Maksymalna dopuszczalna szerokość to {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Szerokość obrazka jest zbyt mała ({{ width }}px). Oczekiwana minimalna szerokość to {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Wysokość obrazka jest zbyt duża ({{ height }}px). Maksymalna dopuszczalna wysokość to {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Wysokość obrazka jest zbyt mała ({{ height }}px). Oczekiwana minimalna wysokość to {{ min_height }}px. This value should be the user's current password. Ta wartość powinna być aktualnym hasłem użytkownika. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Ta wartość powinna mieć dokładnie {{ limit }} znak.|Ta wartość powinna mieć dokładnie {{ limit }} znaki.|Ta wartość powinna mieć dokładnie {{ limit }} znaków. The file was only partially uploaded. Plik został wgrany tylko częściowo. No file was uploaded. Żaden plik nie został wgrany. No temporary folder was configured in php.ini. Nie skonfigurowano folderu tymczasowego w php.ini. Cannot write temporary file to disk. Nie można zapisać pliku tymczasowego na dysku. A PHP extension caused the upload to fail. Rozszerzenie PHP spowodowało błąd podczas wgrywania. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Ten zbiór powinien zawierać {{ limit }} lub więcej elementów. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Ten zbiór powinien zawierać {{ limit }} lub mniej elementów. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Ten zbiór powinien zawierać dokładnie {{ limit }} element.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementy.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementów. Invalid card number. Nieprawidłowy numer karty. Unsupported card type or invalid card number. Nieobsługiwany rodzaj karty lub nieprawidłowy numer karty. This is not a valid International Bank Account Number (IBAN). Nieprawidłowy międzynarodowy numer rachunku bankowego (IBAN). This value is not a valid ISBN-10. Ta wartość nie jest prawidłowym numerem ISBN-10. This value is not a valid ISBN-13. Ta wartość nie jest prawidłowym numerem ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Ta wartość nie jest prawidłowym numerem ISBN-10 ani ISBN-13. This value is not a valid ISSN. Ta wartość nie jest prawidłowym numerem ISSN. This value is not a valid currency. Ta wartość nie jest prawidłową walutą. This value should be equal to {{ compared_value }}. Ta wartość powinna być równa {{ compared_value }}. This value should be greater than {{ compared_value }}. Ta wartość powinna być większa niż {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Ta wartość powinna być większa bądź równa {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Ta wartość powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}. This value should be less than {{ compared_value }}. Ta wartość powinna być mniejsza niż {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Ta wartość powinna być mniejsza bądź równa {{ compared_value }}. This value should not be equal to {{ compared_value }}. Ta wartość nie powinna być równa {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Ta wartość nie powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Proporcje obrazu są zbyt duże ({{ ratio }}). Maksymalne proporcje to {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Proporcje obrazu są zbyt małe ({{ ratio }}). Minimalne proporcje to {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. Obraz jest kwadratem ({{ width }}x{{ height }}px). Kwadratowe obrazy nie są akceptowane. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. Obraz jest panoramiczny ({{ width }}x{{ height }}px). Panoramiczne zdjęcia nie są akceptowane. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. Obraz jest portretowy ({{ width }}x{{ height }}px). Portretowe zdjęcia nie są akceptowane. An empty file is not allowed. Plik nie może być pusty. This value does not match the expected {{ charset }} charset. Ta wartość nie pasuje do oczekiwanego zestawu znaków {{ charset }}. This value should be false. Questo valore dovrebbe essere falso. This value should be true. Questo valore dovrebbe essere vero. This value should be of type {{ type }}. Questo valore dovrebbe essere di tipo {{ type }}. This value should be blank. Questo valore dovrebbe essere vuoto. The value you selected is not a valid choice. Questo valore dovrebbe essere una delle opzioni disponibili. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Si dovrebbe selezionare almeno {{ limit }} opzione.|Si dovrebbero selezionare almeno {{ limit }} opzioni. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Si dovrebbe selezionare al massimo {{ limit }} opzione.|Si dovrebbero selezionare al massimo {{ limit }} opzioni. One or more of the given values is invalid. Uno o più valori inseriti non sono validi. This field was not expected. Questo campo non è stato previsto. This field is missing. Questo campo è mancante. This value is not a valid date. Questo valore non è una data valida. This value is not a valid datetime. Questo valore non è una data e ora valida. This value is not a valid email address. Questo valore non è un indirizzo email valido. The file could not be found. Non è stato possibile trovare il file. The file is not readable. Il file non è leggibile. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Il file è troppo grande ({{ size }} {{ suffix }}). La dimensione massima consentita è {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Il mime type del file non è valido ({{ type }}). I tipi permessi sono {{ types }}. This value should be {{ limit }} or less. Questo valore dovrebbe essere {{ limit }} o inferiore. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} carattere.|Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} caratteri. This value should be {{ limit }} or more. Questo valore dovrebbe essere {{ limit }} o superiore. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} carattere.|Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} caratteri. This value should not be blank. Questo valore non dovrebbe essere vuoto. This value should not be null. Questo valore non dovrebbe essere nullo. This value should be null. Questo valore dovrebbe essere nullo. This value is not valid. Questo valore non è valido. This value is not a valid time. Questo valore non è un'ora valida. This value is not a valid URL. Questo valore non è un URL valido. The two values should be equal. I due valori dovrebbero essere uguali. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Il file è troppo grande. La dimensione massima è {{ limit }} {{ suffix }}. The file is too large. Il file è troppo grande. The file could not be uploaded. Il file non può essere caricato. This value should be a valid number. Questo valore dovrebbe essere un numero. This file is not a valid image. Questo file non è una immagine valida. This is not a valid IP address. Questo valore non è un indirizzo IP valido. This value is not a valid language. Questo valore non è una lingua valida. This value is not a valid locale. Questo valore non è una impostazione regionale valida. This value is not a valid country. Questo valore non è una nazione valida. This value is already used. Questo valore è già stato utilizzato. The size of the image could not be detected. La dimensione dell'immagine non può essere determinata. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. La larghezza dell'immagine è troppo grande ({{ width }}px). La larghezza massima è di {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. La larghezza dell'immagine è troppo piccola ({{ width }}px). La larghezza minima è di {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. L'altezza dell'immagine è troppo grande ({{ height }}px). L'altezza massima è di {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. L'altezza dell'immagine è troppo piccola ({{ height }}px). L'altezza minima è di {{ min_height }}px. This value should be the user's current password. Questo valore dovrebbe essere la password attuale dell'utente. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Questo valore dovrebbe contenere esattamente {{ limit }} carattere.|Questo valore dovrebbe contenere esattamente {{ limit }} caratteri. The file was only partially uploaded. Il file è stato caricato solo parzialmente. No file was uploaded. Nessun file è stato caricato. No temporary folder was configured in php.ini. Nessuna cartella temporanea è stata configurata nel php.ini. Cannot write temporary file to disk. Impossibile scrivere il file temporaneo sul disco. A PHP extension caused the upload to fail. Un'estensione PHP ha causato il fallimento del caricamento. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Questa collezione dovrebbe contenere almeno {{ limit }} elemento.|Questa collezione dovrebbe contenere almeno {{ limit }} elementi. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Questa collezione dovrebbe contenere massimo {{ limit }} elemento.|Questa collezione dovrebbe contenere massimo {{ limit }} elementi. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Questa collezione dovrebbe contenere esattamente {{ limit }} elemento.|Questa collezione dovrebbe contenere esattamente {{ limit }} elementi. Invalid card number. Numero di carta non valido. Unsupported card type or invalid card number. Tipo di carta non supportato o numero non valido. This is not a valid International Bank Account Number (IBAN). Questo valore non è un IBAN (International Bank Account Number) valido. This value is not a valid ISBN-10. Questo valore non è un codice ISBN-10 valido. This value is not a valid ISBN-13. Questo valore non è un codice ISBN-13 valido. This value is neither a valid ISBN-10 nor a valid ISBN-13. Questo valore non è un codice ISBN-10 o ISBN-13 valido. This value is not a valid ISSN. Questo valore non è un codice ISSN valido. This value is not a valid currency. Questo valore non è una valuta valida. This value should be equal to {{ compared_value }}. Questo valore dovrebbe essere uguale a {{ compared_value }}. This value should be greater than {{ compared_value }}. Questo valore dovrebbe essere maggiore di {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Questo valore dovrebbe essere maggiore o uguale a {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Questo valore dovrebbe essere identico a {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Questo valore dovrebbe essere minore di {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Questo valore dovrebbe essere minore o uguale a {{ compared_value }}. This value should not be equal to {{ compared_value }}. Questo valore dovrebbe essere diverso da {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Questo valore dovrebbe essere diverso da {{ compared_value_type }} {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Il rapporto di aspetto dell'immagine è troppo grande ({{ ratio }}). Il rapporto massimo consentito è {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Il rapporto di aspetto dell'immagine è troppo piccolo ({{ ratio }}). Il rapporto minimo consentito è {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. L'immagine è quadrata ({{ width }}x{{ height }}px). Le immagini quadrate non sono consentite. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. L'immagine è orizzontale ({{ width }}x{{ height }}px). Le immagini orizzontali non sono consentite. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. L'immagine è verticale ({{ width }}x{{ height }}px). Le immagini verticali non sono consentite. An empty file is not allowed. Un file vuoto non è consentito. This value should be false. Väärtus peaks olema väär. This value should be true. Väärtus peaks oleme tõene. This value should be of type {{ type }}. Väärtus peaks olema {{ type }}-tüüpi. This value should be blank. Väärtus peaks olema tühi. The value you selected is not a valid choice. Väärtus peaks olema üks etteantud valikutest. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Valima peaks vähemalt {{ limit }} valikut. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Valima peaks mitte rohkem kui {{ limit }} valikut. One or more of the given values is invalid. One or more of the given values is invalid. This field was not expected. See väli ei oodatud. This field is missing. See väli on puudu. This value is not a valid date. Väärtus pole korrektne kuupäev. This value is not a valid datetime. Väärtus pole korrektne kuupäev ja kellaeg. This value is not a valid email address. Väärtus pole korrektne e-maili aadress. The file could not be found. Faili ei leita. The file is not readable. Fail ei ole loetav. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fail on liiga suur ({{ size }} {{ suffix }}). Suurim lubatud suurus on {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Faili sisutüüp on vigane ({{ type }}). Lubatud sisutüübid on {{ types }}. This value should be {{ limit }} or less. Väärtus peaks olema {{ limit }} või vähem. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Väärtus on liiga pikk. Pikkus peaks olema {{ limit }} tähemärki või vähem. This value should be {{ limit }} or more. Väärtus peaks olema {{ limit }} või rohkem. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Väärtus on liiga lühike. Pikkus peaks olema {{ limit }} tähemärki või rohkem. This value should not be blank. Väärtus ei tohiks olla tühi. This value should not be null. Väärtus ei tohiks olla 'null'. This value should be null. Väärtus peaks olema 'null'. This value is not valid. Väärtus on vigane. This value is not a valid time. Väärtus pole korrektne aeg. This value is not a valid URL. Väärtus pole korrektne URL. The two values should be equal. Väärtused peaksid olema võrdsed. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fail on liiga suur. Maksimaalne lubatud suurus on {{ limit }} {{ suffix }}. The file is too large. Fail on liiga suur. The file could not be uploaded. Faili ei saa üles laadida. This value should be a valid number. Väärtus peaks olema korrektne number. This file is not a valid image. Fail ei ole korrektne pilt. This is not a valid IP address. IP aadress pole korrektne. This value is not a valid language. Väärtus pole korrektne keel. This value is not a valid locale. Väärtus pole korrektne asukohakeel. This value is not a valid country. Väärtus pole olemasolev riik. This value is already used. Väärtust on juba kasutatud. The size of the image could not be detected. Pildi suurust polnud võimalik tuvastada. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Pilt on liiga lai ({{ width }}px). Suurim lubatud laius on {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Pilt on liiga kitsas ({{ width }}px). Vähim lubatud laius on {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Pilt on liiga pikk ({{ height }}px). Lubatud suurim pikkus on {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Pilt pole piisavalt pikk ({{ height }}px). Lubatud vähim pikkus on {{ min_height }}px. This value should be the user's current password. Väärtus peaks olema kasutaja kehtiv salasõna. This value should have exactly {{ limit }} characters. Väärtus peaks olema täpselt {{ limit }} tähemärk pikk.|Väärtus peaks olema täpselt {{ limit }} tähemärki pikk. The file was only partially uploaded. Fail ei laetud täielikult üles. No file was uploaded. Ühtegi faili ei laetud üles. No temporary folder was configured in php.ini. Ühtegi ajutist kausta polnud php.ini-s seadistatud. Cannot write temporary file to disk. Ajutist faili ei saa kettale kirjutada. A PHP extension caused the upload to fail. PHP laiendi tõttu ebaõnnestus faili üleslaadimine. This collection should contain {{ limit }} elements or more. Kogumikus peaks olema vähemalt {{ limit }} element.|Kogumikus peaks olema vähemalt {{ limit }} elementi. This collection should contain {{ limit }} elements or less. Kogumikus peaks olema ülimalt {{ limit }} element.|Kogumikus peaks olema ülimalt {{ limit }} elementi. This collection should contain exactly {{ limit }} elements. Kogumikus peaks olema täpselt {{ limit }} element.|Kogumikus peaks olema täpselt {{ limit }}|elementi. Invalid card number. Vigane kaardi number. Unsupported card type or invalid card number. Kaardi tüüpi ei toetata või kaardi number on vigane. This is not a valid International Bank Account Number (IBAN). Väärtus pole korrektne IBAN-number. This value is not a valid ISBN-10. Väärtus pole korrektne ISBN-10. This value is not a valid ISBN-13. Väärtus pole korrektne ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Väärtus pole korrektne ISBN-10 ega ISBN-13. This value is not a valid ISSN. Väärtus pole korrektne ISSN. This value is not a valid currency. Väärtus pole korrektne valuuta. This value should be equal to {{ compared_value }}. Väärtus peaks olema võrdne {{ compared_value }}-ga. This value should be greater than {{ compared_value }}. Väärtus peaks olema suurem kui {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Väärtus peaks olema suurem kui või võrduma {{ compared_value }}-ga. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Väärtus peaks olema identne väärtusega {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Väärtus peaks olema väiksem kui {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Väärtus peaks olema väiksem kui või võrduma {{ compared_value }}-ga. This value should not be equal to {{ compared_value }}. Väärtus ei tohiks võrduda {{ compared_value }}-ga. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Väärtus ei tohiks olla identne väärtusega {{ compared_value_type }} {{ compared_value }}. This value should be false. Nilai ini harus bernilai salah. This value should be true. Nilai ini harus bernilai benar. This value should be of type {{ type }}. Nilai ini harus bertipe {{ type }}. This value should be blank. Nilai ini harus kosong. The value you selected is not a valid choice. Nilai yang dipilih tidak tepat. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Anda harus memilih paling tidak {{ limit }} pilihan. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Anda harus memilih paling banyak {{ limit }} pilihan. One or more of the given values is invalid. Satu atau lebih nilai yang diberikan tidak sah. This field was not expected. Bidang ini tidak diharapkan. This field is missing. Bidang ini hilang. This value is not a valid date. Nilai ini bukan merupakan tanggal yang sah. This value is not a valid datetime. Nilai ini bukan merupakan tanggal dan waktu yang sah. This value is not a valid email address. Nilai ini bukan alamat email yang sah. The file could not be found. Berkas tidak ditemukan. The file is not readable. Berkas tidak bisa dibaca. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Ukuran berkas terlalu besar ({{ size }} {{ suffix }}). Ukuran maksimum yang diizinkan adalah {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Jenis berkas ({{ type }}) tidak sah. Jenis berkas yang diijinkan adalah {{ types }}. This value should be {{ limit }} or less. Nilai ini harus {{ limit }} atau kurang. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Nilai ini terlalu panjang. Seharusnya {{ limit }} karakter atau kurang. This value should be {{ limit }} or more. Nilai ini harus {{ limit }} atau lebih. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Nilai ini terlalu pendek. Seharusnya {{ limit }} karakter atau lebih. This value should not be blank. Nilai ini tidak boleh kosong. This value should not be null. Nilai ini tidak boleh 'null'. This value should be null. Nilai ini harus 'null'. This value is not valid. Nilai ini tidak sah. This value is not a valid time. Nilai ini bukan merupakan waktu yang sah. This value is not a valid URL. Nilai ini bukan URL yang sah. The two values should be equal. Isi keduanya harus sama. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ukuran berkas terlalu besar. Ukuran maksimum yang diijinkan adalah {{ limit }} {{ suffix }}. The file is too large. Ukuran berkas terlalu besar. The file could not be uploaded. Berkas tidak dapat diunggah. This value should be a valid number. Nilai ini harus angka yang sah. This file is not a valid image. Berkas ini tidak termasuk gambar. This is not a valid IP address. Ini bukan alamat IP yang sah. This value is not a valid language. Nilai ini bukan bahasa yang sah. This value is not a valid locale. Nilai ini bukan lokal yang sah. This value is not a valid country. Nilai ini bukan negara yang sah. This value is already used. Nilai ini sudah digunakan. The size of the image could not be detected. Ukuran dari gambar tidak bisa dideteksi. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Lebar gambar terlalu besar ({{ width }}px). Ukuran lebar maksimum adalah {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Lebar gambar terlalu kecil ({{ width }}px). Ukuran lebar minimum yang diharapkan adalah {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Tinggi gambar terlalu besar ({{ height }}px). Ukuran tinggi maksimum adalah {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Tinggi gambar terlalu kecil ({{ height }}px). Ukuran tinggi minimum yang diharapkan adalah {{ min_height }}px. This value should be the user's current password. Nilai ini harus kata sandi pengguna saat ini. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Nilai ini harus memiliki tepat {{ limit }} karakter. The file was only partially uploaded. Berkas hanya terunggah sebagian. No file was uploaded. Tidak ada berkas terunggah. No temporary folder was configured in php.ini. Direktori sementara tidak dikonfiguasi pada php.ini. Cannot write temporary file to disk. Tidak dapat menuliskan berkas sementara ke dalam media penyimpanan. A PHP extension caused the upload to fail. Sebuah ekstensi PHP menyebabkan kegagalan unggah. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Kumpulan ini harus memiliki {{ limit }} elemen atau lebih. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Kumpulan ini harus memiliki kurang dari {{ limit }} elemen. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Kumpulan ini harus memiliki tepat {{ limit }} elemen. Invalid card number. Nomor kartu tidak sah. Unsupported card type or invalid card number. Jenis kartu tidak didukung atau nomor kartu tidak sah. This is not a valid International Bank Account Number (IBAN). Ini bukan Nomor Rekening Bank Internasional (IBAN) yang sah. This value is not a valid ISBN-10. Nilai ini bukan ISBN-10 yang sah. This value is not a valid ISBN-13. Nilai ini bukan ISBN-13 yang sah. This value is neither a valid ISBN-10 nor a valid ISBN-13. Nilai ini bukan ISBN-10 maupun ISBN-13 yang sah. This value is not a valid ISSN. Nilai ini bukan ISSN yang sah. This value is not a valid currency. Nilai ini bukan mata uang yang sah. This value should be equal to {{ compared_value }}. Nilai ini seharusnya sama dengan {{ compared_value }}. This value should be greater than {{ compared_value }}. Nilai ini seharusnya lebih dari {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Nilai ini seharusnya lebih dari atau sama dengan {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Nilai ini seharusnya identik dengan {{ compared_value_type }} {{ compared_value }}. This value should be less than {{ compared_value }}. Nilai ini seharusnya kurang dari {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Nilai ini seharusnya kurang dari atau sama dengan {{ compared_value }}. This value should not be equal to {{ compared_value }}. Nilai ini seharusnya tidak sama dengan {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Nilai ini seharusnya tidak identik dengan {{ compared_value_type }} {{ compared_value }}. This value should be false. ค่านี้ควรจะเป็น false This value should be true. ค่านี้ควรจะเป็น true This value should be of type {{ type }}. ค่านี้ควรจะเป็นชนิด {{ type }} This value should be blank. ควรจะเป็นค่าว่าง The value you selected is not a valid choice. คุณเลือกค่าที่ไม่ตรงกับตัวเลือก You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. คุณต้องเลือกอย่างน้อย {{ limit }} ตัวเลือก You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. คุณเลือกได้มากที่สุด {{ limit }} ตัวเลือก One or more of the given values is invalid. มีบางค่าที่ส่งมาไม่ถูกต้อง This field was not expected. ฟิลด์นี้ที่ไม่ได้คาดหวัง This field is missing. ฟิลด์นี้จะหายไป This value is not a valid date. ค่าของวันที่ไม่ถูกต้อง This value is not a valid datetime. ค่าของวันที่และเวลาไม่ถูกต้อง This value is not a valid email address. ค่าของอีเมล์ไม่ถูกต้อง The file could not be found. ไม่พบไฟล์ The file is not readable. ไฟล์ไม่อยู่ในสถานะที่สามารถอ่านได้ The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. ไฟล์ใหญ่เกิน ({{ size }} {{ suffix }}) อนุญาตให้ใหญ่ที่สุดได้ไม่เกิน {{ limit }} {{ suffix }} The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Mime type ของไฟล์ไม่ถูกต้อง ({{ type }}) Mime types ที่อนุญาตคือ {{ types }} This value should be {{ limit }} or less. ค่านี้ควรจะเป็น {{ limit }} หรือน้อยกว่านั้น This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. ค่านี้ยาวเกินไป ควรจะมีแค่ {{ limit }} ตัวอักษรหรือน้อยกว่านั้น This value should be {{ limit }} or more. ค่านี้ควรจะมี {{ limit }} หรือมากกว่านั้น This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. ค่านี้สั้นเกินไป ควรจะมี {{ limit }} ตัวอักษรหรือมากกว่านั้น This value should not be blank. ค่านี้ไม่ควรเป็นค่าว่าง This value should not be null. ค่านี้ไม่ควรเป็นค่า null This value should be null. ค่านี้ควรเป็นค่า null This value is not valid. ค่านี้ไม่ถูกต้อง This value is not a valid time. ค่าของเวลาไม่ถูกต้อง This value is not a valid URL. ค่าของ URL ไม่ถูกต้อง The two values should be equal. ค่าทั้งสองค่าควรจะเหมือนกัน The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. ขนาดไฟล์ใหญ่เกินไป อนุญาตให้ไฟล์ขนาดใหญ่ได้ไม่เกิน {{ limit }} {{ suffix }} The file is too large. ขนาดไฟล์ใหญ่เกินไป The file could not be uploaded. ไม่สามารถอัปโหลดไฟล์ได้ This value should be a valid number. ค่าของตัวเลขไม่ถูกต้อง This file is not a valid image. ไฟล์นี้ไม่ใช่ไฟล์รูปภาพ This is not a valid IP address. ค่าของ IP ไม่ถูกต้อง This value is not a valid language. ค่าของภาษาไม่ถูกต้อง This value is not a valid locale. ค่าของภูมิภาค (Locale) ไม่ถูกต้อง This value is not a valid country. ค่าของประเทศไม่ถูกต้อง This value is already used. Tค่านี้ถูกใช้งานไปแล้ว The size of the image could not be detected. ไม่สามารถตรวจสอบขนาดไฟล์ของภาพได้ The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. ความกว้างของภาพเกินขนาด ({{ width }}px) อนุญาตให้กว้างได้มากที่สุด {{ max_width }}px The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. ความกว้างของภาพไม่ได้ขนาด ({{ width }}px) อนุญาตให้สั้นที่สุด {{ min_width }}px The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. ความสูงของภาพเกินขนาด ({{ height }}px) อนุญาตให้สูงได้มากที่สุด {{ max_height }}px The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. ความสูงของภาพไม่ได้ขนาด ({{ height }}px) อนุญาตให้สูงอย่างน้อยที่สุด {{ min_height }}px This value should be the user current password. ค่านี้ควรจะเป็นรหัสผ่านปัจจุบันของผู้ใช้ This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. ค่านี้ควรจะมีความยาว {{ limit }} ตัวอักษร The file was only partially uploaded. อัปโหลดไฟล์ได้เพียงบางส่วนเท่านั้น No file was uploaded. ไม่มีไฟล์ใดถูกอัปโหลด No temporary folder was configured in php.ini. ไม่พบไฟล์ temp ควรจะกำหนดใน php.ini Cannot write temporary file to disk. ไม่สามารถเขียน temp ไฟล์ลงดิสก์ได้ A PHP extension caused the upload to fail. PHP extension เกี่ยวกับการอัปโหลดมีปัญหา This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. คอเล็กชั่นนี้ควรจะประกอบไปด้วยอ่างน้อย {{ limit }} สมาชิก This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. คอเล็กชั่นนี้ไม่ควรมีสมาชิกเกิน {{ limit }} This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. คอเล็กชั่นนี้ควรจะมีสมาชิก {{ limit }} เท่านั้น Invalid card number. หมายเลขบัตรไม่ถูกต้อง Unsupported card type or invalid card number. ไม่รู้จักประเภทของบัตร หรือหมายเลขบัตรไม่ถูกต้อง This is not a valid International Bank Account Number (IBAN). นี่ไม่ถูกต้องตาม International Bank Account Number (IBAN) This value is not a valid ISBN-10. ค่านี้ไม่ถูกต้องตาม ISBN-10 This value is not a valid ISBN-13. ค่านี้ไม่ถูกต้องตาม ISBN-13 This value is neither a valid ISBN-10 nor a valid ISBN-13. ค่านี้ไม่ถูกต้องตามทั้ง ISBN-10 และ ISBN-13 This value is not a valid ISSN. ค่านี้ไม่ถุกต้องตาม ISSN This value is not a valid currency. ค่านี้ไม่ถูกต้องตามสกุลเงิน This value should be equal to {{ compared_value }}. ค่านี้ไม่ตรงกับ {{ compared_value }} This value should be greater than {{ compared_value }}. ค่านี้ควรจะมากกว่า {{ compared_value }} This value should be greater than or equal to {{ compared_value }}. ค่านี้ควรจะมากกว่าหรือตรงกับ {{ compared_value }} This value should be identical to {{ compared_value_type }} {{ compared_value }}. ค่านี้ควรจะเหมือนกันกับ {{ compared_value_type }} {{ compared_value }} This value should be less than {{ compared_value }}. ค่านี้ควรจะน้อยกว่า {{ compared_value }} This value should be less than or equal to {{ compared_value }}. ค่านี้ควรจะน้อยกว่าหรือเท่ากับ {{ compared_value }} This value should not be equal to {{ compared_value }}. ค่านี้ไม่ควรเท่ากันกับ {{ compared_value }} This value should not be identical to {{ compared_value_type }} {{ compared_value }}. ค่านี้ไม่ควรเหมือนกันกับ {{ compared_value_type }} {{ compared_value }} The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. สัดส่วนของภาพใหญ่เกิน ({{ ratio }}) สามารถมีขนาดใหญ่ที่สุดได้ {{ max_ratio }} The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. สัดส่วนของภาพเล็กเกิน ({{ ratio }}) สามารถมีขนาดเล็กที่สุดได้ {{ min_ratio }} The image is square ({{ width }}x{{ height }}px). Square images are not allowed. รูปภาพเป็นจุตรัส ({{ width }}x{{ height }}px) ไม่อนุญาตภาพที่เป็นสี่เหลี่ยมจตุรัส The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. ภาพนี้เป็นแนวนอน ({{ width }}x{{ height }}px) ไม่อนุญาตภาพที่เป็นแนวนอน The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. ภาพนี้เป็นแนวตั้ง ({{ width }}x{{ height }}px) ไม่อนุญาตภาพที่เป็นแนวตั้ง  This value should be false. Энэ утга буруу байх ёстой. This value should be true. Энэ утга үнэн байх ёстой. This value should be of type {{ type }}. Энэ утга {{ type }} -н төрөл байх ёстой. This value should be blank. Энэ утга хоосон байх ёстой. The value you selected is not a valid choice. Сонгосон утга буруу байна. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Хамгийн багадаа {{ limit }} утга сонгогдсон байх ёстой. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Хамгийн ихдээ {{ limit }} утга сонгогдох боломжтой. One or more of the given values is invalid. Өгөгдсөн нэг эсвэл нэгээс олон утга буруу байна. This field was not expected. Энэ талбар нь хүлээгдэж байсан юм. This field is missing. Энэ талбар нь алга болсон байна. This value is not a valid date. Энэ утга буруу date төрөл байна . This value is not a valid datetime. Энэ утга буруу цаг төрөл байна. This value is not a valid email address. И-майл хаяг буруу байна. The file could not be found. Файл олдсонгүй. The file is not readable. Файл уншигдахуйц биш байна. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Файл хэтэрхий том байна ({{ size }} {{ suffix }}). Зөвшөөрөгдөх дээд хэмжээ {{ limit }} {{ suffix }} байна. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Файлын MIME-төрөл нь буруу байна ({{ type }}). Зөвшөөрөгдөх MIME-төрлүүд {{ types }}. This value should be {{ limit }} or less. Энэ утга {{ limit }} юмуу эсвэл бага байна. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Энэ утга хэтэрхий урт байна. {{ limit }} тэмдэгтийн урттай юмуу эсвэл бага байна. This value should be {{ limit }} or more. Энэ утга {{ limit }} юмуу эсвэл их байна. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Энэ утга хэтэрхий богино байна. {{ limit }} тэмдэгт эсвэл их байна. This value should not be blank. Энэ утга хоосон байж болохгүй. This value should not be null. Энэ утга null байж болохгүй. This value should be null. Энэ утга null байна. This value is not valid. Энэ утга буруу байна. This value is not a valid time. Энэ утга буруу цаг төрөл байна. This value is not a valid URL. Энэ утга буруу URL байна . The two values should be equal. Хоёр утгууд ижил байх ёстой. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Файл хэтэрхий том байна. Зөвшөөрөгдөх дээд хэмжээ нь {{ limit }} {{ suffix }} байна. The file is too large. Файл хэтэрхий том байна. The file could not be uploaded. Файл upload хийгдсэнгүй. This value should be a valid number. Энэ утга зөвхөн тоо байна. This value is not a valid country. Энэ утга үнэн бодит улс биш байна. This file is not a valid image. Файл зураг биш байна. This is not a valid IP address. IP хаяг зөв биш байна. This value is not a valid language. Энэ утга үнэн зөв хэл биш байна .  This value should be false. Արժեքը պետք է լինի կեղծ. This value should be true. Արժեքը պետք է լինի ճշմարիտ. This value should be of type {{ type }}. Արժեքը պետք է լինի {{ type }} տեսակի. This value should be blank. Արժեքը պետք է լինի դատարկ. The value you selected is not a valid choice. Ձեր ընտրած արժեքը անթույլատրելի է. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Դուք պետք է ընտրեք ամենաքիչը {{ limit }} տարբերակներ. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Դուք պետք է ընտրեք ոչ ավելի քան {{ limit }} տարբերակներ. One or more of the given values is invalid. Մեկ կամ ավելի տրված արժեքները անթույլատրելի են. This field was not expected. Այս դաշտը չի սպասվում. This field is missing. Այս դաշտը բացակայում է. This value is not a valid date. Արժեքը սխալ ամսաթիվ է. This value is not a valid datetime. Ամսաթվի և ժամանակի արժեքը անթույլատրելի է. This value is not a valid email address. Էլ-փոստի արժեքը անթույլատրելի է. The file could not be found. Ֆայլը չի գտնվել. The file is not readable. Ֆայլը անընթեռնելի է. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Ֆայլը չափազանց մեծ է ({{ size }} {{ suffix }}): Մաքսիմալ թույլատրելի չափսը՝ {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. MIME-տեսակը անթույլատրելի է({{ type }}): Ֆայլերի թույլատրելի MIME-տեսակներն են: {{ types }}. This value should be {{ limit }} or less. Արժեքը պետք է լինի {{ limit }} կամ փոքր. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Արժեքը չափազանց երկար է: Պետք է լինի {{ limit }} կամ ավել սիմվոլներ. This value should be {{ limit }} or more. Արժեքը պետ է լինի {{ limit }} կամ շատ. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Արժեքը չափազանց կարճ է: Պետք է լինի {{ limit }} կամ ավելի սիմվոլներ. This value should not be blank. Արժեքը չպետք է դատարկ լինի. This value should not be null. Արժեքը չպետք է լինի null. This value should be null. Արժեքը պետք է լինի null. This value is not valid. Անթույլատրելի արժեք. This value is not a valid time. Ժամանակի արժեքը անթույլատրելի է. This value is not a valid URL. Արժեքը URL չէ. The two values should be equal. Երկու արժեքները պետք է նույնը լինեն. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Ֆայլը չափազանց մեծ է: Մաքսիմալ թույլատրելի չափսը {{ limit }} {{ suffix }} է. The file is too large. Ֆայլը չափազանց մեծ է. The file could not be uploaded. Ֆայլը չի կարող բեռնվել. This value should be a valid number. Արժեքը պետք է լինի թիվ. This value is not a valid country. Արժեքը պետք է լինի երկիր. This file is not a valid image. Ֆայլը նկարի թույլատրելի ֆորմատ չէ. This is not a valid IP address. Արժեքը թույլատրելի IP հասցե չէ. This value is not a valid language. Արժեքը թույլատրելի լեզու չէ. This value is not a valid locale. Արժեքը չի հանդիսանում թույլատրելի տեղայնացում. This value is already used. Այդ արժեքը արդեն օգտագործվում է. The size of the image could not be detected. Նկարի չափսերը չստացվեց որոշել. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Նկարի լայնությունը չափազանց մեծ է({{ width }}px). Մաքսիմալ չափն է {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Նկարի լայնությունը չափազանց փոքր է ({{ width }}px). Մինիմալ չափն է {{ min_ width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Նկարի բարձրությունը չափազանց մեծ է ({{ height }}px). Մաքսիմալ չափն է {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Նկարի բարձրությունը չափազանց փոքր է ({{ height }}px). Մինիմալ չափն է {{ min_height }}px. This value should be the user's current password. Այս արժեքը պետք է լինի օգտագործողի ներկա ծածկագիրը. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Այս արժեքը պետք է ունենա ճիշտ {{ limit }} սիմվոլներ. This value should be false. Bu dəyər false olmalıdır. This value should be true. Bu dəyər true olmalıdır. This value should be of type {{ type }}. Bu dəyərin tipi {{ type }} olmalıdır. This value should be blank. Bu dəyər boş olmalıdır. The value you selected is not a valid choice. Seçdiyiniz dəyər düzgün bir seçim değil. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Ən az {{ limit }} seçim qeyd edilməlidir. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Ən çox {{ limit }} seçim qeyd edilməlidir. One or more of the given values is invalid. Təqdim edilən dəyərlərdən bir və ya bir neçəsi yanlışdır. This field was not expected. Bu sahə gözlənilmirdi. This field is missing. Bu sahə əksikdir. This value is not a valid date. Bu dəyər düzgün bir tarix deyil. This value is not a valid datetime. Bu dəyər düzgün bir tarixsaat deyil. This value is not a valid email address. Bu dəyər düzgün bir e-poçt adresi deyil. The file could not be found. Fayl tapılmadı. The file is not readable. Fayl oxunabilən deyil. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Fayl çox böyükdür ({{ size }} {{ suffix }}). İcazə verilən maksimum fayl ölçüsü {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Faylın mime tipi yanlışdr ({{ type }}). İcazə verilən mime tipləri {{ types }}. This value should be {{ limit }} or less. Bu dəyər {{ limit }} və ya altında olmalıdır. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Bu dəyər çox uzundur. {{ limit }} və ya daha az simvol olmalıdır. This value should be {{ limit }} or more. Bu dəyər {{ limit }} veya daha fazla olmalıdır. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Bu dəyər çox qısadır. {{ limit }} və ya daha çox simvol olmalıdır. This value should not be blank. Bu dəyər boş olmamalıdır. This value should not be null. Bu dəyər boş olmamalıdır. This value should be null. Bu dəyər boş olmamalıdır. This value is not valid. Bu dəyər doğru deyil. This value is not a valid time. Bu dəyər doğru bir saat deyil. This value is not a valid URL. Bu dəyər doğru bir URL değil. The two values should be equal. İki dəyər eyni olmalıdır. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Fayl çox böyükdür. İcazə verilən ən böyük fayl ölçüsü {{ limit }} {{ suffix }}. The file is too large. Fayl çox böyükdür. The file could not be uploaded. Fayl yüklənəbilmir. This value should be a valid number. Bu dəyər rəqəm olmalıdır. This file is not a valid image. Bu fayl düzgün bir şəkil deyil. This is not a valid IP address. Bu düzgün bir IP adresi deyil. This value is not a valid language. Bu dəyər düzgün bir dil deyil. This value is not a valid locale. Bu dəyər düzgün bir dil deyil. This value is not a valid country. Bu dəyər düzgün bir ölkə deyil. This value is already used. Bu dəyər hal-hazırda istifadədədir. The size of the image could not be detected. Şəklin ölçüsü hesablana bilmir. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Şəklin genişliyi çox böyükdür ({{ width }}px). İcazə verilən ən böyük genişlik {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Şəklin genişliyi çox kiçikdir ({{ width }}px). Ən az {{ min_width }}px olmalıdır. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Şəklin yüksəkliyi çox böyükdür ({{ height }}px). İcazə verilən ən böyük yüksəklik {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Şəklin yüksəkliyi çox kiçikdir ({{ height }}px). Ən az {{ min_height }}px olmalıdır. This value should be the user's current password. Bu dəyər istifadəçinin hazırkı parolu olmalıdır. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Bu dəyər tam olaraq {{ limit }} simvol olmaldır. The file was only partially uploaded. Fayl qismən yükləndi. No file was uploaded. Fayl yüklənmədi. No temporary folder was configured in php.ini. php.ini'də müvəqqəti qovluq quraşdırılmayıb. Cannot write temporary file to disk. Müvəqqəti fayl diskə yazıla bilmir. A PHP extension caused the upload to fail. Bir PHP əlavəsi faylın yüklənməsinə mane oldu. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Bu kolleksiyada {{ limit }} və ya daha çox element olmalıdır. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Bu kolleksiyada {{ limit }} və ya daha az element olmalıdır. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Bu kolleksiyada tam olaraq {{ limit }} element olmalıdır. Invalid card number. Yanlış kart nömrəsi. Unsupported card type or invalid card number. Dəstəklənməyən kart tipi və ya yanlış kart nömrəsi. This value should be false. Dylid bod y gwerth hwn yn ffug. This value should be true. Dylid bod y gwerth hwn yn wir. This value should be of type {{ type }}. Dylid bod y gwerth hwn bod o fath {{ type }}. This value should be blank. Dylid bod y gwerth hwn yn wag. The value you selected is not a valid choice. Nid yw'r gwerth â ddewiswyd yn ddilys. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Rhaid dewis o leiaf {{ limit }} opsiwn. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Rhaid dewis dim mwy na {{ limit }} opsiwn. One or more of the given values is invalid. Mae un neu fwy o'r gwerthoedd a roddwyd yn annilys. This field was not expected. Nid oedd disgwyl y maes hwn. This field is missing. Mae'r maes hwn ar goll. This value is not a valid date. Nid yw'r gwerth yn ddyddiad dilys. This value is not a valid datetime. Nid yw'r gwerth yn datetime dilys. This value is not a valid email address. Nid yw'r gwerth yn gyfeiriad ebost dilys. The file could not be found. Ni ddarganfyddwyd y ffeil. The file is not readable. Ni ellir darllen y ffeil. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Mae'r ffeil yn rhy fawr ({{ size }} {{ suffix }}). Yr uchafswm â ganiateir yw {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Nid yw math mime y ffeil yn ddilys ({{ type }}). Dyma'r mathau â ganiateir {{ types }}. This value should be {{ limit }} or less. Dylai'r gwerth hwn fod yn {{ limit }} neu lai. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Mae'r gwerth hwn rhy hir. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu lai. This value should be {{ limit }} or more. Dylai'r gwerth hwn fod yn {{ limit }} neu fwy. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Mae'r gwerth hwn yn rhy fyr. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu fwy. This value should not be blank. Ni ddylai'r gwerth hwn fod yn wag. This value should not be null. Ni ddylai'r gwerth hwn fod yn null. This value should be null. Dylai'r gwerth fod yn null. This value is not valid. Nid yw'r gwerth hwn yn ddilys. This value is not a valid time. Nid yw'r gwerth hwn yn amser dilys. This value is not a valid URL. Nid yw'r gwerth hwn yn URL dilys. The two values should be equal. Rhaid i'r ddau werth fod yn gyfystyr a'u gilydd. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Mae'r ffeil yn rhy fawr. Yr uchafswm â ganiateir yw {{ limit }} {{ suffix }}. The file is too large. Mae'r ffeil yn rhy fawr. The file could not be uploaded. Methwyd ag uwchlwytho'r ffeil. This value should be a valid number. Dylai'r gwerth hwn fod yn rif dilys. This file is not a valid image. Nid yw'r ffeil hon yn ddelwedd dilys. This is not a valid IP address. Nid yw hwn yn gyfeiriad IP dilys. This value is not a valid language. Nid yw'r gwerth hwn yn iaith ddilys. This value is not a valid locale. Nid yw'r gwerth hwn yn locale dilys. This value is not a valid country. Nid yw'r gwerth hwn yn wlad dilys. This value is already used. Mae'r gwerth hwn eisoes yn cael ei ddefnyddio. The size of the image could not be detected. Methwyd â darganfod maint y ddelwedd. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Mae lled y ddelwedd yn rhy fawr ({{ width }}px). Y lled mwyaf â ganiateir yw {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Mae lled y ddelwedd yn rhy fach ({{ width }}px). Y lled lleiaf â ganiateir yw {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Mae uchder y ddelwedd yn rhy fawr ({{ width }}px). Yr uchder mwyaf â ganiateir yw {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Mae uchder y ddelwedd yn rhy fach ({{ width }}px). Yr uchder lleiaf â ganiateir yw {{ min_height }}px. This value should be the user's current password. Dylaid bod y gwerth hwn yn gyfrinair presenol y defnyddiwr. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Dylai'r gwerth hwn fod yn union {{ limit }} nodyn cyfrifiadurol o hyd. The file was only partially uploaded. Dim ond rhan o'r ffeil ag uwchlwythwyd. No file was uploaded. Ni uwchlwythwyd unrhyw ffeil. No temporary folder was configured in php.ini. Nid oes ffolder dros-dro wedi'i gosod yn php.ini. Cannot write temporary file to disk. Methwyd ag ysgrifennu'r ffeil dros-dro ar ddisg. A PHP extension caused the upload to fail. Methwyd ag uwchlwytho oherwydd ategyn PHP. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu fwy. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu lai. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Dylai'r casgliad hwn gynnwys union {{ limit }} elfen. Invalid card number. Nid oedd rhif y cerdyn yn ddilys. Unsupported card type or invalid card number. Unai ni dderbynir y math yna o gerdyn, neu nid yw rhif y cerdyn yn ddilys. This value should be false. این مقدار باید نادرست(False) باشد. This value should be true. این مقدار باید درست(True) باشد. This value should be of type {{ type }}. این مقدار باید از نوع {{ type }} باشد. This value should be blank. این فیلد باید خالی باشد. The value you selected is not a valid choice. گزینه انتخابی معتبر نیست. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. باید حداقل {{ limit }} گزینه انتخاب کنید.|باید حداقل {{ limit }} گزینه انتخاب کنید. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. حداکثر {{ limit }} گزینه می توانید انتخاب کنید.|حداکثر {{ limit }} گزینه می توانید انتخاب کنید. One or more of the given values is invalid. یک یا چند مقدار نامعتبر وجود دارد. The fields {{ fields }} were not expected. فیلدهای {{ fields }} اضافی هستند. The fields {{ fields }} are missing. فیلدهای {{ fields }} کم هستند. This value is not a valid date. این مقدار یک تاریخ معتبر نیست. This value is not a valid datetime. این مقدار یک تاریخ و زمان معتبر نیست. This value is not a valid email address. این یک رایانامه معتبر نیست. The file could not be found. فایل پیدا نشد. The file is not readable. فایل قابلیت خواندن ندارد. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. فایل بیش از اندازه بزرگ است({{ size }} {{ suffix }}). حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. این نوع فایل مجاز نیست({{ type }}). نوع های مجاز {{ types }} هستند. This value should be {{ limit }} or less. این مقدار باید کوچکتر یا مساوی {{ limit }} باشد. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.|بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است. This value should be {{ limit }} or more. این مقدار باید برابر و یا بیشتر از {{ limit }} باشد. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.|بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد. This value should not be blank. این مقدار نباید تهی باشد. This value should not be null. باید مقداری داشته باشد.. This value should be null. نباید مقداری داشته باشد. This value is not valid. این مقدار معتبر نیست. This value is not a valid time. این مقدار یک زمان صحیح نیست. This value is not a valid URL. این یک URL معتبر نیست. The two values should be equal. دو مقدار باید برابر باشند. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. فایل بیش از اندازه بزرگ است. حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است. The file is too large. فایل بیش از اندازه بزرگ است. The file could not be uploaded. بارگذاری فایل با شکست مواجه شد. This value should be a valid number. این مقدار باید یک عدد معتبر باشد. This file is not a valid image. این فایل یک تصویر نیست. This is not a valid IP address. این مقدار یک IP معتبر نیست. This value is not a valid language. این مقدار یک زبان صحیح نیست. This value is not a valid locale. این مقدار یک محل صحیح نیست. This value is not a valid country. این مقدار یک کشور صحیح نیست. This value is already used. این مقدار قبلا مورد استفاده قرار گرفته است. The size of the image could not be detected. اندازه تصویر قابل شناسایی نیست. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. طول تصویر بسیار بزرگ است ({{ width }}px). بشینه طول مجاز {{ max_width }}px است. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. طول تصویر بسیار کوچک است ({{ width }}px). کمینه طول موردنظر {{ min_width }}px است. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. ارتفاع تصویر بسیار بزرگ است ({{ height }}px). بشینه ارتفاع مجاز {{ max_height }}px است. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. ارتفاع تصویر بسیار کوچک است ({{ height }}px). کمینه ارتفاع موردنظر {{ min_height }}px است. This value should be the user's current password. این مقدار می بایست کلمه عبور کنونی کاربر باشد. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. این مقدار می بایست دقیقا {{ limit }} کاراکتر داشته باشد.| این مقدار می بایست دقیقا {{ limit }} کاراکتر داشته باشد. The file was only partially uploaded. فایل به صورت جزیی بارگذاری شده است. No file was uploaded. هیچ فایلی بارگذاری نشد. No temporary folder was configured in php.ini. فولدر موقت در php.ini پیکربندی نشده است. Cannot write temporary file to disk. فایل موقت را نمی توان در دیسک نوشت. A PHP extension caused the upload to fail. اکستنشن PHP موجب شد که بارگذاری فایل با شکست مواجه شود. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. این مجموعه می بایست دارای حداقل {{ limit }} عنصر یا کمتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا کمتر باشد. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. این مجموعه می بایست به طور دقیق دارا {{ limit }} عنصر باشد.|این مجموعه می بایست به طور دقیق دارای {{ limit }} قلم باشد. Invalid card number. شماره کارت نامعتبر است. Unsupported card type or invalid card number. نوع کارت پشتیبانی نمی شود یا شماره کارت نامعتبر است. This is not a valid International Bank Account Number (IBAN). این یک شماره حساب بین المللی بانک (IBAN) درست نیست. This value is not a valid ISBN-10. این مقدار یک ISBN-10 درست نیست. This value is not a valid ISBN-13. این مقدار یک ISBN-13 درست نیست. This value is neither a valid ISBN-10 nor a valid ISBN-13. این مقدار یک ISBN-10 درست یا ISBN-13 درست نیست. This value is not a valid ISSN. این مقدار یک ISSN درست نیست. This value is not a valid currency. این مقدار یک یکای پول درست نیست. This value should be equal to {{ compared_value }}. این مقدار باید برابر با {{ compared_value }} باشد. This value should be greater than {{ compared_value }}. این مقدار باید از {{ compared_value }} بیشتر باشد. This value should be greater than or equal to {{ compared_value }}. این مقدار باید بزرگتر یا مساوی با {{ compared_value }} باشد. This value should be identical to {{ compared_value_type }} {{ compared_value }}. این مقدار باید با {{ compared_value_type }} {{ compared_value }} یکی باشد. This value should be less than {{ compared_value }}. این مقدار باید کمتر از {{ compared_value }} باشد. This value should be less than or equal to {{ compared_value }}. این مقدار باید کمتر یا مساوی با {{ compared_value }} باشد. This value should not be equal to {{ compared_value }}. این مقدار نباید با {{ compared_value }} برابر باشد. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. این مقدار نباید {{ compared_value_type }} {{ compared_value }} یکی باشد. This value should be false. Bu değer olumsuz olmalıdır. This value should be true. Bu değer olumlu olmalıdır. This value should be of type {{ type }}. Bu değerin tipi {{ type }} olmalıdır. This value should be blank. Bu değer boş olmalıdır. The value you selected is not a valid choice. Seçtiğiniz değer geçerli bir seçenek değil. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. En az {{ limit }} seçenek belirtmelisiniz. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. En çok {{ limit }} seçenek belirtmelisiniz. One or more of the given values is invalid. Verilen değerlerden bir veya daha fazlası geçersiz. This field was not expected. Bu alan beklenen olmadı. This field is missing. Bu alan, eksik This value is not a valid date. Bu değer doğru bir tarih biçimi değildir. This value is not a valid datetime. Bu değer doğru bir tarihsaat biçimi değildir. This value is not a valid email address. Bu değer doğru bir e-mail adresi değildir. The file could not be found. Dosya bulunamadı. The file is not readable. Dosya okunabilir değil. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Dosya çok büyük ({{ size }} {{ suffix }}). İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Dosyanın mime tipi geçersiz ({{ type }}). İzin verilen mime tipleri {{ types }}. This value should be {{ limit }} or less. Bu değer {{ limit }} ve altında olmalıdır. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Bu değer çok uzun. {{ limit }} karakter veya daha az olmalıdır. This value should be {{ limit }} or more. Bu değer {{ limit }} veya daha fazla olmalıdır. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Bu değer çok kısa. {{ limit }} karakter veya daha fazla olmaldır. This value should not be blank. Bu değer boş bırakılmamalıdır. This value should not be null. Bu değer boş bırakılmamalıdır. This value should be null. Bu değer boş bırakılmalıdır. This value is not valid. Bu değer geçerli değil. This value is not a valid time. Bu değer doğru bir saat değil. This value is not a valid URL. Bu değer doğru bir URL değil. The two values should be equal. İki değer eşit olmalıdır. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Dosya çok büyük. İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}. The file is too large. Dosya çok büyük. The file could not be uploaded. Dosya yüklenemiyor. This value should be a valid number. Bu değer geçerli bir rakam olmalıdır. This file is not a valid image. Bu dosya geçerli bir resim değildir. This is not a valid IP address. Bu geçerli bir IP adresi değildir. This value is not a valid language. Bu değer geçerli bir lisan değil. This value is not a valid locale. Bu değer geçerli bir yer değildir. This value is not a valid country. Bu değer geçerli bir ülke değildir. This value is already used. Bu değer şu anda kullanımda. The size of the image could not be detected. Resmin boyutu saptanamıyor. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Resmin genişliği çok büyük ({{ width }}px). İzin verilen en büyük genişlik {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Resmin genişliği çok küçük ({{ width }}px). En az {{ min_width }}px olmalıdır. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Resmin yüksekliği çok büyük ({{ height }}px). İzin verilen en büyük yükseklik {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Resmin yüksekliği çok küçük ({{ height }}px). En az {{ min_height }}px olmalıdır. This value should be the user's current password. Bu değer kullanıcının şu anki şifresi olmalıdır. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Bu değer tam olarak {{ limit }} karakter olmaldır. The file was only partially uploaded. Dosya sadece kısmen yüklendi. No file was uploaded. Hiçbir dosya yüklenmedi. No temporary folder was configured in php.ini. php.ini içerisinde geçici dizin tanımlanmadı. Cannot write temporary file to disk. Geçici dosya diske yazılamıyor. A PHP extension caused the upload to fail. Bir PHP eklentisi dosyanın yüklemesini başarısız kıldı. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Bu derlem {{ limit }} veya daha çok eleman içermelidir. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Bu derlem {{ limit }} veya daha az eleman içermelidir. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Bu derlem {{ limit }} eleman içermelidir. Invalid card number. Geçersiz kart numarası. Unsupported card type or invalid card number. Desteklenmeyen kart tipi veya geçersiz kart numarası. This value should be false. Tato hodnota musí být nepravdivá (false). This value should be true. Tato hodnota musí být pravdivá (true). This value should be of type {{ type }}. Tato hodnota musí být typu {{ type }}. This value should be blank. Tato hodnota musí být prázdná. The value you selected is not a valid choice. Vybraná hodnota není platnou možností. You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. Musí být vybrána nejméně {{ limit }} možnost.|Musí být vybrány nejméně {{ limit }} možnosti.|Musí být vybráno nejméně {{ limit }} možností. You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. Musí být vybrána maximálně {{ limit }} možnost.|Musí být vybrány maximálně {{ limit }} možnosti.|Musí být vybráno maximálně {{ limit }} možností. One or more of the given values is invalid. Některé z uvedených hodnot jsou neplatné. This field was not expected. Toto pole nebyla očekávána. This field is missing. Toto pole chybí. This value is not a valid date. Tato hodnota není platné datum. This value is not a valid datetime. Tato hodnota není platné datum s časovým údajem. This value is not a valid email address. Tato hodnota není platná e-mailová adresa. The file could not be found. Soubor nebyl nalezen. The file is not readable. Soubor je nečitelný. The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. Soubor je příliš velký ({{ size }} {{ suffix }}). Maximální povolená velikost souboru je {{ limit }} {{ suffix }}. The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. Neplatný mime typ souboru ({{ type }}). Povolené mime typy souborů jsou {{ types }}. This value should be {{ limit }} or less. Tato hodnota musí být {{ limit }} nebo méně. This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znak.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaky.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaků. This value should be {{ limit }} or more. Tato hodnota musí být {{ limit }} nebo více. This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znak.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaky.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaků. This value should not be blank. Tato hodnota nesmí být prázdná. This value should not be null. Tato hodnota nesmí být null. This value should be null. Tato hodnota musí být null. This value is not valid. Tato hodnota není platná. This value is not a valid time. Tato hodnota není platný časový údaj. This value is not a valid URL. Tato hodnota není platná URL adresa. The two values should be equal. Tyto dvě hodnoty musí být stejné. The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. Soubor je příliš velký. Maximální povolená velikost souboru je {{ limit }} {{ suffix }}. The file is too large. Soubor je příliš velký. The file could not be uploaded. Soubor se nepodařilo nahrát. This value should be a valid number. Tato hodnota musí být číslo. This file is not a valid image. Tento soubor není obrázek. This is not a valid IP address. Toto není platná IP adresa. This value is not a valid language. Tento jazyk neexistuje. This value is not a valid locale. Tato lokalizace neexistuje. This value is not a valid country. Tato země neexistuje. This value is already used. Tato hodnota je již používána. The size of the image could not be detected. Nepodařily se zjistit rozměry obrázku. The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. Obrázek je příliš široký ({{ width }}px). Maximální povolená šířka obrázku je {{ max_width }}px. The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. Obrázek je příliš úzký ({{ width }}px). Minimální šířka musí být {{ min_width }}px. The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. Obrázek je příliš vysoký ({{ height }}px). Maximální povolená výška obrázku je {{ max_height }}px. The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. Obrázek je příliš nízký ({{ height }}px). Minimální výška obrázku musí být {{ min_height }}px. This value should be the user's current password. Tato hodnota musí být aktuální heslo uživatele. This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. Tato hodnota musí mít přesně {{ limit }} znak.|Tato hodnota musí mít přesně {{ limit }} znaky.|Tato hodnota musí mít přesně {{ limit }} znaků. The file was only partially uploaded. Byla nahrána jen část souboru. No file was uploaded. Žádný soubor nebyl nahrán. No temporary folder was configured in php.ini. V php.ini není nastavena cesta k adresáři pro dočasné soubory. Cannot write temporary file to disk. Dočasný soubor se nepodařilo zapsat na disk. A PHP extension caused the upload to fail. Rozšíření PHP zabránilo nahrání souboru. This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. Tato kolekce musí obsahovat minimálně {{ limit }} prvek.|Tato kolekce musí obsahovat minimálně {{ limit }} prvky.|Tato kolekce musí obsahovat minimálně {{ limit }} prvků. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. Tato kolekce musí obsahovat maximálně {{ limit }} prvek.|Tato kolekce musí obsahovat maximálně {{ limit }} prvky.|Tato kolekce musí obsahovat maximálně {{ limit }} prvků. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. Tato kolekce musí obsahovat přesně {{ limit }} prvek.|Tato kolekce musí obsahovat přesně {{ limit }} prvky.|Tato kolekce musí obsahovat přesně {{ limit }} prvků. Invalid card number. Neplatné číslo karty. Unsupported card type or invalid card number. Nepodporovaný typ karty nebo neplatné číslo karty. This is not a valid International Bank Account Number (IBAN). Toto je neplatný IBAN. This value is not a valid ISBN-10. Tato hodnota není platné ISBN-10. This value is not a valid ISBN-13. Tato hodnota není platné ISBN-13. This value is neither a valid ISBN-10 nor a valid ISBN-13. Tato hodnota není platné ISBN-10 ani ISBN-13. This value is not a valid ISSN. Tato hodnota není platné ISSN. This value is not a valid currency. Tato měna neexistuje. This value should be equal to {{ compared_value }}. Tato hodnota musí být rovna {{ compared_value }}. This value should be greater than {{ compared_value }}. Tato hodnota musí být větší než {{ compared_value }}. This value should be greater than or equal to {{ compared_value }}. Tato hodnota musí být větší nebo rovna {{ compared_value }}. This value should be identical to {{ compared_value_type }} {{ compared_value }}. Tato hodnota musí být typu {{ compared_value_type }} a zároveň musí být rovna {{ compared_value }}. This value should be less than {{ compared_value }}. Tato hodnota musí být menší než {{ compared_value }}. This value should be less than or equal to {{ compared_value }}. Tato hodnota musí být menší nebo rovna {{ compared_value }}. This value should not be equal to {{ compared_value }}. Tato hodnota nesmí být rovna {{ compared_value }}. This value should not be identical to {{ compared_value_type }} {{ compared_value }}. Tato hodnota nesmí být typu {{ compared_value_type }} a zároveň nesmí být rovna {{ compared_value }}. The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. Poměr stran obrázku je příliš velký ({{ ratio }}). Maximální povolený poměr stran obrázku je {{ max_ratio }}. The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. Poměr stran obrázku je příliš malý ({{ ratio }}). Minimální povolený poměr stran obrázku je {{ min_ratio }}. The image is square ({{ width }}x{{ height }}px). Square images are not allowed. Strany obrázku jsou čtvercové ({{ width }}x{{ height }}px). Čtvercové obrázky nejsou povolené. The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. Obrázek je orientovaný na šířku ({{ width }}x{{ height }}px). Obrázky orientované na šířku nejsou povolené. The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. Obrázek je orientovaný na výšku ({{ width }}x{{ height }}px). Obrázky orientované na výšku nejsou povolené. An empty file is not allowed. Soubor nesmí být prázdný. Validator Component =================== This component is based on the JSR-303 Bean Validation specification and enables specifying validation rules for classes using XML, YAML, PHP or annotations, which can then be checked against instances of these classes. Usage ----- The component provides "validation constraints", which are simple objects containing the rules for the validation. Let's validate a simple string as an example: ```php use Symfony\Component\Validator\Validation; use Symfony\Component\Validator\Constraints\Length; $validator = Validation::createValidator(); $violations = $validator->validateValue('Bernhard', new Length(array('min' => 10))); ``` This validation will fail because the given string is shorter than ten characters. The precise errors, here called "constraint violations", are returned by the validator. You can analyze these or return them to the user. If the violation list is empty, validation succeeded. Validation of arrays is possible using the `Collection` constraint: ```php use Symfony\Component\Validator\Validation; use Symfony\Component\Validator\Constraints as Assert; $validator = Validation::createValidator(); $constraint = new Assert\Collection(array( 'name' => new Assert\Collection(array( 'first_name' => new Assert\Length(array('min' => 101)), 'last_name' => new Assert\Length(array('min' => 1)), )), 'email' => new Assert\Email(), 'simple' => new Assert\Length(array('min' => 102)), 'gender' => new Assert\Choice(array(3, 4)), 'file' => new Assert\File(), 'password' => new Assert\Length(array('min' => 60)), )); $violations = $validator->validateValue($input, $constraint); ``` Again, the validator returns the list of violations. Validation of objects is possible using "constraint mapping". With such a mapping you can put constraints onto properties and objects of classes. Whenever an object of this class is validated, its properties and method results are matched against the constraints. ```php use Symfony\Component\Validator\Validation; use Symfony\Component\Validator\Constraints as Assert; class User { /** * @Assert\Length(min = 3) * @Assert\NotBlank */ private $name; /** * @Assert\Email * @Assert\NotBlank */ private $email; public function __construct($name, $email) { $this->name = $name; $this->email = $email; } /** * @Assert\IsTrue(message = "The user should have a Google Mail account") */ public function isGmailUser() { return false !== strpos($this->email, '@gmail.com'); } } $validator = Validation::createValidatorBuilder() ->enableAnnotationMapping() ->getValidator(); $user = new User('John Doe', 'john@example.com'); $violations = $validator->validate($user); ``` This example uses the annotation support of Doctrine Common to map constraints to properties and methods. You can also map constraints using XML, YAML or plain PHP, if you dislike annotations or don't want to include Doctrine. Check the documentation for more information about these drivers. Resources --------- Silex integration: https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/ValidatorServiceProvider.php Documentation: https://symfony.com/doc/2.6/book/validation.html JSR-303 Specification: http://jcp.org/en/jsr/detail?id=303 You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Validator/ $ composer install $ phpunit { "name": "symfony/validator", "type": "library", "description": "Symfony Validator Component", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=5.3.3", "symfony/translation": "~2.0,>=2.0.5" }, "require-dev": { "symfony/phpunit-bridge": "~2.7", "doctrine/common": "~2.3", "symfony/http-foundation": "~2.1", "symfony/intl": "~2.3", "symfony/yaml": "~2.0,>=2.0.5", "symfony/config": "~2.2", "symfony/property-access": "~2.3", "symfony/expression-language": "~2.4", "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", "egulias/email-validator": "~1.2,>=1.2.1" }, "suggest": { "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", "doctrine/cache": "For using the default cached annotation reader and metadata cache.", "symfony/http-foundation": "", "symfony/intl": "", "symfony/yaml": "", "symfony/config": "", "egulias/email-validator": "Strict (RFC compliant) email validation", "symfony/property-access": "For using the 2.4 Validator API", "symfony/expression-language": "For using the 2.4 Expression validator" }, "autoload": { "psr-0": { "Symfony\\Component\\Validator\\": "" } }, "target-dir": "Symfony/Component/Validator", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.6-dev" } } } Copyright (c) 2005-2015, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ./test/ disable ./src ./test/ disable ./src # CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-service-manager/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-service-manager.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-service-manager) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-service-manager.git $ cd zend-service-manager ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-service-manager.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-service-manager.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` # zend-servicemanager The Service Locator design pattern is implemented by the `Zend\ServiceManager` component. The Service Locator is a service/object locator, tasked with retrieving other objects. - File issues at https://github.com/zendframework/zend-servicemanager/issues - Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-servicemanager { "name": "zendframework/zend-servicemanager", "description": " ", "license": "BSD-3-Clause", "keywords": [ "zf2", "servicemanager" ], "autoload": { "psr-4": { "Zend\\ServiceManager\\": "src/" } }, "require": { "php": ">=5.3.3" }, "suggest": { "zendframework/zend-di": "Zend\\Di component" }, "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "homepage": "https://github.com/zendframework/zend-service-manager", "autoload-dev": { "psr-4": { "ZendTest\\ServiceManager\\": "test/" } }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "satooshi/php-coveralls": "dev-master", "phpunit/PHPUnit": "~4.0" } }Copyright (c) 2005-2015, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ./test/ disable ./src ./test/ disable ./src # CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-stdlib/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-stdlib.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-stdlib) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-stdlib.git $ cd zend-stdlib ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-stdlib.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-stdlib.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` # zend-stdlib `Zend\Stdlib` is a set of components that implements general purpose utility class for different scopes like: - array utilities functions; - hydrators; - json serialazible interfaces; - general messaging systems; - strin wrappers; - etc - File issues at https://github.com/zendframework/zend-stdlib/issues - Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-stdlib { "name": "zendframework/zend-stdlib", "description": " ", "license": "BSD-3-Clause", "keywords": [ "zf2", "stdlib" ], "homepage": "https://github.com/zendframework/zend-stdlib", "autoload": { "psr-4": { "Zend\\Stdlib\\": "src/" } }, "require": { "php": ">=5.3.3" }, "require-dev": { "zendframework/zend-eventmanager": "self.version", "zendframework/zend-serializer": "self.version", "zendframework/zend-servicemanager": "self.version", "zendframework/zend-filter": "self.version", "fabpot/php-cs-fixer": "1.7.*", "satooshi/php-coveralls": "dev-master", "phpunit/PHPUnit": "~4.0" }, "suggest": { "zendframework/zend-eventmanager": "To support aggregate hydrator usage", "zendframework/zend-serializer": "Zend\\Serializer component", "zendframework/zend-servicemanager": "To support hydrator plugin manager usage", "zendframework/zend-filter": "To support naming strategy hydrator usage" }, "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "autoload-dev": { "psr-4": { "ZendTest\\Stdlib\\": "test/" } } }Copyright (c) 2005-2015, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ./test/ disable ./src ./test/ disable ./src # CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-filter/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-filter.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-filter) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-filter.git $ cd zend-filter ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-filter.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-filter.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` # zend-filter The `Zend\Filter` component provides a set of commonly needed data filters. It also provides a simple filter chaining mechanism by which multiple filters may be applied to a single datum in a user-defined order. - File issues at https://github.com/zendframework/zend-filter/issues - Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-filter { "name": "zendframework/zend-filter", "description": "provides a set of commonly needed data filters", "license": "BSD-3-Clause", "keywords": [ "zf2", "filter" ], "homepage": "https://github.com/zendframework/zend-filter", "autoload": { "psr-4": { "Zend\\Filter\\": "src/" } }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "zendframework/zend-crypt": "self.version", "zendframework/zend-servicemanager": "self.version", "zendframework/zend-uri": "self.version", "fabpot/php-cs-fixer": "1.7.*", "satooshi/php-coveralls": "dev-master", "phpunit/PHPUnit": "~4.0" }, "suggest": { "zendframework/zend-crypt": "Zend\\Crypt component", "zendframework/zend-i18n": "Zend\\I18n component", "zendframework/zend-servicemanager": "Zend\\ServiceManager component", "zendframework/zend-uri": "Zend\\Uri component for UriNormalize filter", "zendframework/zend-validator": "Zend\\Validator component" }, "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "autoload-dev": { "psr-4": { "ZendTest\\Filter\\": "test/" } } }Copyright (c) 2005-2015, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ./test/ disable ./src ./test/ disable ./src # CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-cache/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-cache.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-cache) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-cache.git $ cd zend-cache ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-cache.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-cache.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` # zend-cache `Zend\Cache` provides a general cache system for PHP. The `Zend\Cache` component is able to cache different patterns (class, object, output, etc) using different storage adapters (DB, File, Memcache, etc). - File issues at https://github.com/zendframework/zend-cache/issues - Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-cache { "name": "zendframework/zend-cache", "description": "provides a generic way to cache any data", "license": "BSD-3-Clause", "keywords": [ "zf2", "cache" ], "homepage": "https://github.com/zendframework/zend-cache", "autoload": { "psr-4": { "Zend\\Cache\\": "src/" } }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version", "zendframework/zend-servicemanager": "self.version", "zendframework/zend-serializer": "self.version", "zendframework/zend-eventmanager": "self.version" }, "require-dev": { "zendframework/zend-session": "self.version", "zendframework/zend-serializer": "self.version", "fabpot/php-cs-fixer": "1.7.*", "satooshi/php-coveralls": "dev-master", "phpunit/PHPUnit": "~4.0" }, "suggest": { "zendframework/zend-serializer": "Zend\\Serializer component", "zendframework/zend-session": "Zend\\Session component", "ext-apc": "APC >= 3.1.6 to use the APC storage adapter", "ext-dba": "DBA, to use the DBA storage adapter", "ext-memcached": "Memcached >= 1.0.0 to use the Memcached storage adapter", "ext-mongo": "Mongo, to use MongoDb storage adapter", "ext-wincache": "WinCache, to use the WinCache storage adapter", "mongofill/mongofill": "Alternative to ext-mongo - a pure PHP implementation designed as a drop in replacement" }, "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "autoload-dev": { "psr-4": { "ZendTest\\Cache\\": "test/" } } }Copyright (c) 2005-2015, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ./test/ disable ./src ./test/ disable ./src # CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-event-manager/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-event-manager.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-event-manager) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-event-manager.git $ cd zend-event-manager ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-event-manager.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-event-manager.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` # zend-eventmanager The `Zend\EventManager` is a component designed for the following use cases: - Implementing simple subject/observer patterns. - Implementing Aspect-Oriented designs. - Implementing event-driven architectures. The basic architecture allows you to attach and detach listeners to named events, both on a per-instance basis as well as via shared collections; trigger events; and interrupt execution of listeners. - File issues at https://github.com/zendframework/zend-eventmanager/issues - Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-eventmanager { "name": "zendframework/zend-eventmanager", "description": " ", "license": "BSD-3-Clause", "keywords": [ "zf2", "eventmanager" ], "autoload": { "psr-4": { "Zend\\EventManager\\": "src/" } }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version" }, "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "homepage": "https://github.com/zendframework/zend-event-manager", "autoload-dev": { "psr-4": { "ZendTest\\EventManager\\": "test/" } }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "satooshi/php-coveralls": "dev-master", "phpunit/PHPUnit": "~4.0" } }Copyright (c) 2005-2015, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ./test/ disable ./src ./test/ disable ./src # CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-config/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-config.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-config) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-config.git $ cd zend-config ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-config.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-config.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` # zend-config `Zend\Config` is designed to simplify access to configuration data within applications. It provides a nested object property-based user interface for accessing this configuration data within application code. The configuration data may come from a variety of media supporting hierarchical data storage. - File issues at https://github.com/zendframework/zend-code/issues - Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-code { "name": "zendframework/zend-config", "description": "provides a nested object property based user interface for accessing this configuration data within application code", "license": "BSD-3-Clause", "keywords": [ "zf2", "config" ], "homepage": "https://github.com/zendframework/zend-config", "autoload": { "psr-4": { "Zend\\Config\\": "src/" } }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "zendframework/zend-filter": "self.version", "zendframework/zend-i18n": "self.version", "zendframework/zend-json": "self.version", "zendframework/zend-servicemanager": "self.version", "fabpot/php-cs-fixer": "1.7.*", "satooshi/php-coveralls": "dev-master", "phpunit/PHPUnit": "~4.0" }, "suggest": { "zendframework/zend-filter": "Zend\\Filter component", "zendframework/zend-i18n": "Zend\\I18n component", "zendframework/zend-json": "Zend\\Json to use the Json reader or writer classes", "zendframework/zend-servicemanager": "Zend\\ServiceManager for use with the Config Factory to retrieve reader and writer instances" }, "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "autoload-dev": { "psr-4": { "ZendTest\\Config\\": "test/" } } }Copyright (c) 2005-2015, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ./test/ disable ./src ./test/ disable ./src # CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-i18n/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-i18n.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-i18n) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-i18n.git $ cd zend-i18n ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-i18n.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-i18n.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` # zend-i18n `Zend\I18n` comes with a complete translation suite which supports all major formats and includes popular features like plural translations and text domains. The Translator component is mostly dependency free, except for the fallback to a default locale, where it relies on the Intl PHP extension. The translator itself is initialized without any parameters, as any configuration to it is optional. A translator without any translations will actually do nothing but just return the given message IDs. - File issues at https://github.com/zendframework/zend-i18n/issues - Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-i18n { "name": "zendframework/zend-i18n", "description": " ", "license": "BSD-3-Clause", "keywords": [ "zf2", "i18n" ], "homepage": "https://github.com/zendframework/zend-i18n", "autoload": { "psr-4": { "Zend\\I18n\\": "src/" } }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "zendframework/zend-cache": "self.version", "zendframework/zend-config": "self.version", "zendframework/zend-eventmanager": "self.version", "zendframework/zend-filter": "self.version", "zendframework/zend-servicemanager": "self.version", "zendframework/zend-validator": "self.version", "zendframework/zend-view": "self.version", "fabpot/php-cs-fixer": "1.7.*", "satooshi/php-coveralls": "dev-master", "phpunit/PHPUnit": "~4.0" }, "suggest": { "ext-intl": "Required for most features of Zend\\I18n; included in default builds of PHP", "zendframework/zend-cache": "Zend\\Cache component", "zendframework/zend-config": "Zend\\Config component", "zendframework/zend-eventmanager": "You should install this package to use the events in the translator", "zendframework/zend-filter": "You should install this package to use the provided filters", "zendframework/zend-servicemanager": "Zend\\ServiceManager component", "zendframework/zend-validator": "You should install this package to use the provided validators", "zendframework/zend-view": "You should install this package to use the provided view helpers", "zendframework/zend-resources": "Translation resources" }, "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "autoload-dev": { "psr-4": { "ZendTest\\I18n\\": "test/" } } }Copyright (c) 2005-2015, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ./test/ disable ./src ./test/ disable ./src # CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-json/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-json.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-json) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-json.git $ cd zend-json ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-json.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-json.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` # zend-json `Zend\Json` provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP. For more information on JSON, visit the JSON [project site](http://www.json.org/). - File issues at https://github.com/zendframework/zend-json/issues - Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-json { "name": "zendframework/zend-json", "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", "license": "BSD-3-Clause", "keywords": [ "zf2", "json" ], "homepage": "https://github.com/zendframework/zend-json", "autoload": { "psr-4": { "Zend\\Json\\": "src/" } }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version" }, "require-dev": { "zendframework/zend-http": "self.version", "zendframework/zend-server": "self.version", "fabpot/php-cs-fixer": "1.7.*", "satooshi/php-coveralls": "dev-master", "phpunit/PHPUnit": "~4.0" }, "suggest": { "zendframework/zend-http": "Zend\\Http component", "zendframework/zend-server": "Zend\\Server component", "zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage" }, "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "autoload-dev": { "psr-4": { "ZendTest\\Json\\": "test/" } } }Copyright (c) 2005-2015, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ./test/ disable ./src ./test/ disable ./src # CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-serializer/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-serializer.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-serializer) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-serializer.git $ cd zend-serializer ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-serializer.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-serializer.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` # zend-serializer The `Zend\Serializer` component provides an adapter based interface to simply generate storable representation of PHP types by different facilities, and recover. - File issues at https://github.com/zendframework/zend-serializer/issues - Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-serializer { "name": "zendframework/zend-serializer", "description": "provides an adapter based interface to simply generate storable representation of PHP types by different facilities, and recover", "license": "BSD-3-Clause", "keywords": [ "zf2", "serializer" ], "homepage": "https://github.com/zendframework/zend-serializer", "autoload": { "psr-4": { "Zend\\Serializer\\": "src/" } }, "require": { "php": ">=5.3.3", "zendframework/zend-stdlib": "self.version", "zendframework/zend-json": "self.version", "zendframework/zend-math": "self.version" }, "require-dev": { "zendframework/zend-servicemanager": "self.version", "fabpot/php-cs-fixer": "1.7.*", "satooshi/php-coveralls": "dev-master", "phpunit/PHPUnit": "~4.0" }, "suggest": { "zendframework/zend-servicemanager": "To support plugin manager support" }, "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "autoload-dev": { "psr-4": { "ZendTest\\Serializer\\": "test/" } } }Copyright (c) 2005-2015, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ./test/ disable ./src ./test/ disable ./src # CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-math/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-math.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-math) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-math.git $ cd zend-math ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-math.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-math.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` # zend-math `Zend\Math` provides general mathematical functions. So far the supported functionalities are: - `Zend\Math\Rand`, a random number generator; - `Zend\Math\BigInteger`, a library to manage big integers. - File issues at https://github.com/zendframework/zend-math/issues - Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-math { "name": "zendframework/zend-math", "description": " ", "license": "BSD-3-Clause", "keywords": [ "zf2", "math" ], "homepage": "https://github.com/zendframework/zend-math", "autoload": { "psr-4": { "Zend\\Math\\": "src/" } }, "require": { "php": ">=5.3.3" }, "suggest": { "ext-bcmath": "If using the bcmath functionality", "ext-gmp": "If using the gmp functionality", "ircmaxell/random-lib": "Fallback random byte generator for Zend\\Math\\Rand if OpenSSL/Mcrypt extensions are unavailable", "zendframework/zend-servicemanager": ">= current version, if using the BigInteger::factory functionality" }, "extra": { "branch-alias": { "dev-master": "2.2-dev", "dev-develop": "2.3-dev" } }, "autoload-dev": { "psr-4": { "ZendTest\\Math\\": "test/" } }, "require-dev": { "fabpot/php-cs-fixer": "1.7.*", "satooshi/php-coveralls": "dev-master", "phpunit/PHPUnit": "~4.0" } }article { // Basic font style definitions font-size: 12pt; font-family: sans-serif; font-weight: normal; font-style: normal; line-height: 1.4; text-align: left; text-decoration: none; background-color: transparent; border: 0 solid #000; color: #2e3436; // Basic page layout definitions text-columns: 1; text-column-spacing: 10mm; direction: ltr; // Initilize general properties padding: 0mm; margin: 0mm; // General text layout options orphans: 3; widows: 3; } page { page-size: A4; page-orientation: portrait; padding: 22mm 16mm; // Margin for pages specifies an additional outer border, which can be used // to cut if off later, f.e. in printing margin: 0mm; } para { border: none; margin: 3mm 0mm 1mm 0mm; padding: 0mm; } emphasis { font-weight: bold; } ulink { text-decoration: underline; color: #204a87; } link { text-decoration: underline; color: #204a87; } title { font-family: serif; font-weight: bold; color: #000000; } title { font-size: 32pt; } section > title { font-size: 24pt; text-columns: 1; margin: 10mm 0mm 4mm 0mm; } section > section > title { font-size: 20pt; text-columns: 1; } section > section > section > title { font-size: 18pt; } section > section > section > section > title { font-size: 16pt; } section > section > section > section > section > title { font-size: 14pt; } section > section > section > section > section > section > title { font-size: 12pt; } literallayout { border: 1mm solid #d3d7d5; background-color: #f5f5f6; padding: 1; font-size: 10pt; font-family: monospace; } varlistentry > term { font-weight: bold; } varlistentry > listitem { padding-left: 5mm; margin-bottom: 3mm; } orderedlist > listitem { padding-left: 10mm; margin-bottom: 3mm; } itemizedlist > listitem { padding-left: 10mm; margin-bottom: 3mm; } listitem > para { margin: 0mm 0mm 4mm 0mm; } blockquote { margin: 2mm 0mm 4mm 10mm; } blockquote > attribution { margin: 1mm 0mm 1mm 5mm; font-style: italic; } table { margin: 2mm 0mm; border: 1px solid #babdb6; padding: 0px 1px 1px 0px; } table entry { margin: 1px 0px 0px 1px; border: 1px solid #d3d7d5; padding: 1mm; } table thead entry { font-weight: bold; } XHTML 1.0 (Second Edition) Strict in XML Schema This is the same as HTML 4 Strict except for changes due to the differences between XML and SGML. Namespace = http://www.w3.org/1999/xhtml For further information, see: http://www.w3.org/TR/xhtml1 Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio), All Rights Reserved. The DTD version is identified by the PUBLIC and SYSTEM identifiers: PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" $Id: xhtml1-strict.xsd,v 1.2 2002/08/28 08:05:44 mimasa Exp $ ================ Character mnemonic entities ========================= XHTML entity sets are identified by the PUBLIC and SYSTEM identifiers: PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent" PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent" PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN" SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent" ================== Imported Names ==================================== media type, as per [RFC2045] comma-separated list of media types, as per [RFC2045] a character encoding, as per [RFC2045] a space separated list of character encodings, as per [RFC2045] a language code, as per [RFC3066] a single character, as per section 2.2 of [XML] one or more digits tabindex attribute specifies the position of the current element in the tabbing order for the current document. This value must be a number between 0 and 32767. User agents should ignore leading zeros. space-separated list of link types single or comma-separated list of media descriptors a Uniform Resource Identifier, see [RFC2396] a space separated list of Uniform Resource Identifiers date and time information. ISO date format script expression style sheet data used for titles etc. nn for pixels or nn% for percentage length pixel, percentage, or relative integer representing length in pixels these are used for image maps comma separated list of lengths =================== Generic Attributes =============================== core attributes common to most elements id document-wide unique id class space separated list of classes style associated style info title advisory title/amplification internationalization attributes lang language code (backwards compatible) xml:lang language code (as per XML 1.0 spec) dir direction for weak/neutral text attributes for common UI events onclick a pointer button was clicked ondblclick a pointer button was double clicked onmousedown a pointer button was pressed down onmouseup a pointer button was released onmousemove a pointer was moved onto the element onmouseout a pointer was moved away from the element onkeypress a key was pressed and released onkeydown a key was pressed down onkeyup a key was released attributes for elements that can get the focus accesskey accessibility key character tabindex position in tabbing order onfocus the element got the focus onblur the element lost the focus =================== Text Elements ==================================== these can only occur at block level "Inline" covers inline or "text-level" elements ================== Block level elements ============================== "Flow" mixes block and inline and is used for list items etc. ================== Content models for exclusions ===================== a elements use "Inline" excluding a pre uses "Inline" excluding big, small, sup or sup form uses "Block" excluding form button uses "Flow" but excludes a, form and form controls ================ Document Structure ================================== ================ Document Head ======================================= content model is "head.misc" combined with a single title and an optional base element in any order The title element is not considered part of the flow of text. It should be displayed, for example as the page header or window title. Exactly one title is required per document. document base URI generic metainformation Relationship values can be used in principle: a) for document specific toolbars/menus when used with the link element in document head e.g. start, contents, previous, next, index, end, help b) to link to a separate style sheet (rel="stylesheet") c) to make a link to a script (rel="script") d) by stylesheets to control how collections of html nodes are rendered into printed documents e) to make a link to a printable version of this document e.g. a PostScript or PDF version (rel="alternate" media="print") style info, which may include CDATA sections script statements, which may include CDATA sections alternate content container for non script-based rendering =================== Document Body ==================================== generic language/style container =================== Paragraphs ======================================= =================== Headings ========================================= There are six levels of headings from h1 (the most important) to h6 (the least important). =================== Lists ============================================ Unordered list Ordered (numbered) list list item definition lists - dt for term, dd for its definition =================== Address ========================================== information on author =================== Horizontal Rule ================================== =================== Preformatted Text ================================ content is "Inline" excluding "img|object|big|small|sub|sup" =================== Block-like Quotes ================================ =================== Inserted/Deleted Text ============================ ins/del are allowed in block and inline content, but its inappropriate to include block content within an ins element occurring in inline content. ================== The Anchor Element ================================ content is "Inline" except that anchors shouldn't be nested ===================== Inline Elements ================================ generic language/style container I18N BiDi over-ride forced line break emphasis strong emphasis definitional program code sample something user would type variable citation abbreviation acronym inlined quote subscript superscript fixed pitch font italic font bold font bigger font smaller font ==================== Object ====================================== object is used to embed objects as part of HTML pages. param elements should precede other content. Parameters can also be expressed as attribute/value pairs on the object element itself when brevity is desired. param is used to supply a named property value. In XML it would seem natural to follow RDF and support an abbreviated syntax where the param elements are replaced by attribute value pairs on the object start tag. =================== Images =========================================== To avoid accessibility problems for people who aren't able to see the image, you should provide a text description using the alt and longdesc attributes. In addition, avoid the use of server-side image maps. Note that in this DTD there is no name attribute. That is only available in the transitional and frameset DTD. usemap points to a map element which may be in this document or an external document, although the latter is not widely supported ================== Client-side image maps ============================ These can be placed in the same document or grouped in a separate document although this isn't yet widely supported ================ Forms =============================================== Each label must not contain more than ONE field Label elements shouldn't be nested. form control the name attribute is required for all but submit & reset option selector option group selectable choice multi-line text field The fieldset element is used to group form fields. Only one legend element should occur in the content and if present should only be preceded by whitespace. NOTE: this content model is different from the XHTML 1.0 DTD, closer to the intended content model in HTML4 DTD fieldset label Content is "Flow" excluding a, form and form controls ======================= Tables ======================================= Derived from IETF HTML table standard, see [RFC1942] The border attribute sets the thickness of the frame around the table. The default units are screen pixels. The frame attribute specifies which parts of the frame around the table should be rendered. The values are not the same as CALS to avoid a name clash with the valign attribute. The rules attribute defines which rules to draw between cells: If rules is absent then assume: "none" if border is absent or border="0" otherwise "all" horizontal alignment attributes for cell contents char alignment char, e.g. char=':' charoff offset for alignment char vertical alignment attributes for cell contents Use thead to duplicate headers when breaking table across page boundaries, or for static headers when tbody sections are rendered in scrolling panel. Use tfoot to duplicate footers when breaking table across page boundaries, or for static footers when tbody sections are rendered in scrolling panel. Use multiple tbody sections when rules are needed between groups of table rows. colgroup groups a set of col elements. It allows you to group several semantically related columns together. col elements define the alignment properties for cells in one or more columns. The width attribute specifies the width of the columns, e.g. width=64 width in screen pixels width=0.5* relative width of 0.5 The span attribute causes the attributes of one col element to apply to more than one column. Scope is simpler than headers attribute for common tables th is for headers, td for data and for cells acting as both See http://www.w3.org/XML/1998/namespace.html and http://www.w3.org/TR/REC-xml for information about this namespace. This schema document describes the XML namespace, in a form suitable for import by other schema documents. Note that local names in this namespace are intended to be defined only by the World Wide Web Consortium or its subgroups. The following names are currently defined in this namespace and should not be used with conflicting semantics by any Working Group, specification, or document instance: base (as an attribute name): denotes an attribute whose value provides a URI to be used as the base for interpreting any relative URIs in the scope of the element on which it appears; its value is inherited. This name is reserved by virtue of its definition in the XML Base specification. id (as an attribute name): denotes an attribute whose value should be interpreted as if declared to be of type ID. This name is reserved by virtue of its definition in the xml:id specification. lang (as an attribute name): denotes an attribute whose value is a language code for the natural language of the content of any element; its value is inherited. This name is reserved by virtue of its definition in the XML specification. space (as an attribute name): denotes an attribute whose value is a keyword indicating what whitespace processing discipline is intended for the content of the element; its value is inherited. This name is reserved by virtue of its definition in the XML specification. Father (in any context at all): denotes Jon Bosak, the chair of the original XML Working Group. This name is reserved by the following decision of the W3C XML Plenary and XML Coordination groups: In appreciation for his vision, leadership and dedication the W3C XML Plenary on this 10th day of February, 2000 reserves for Jon Bosak in perpetuity the XML name xml:Father This schema defines attributes and an attribute group suitable for use by schemas wishing to allow xml:base, xml:lang, xml:space or xml:id attributes on elements they define. To enable this, such a schema must import this schema for the XML namespace, e.g. as follows: <schema . . .> . . . <import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/> Subsequently, qualified reference to any of the attributes or the group defined below will have the desired effect, e.g. <type . . .> . . . <attributeGroup ref="xml:specialAttrs"/> will define a type which will schema-validate an instance element with any of those attributes In keeping with the XML Schema WG's standard versioning policy, this schema document will persist at http://www.w3.org/2007/08/xml.xsd. At the date of issue it can also be found at http://www.w3.org/2001/xml.xsd. The schema document at that URI may however change in the future, in order to remain compatible with the latest version of XML Schema itself, or with the XML namespace itself. In other words, if the XML Schema or XML namespaces change, the version of this document at http://www.w3.org/2001/xml.xsd will change accordingly; the version at http://www.w3.org/2007/08/xml.xsd will not change. Attempting to install the relevant ISO 2- and 3-letter codes as the enumerated possible values is probably never going to be a realistic possibility. See RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry at http://www.iana.org/assignments/lang-tag-apps.htm for further information. The union allows for the 'un-declaration' of xml:lang with the empty string. See http://www.w3.org/TR/xmlbase/ for information about this attribute. See http://www.w3.org/TR/xml-id/ for information about this attribute. XHTML 1.0 (Second Edition) Transitional in XML Schema This is the same as HTML 4 Transitional except for changes due to the differences between XML and SGML. Namespace = http://www.w3.org/1999/xhtml For further information, see: http://www.w3.org/TR/xhtml1 Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio), All Rights Reserved. The DTD version is identified by the PUBLIC and SYSTEM identifiers: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" $Id: xhtml1-transitional.xsd,v 1.5 2002/08/28 09:53:29 mimasa Exp $ ================ Character mnemonic entities ========================= XHTML entity sets are identified by the PUBLIC and SYSTEM identifiers: PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent" PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent" PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN" SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent" ================== Imported Names ==================================== media type, as per [RFC2045] comma-separated list of media types, as per [RFC2045] a character encoding, as per [RFC2045] a space separated list of character encodings, as per [RFC2045] a language code, as per [RFC3066] a single character, as per section 2.2 of [XML] one or more digits tabindex attribute specifies the position of the current element in the tabbing order for the current document. This value must be a number between 0 and 32767. User agents should ignore leading zeros. space-separated list of link types single or comma-separated list of media descriptors a Uniform Resource Identifier, see [RFC2396] a space separated list of Uniform Resource Identifiers date and time information. ISO date format script expression style sheet data used for titles etc. render in this frame nn for pixels or nn% for percentage length pixel, percentage, or relative integer representing length in pixels these are used for image maps comma separated list of lengths used for object, applet, img, input and iframe a color using sRGB: #RRGGBB as Hex values There are also 16 widely known color names with their sRGB values: Black = #000000 Green = #008000 Silver = #C0C0C0 Lime = #00FF00 Gray = #808080 Olive = #808000 White = #FFFFFF Yellow = #FFFF00 Maroon = #800000 Navy = #000080 Red = #FF0000 Blue = #0000FF Purple = #800080 Teal = #008080 Fuchsia= #FF00FF Aqua = #00FFFF =================== Generic Attributes =============================== core attributes common to most elements id document-wide unique id class space separated list of classes style associated style info title advisory title/amplification internationalization attributes lang language code (backwards compatible) xml:lang language code (as per XML 1.0 spec) dir direction for weak/neutral text attributes for common UI events onclick a pointer button was clicked ondblclick a pointer button was double clicked onmousedown a pointer button was pressed down onmouseup a pointer button was released onmousemove a pointer was moved onto the element onmouseout a pointer was moved away from the element onkeypress a key was pressed and released onkeydown a key was pressed down onkeyup a key was released attributes for elements that can get the focus accesskey accessibility key character tabindex position in tabbing order onfocus the element got the focus onblur the element lost the focus text alignment for p, div, h1-h6. The default is align="left" for ltr headings, "right" for rtl =================== Text Elements ==================================== these can only occur at block level these can only occur at block level "Inline" covers inline or "text-level" element ================== Block level elements ============================== "Flow" mixes block and inline and is used for list items etc. ================== Content models for exclusions ===================== a elements use "Inline" excluding a pre uses "Inline" excluding img, object, applet, big, small, font, or basefont form uses "Flow" excluding form button uses "Flow" but excludes a, form, form controls, iframe ================ Document Structure ================================== ================ Document Head ======================================= content model is "head.misc" combined with a single title and an optional base element in any order The title element is not considered part of the flow of text. It should be displayed, for example as the page header or window title. Exactly one title is required per document. document base URI generic metainformation Relationship values can be used in principle: a) for document specific toolbars/menus when used with the link element in document head e.g. start, contents, previous, next, index, end, help b) to link to a separate style sheet (rel="stylesheet") c) to make a link to a script (rel="script") d) by stylesheets to control how collections of html nodes are rendered into printed documents e) to make a link to a printable version of this document e.g. a PostScript or PDF version (rel="alternate" media="print") style info, which may include CDATA sections script statements, which may include CDATA sections alternate content container for non script-based rendering ======================= Frames ======================================= inline subwindow alternate content container for non frame-based rendering =================== Document Body ==================================== generic language/style container =================== Paragraphs ======================================= =================== Headings ========================================= There are six levels of headings from h1 (the most important) to h6 (the least important). =================== Lists ============================================ Unordered list bullet styles Unordered list Ordered list numbering style 1 arabic numbers 1, 2, 3, ... a lower alpha a, b, c, ... A upper alpha A, B, C, ... i lower roman i, ii, iii, ... I upper roman I, II, III, ... The style is applied to the sequence number which by default is reset to 1 for the first list item in an ordered list. Ordered (numbered) list single column list (DEPRECATED) multiple column list (DEPRECATED) LIStyle is constrained to: "(ULStyle|OLStyle)" list item definition lists - dt for term, dd for its definition =================== Address ========================================== information on author =================== Horizontal Rule ================================== =================== Preformatted Text ================================ content is "Inline" excluding "img|object|applet|big|small|sub|sup|font|basefont" =================== Block-like Quotes ================================ =================== Text alignment =================================== center content =================== Inserted/Deleted Text ============================ ins/del are allowed in block and inline content, but its inappropriate to include block content within an ins element occurring in inline content. ================== The Anchor Element ================================ content is "Inline" except that anchors shouldn't be nested ===================== Inline Elements ================================ generic language/style container I18N BiDi over-ride forced line break emphasis strong emphasis definitional program code sample something user would type variable citation abbreviation acronym inlined quote subscript superscript fixed pitch font italic font bold font bigger font smaller font underline strike-through strike-through base font size local change to font ==================== Object ====================================== object is used to embed objects as part of HTML pages. param elements should precede other content. Parameters can also be expressed as attribute/value pairs on the object element itself when brevity is desired. param is used to supply a named property value. In XML it would seem natural to follow RDF and support an abbreviated syntax where the param elements are replaced by attribute value pairs on the object start tag. =================== Java applet ================================== One of code or object attributes must be present. Place param elements before other content. =================== Images =========================================== To avoid accessibility problems for people who aren't able to see the image, you should provide a text description using the alt and longdesc attributes. In addition, avoid the use of server-side image maps. usemap points to a map element which may be in this document or an external document, although the latter is not widely supported ================== Client-side image maps ============================ These can be placed in the same document or grouped in a separate document although this isn't yet widely supported ================ Forms =============================================== Each label must not contain more than ONE field Label elements shouldn't be nested. form control the name attribute is required for all but submit & reset option selector option group selectable choice multi-line text field The fieldset element is used to group form fields. Only one legend element should occur in the content and if present should only be preceded by whitespace. NOTE: this content model is different from the XHTML 1.0 DTD, closer to the intended content model in HTML4 DTD fieldset label Content is "Flow" excluding a, form and form controls single-line text input control (DEPRECATED) ======================= Tables ======================================= Derived from IETF HTML table standard, see [RFC1942] The border attribute sets the thickness of the frame around the table. The default units are screen pixels. The frame attribute specifies which parts of the frame around the table should be rendered. The values are not the same as CALS to avoid a name clash with the valign attribute. The rules attribute defines which rules to draw between cells: If rules is absent then assume: "none" if border is absent or border="0" otherwise "all" horizontal placement of table relative to document horizontal alignment attributes for cell contents char alignment char, e.g. char=':' charoff offset for alignment char vertical alignment attributes for cell contents Use thead to duplicate headers when breaking table across page boundaries, or for static headers when tbody sections are rendered in scrolling panel. Use tfoot to duplicate footers when breaking table across page boundaries, or for static footers when tbody sections are rendered in scrolling panel. Use multiple tbody sections when rules are needed between groups of table rows. colgroup groups a set of col elements. It allows you to group several semantically related columns together. col elements define the alignment properties for cells in one or more columns. The width attribute specifies the width of the columns, e.g. width=64 width in screen pixels width=0.5* relative width of 0.5 The span attribute causes the attributes of one col element to apply to more than one column. Scope is simpler than headers attribute for common tables th is for headers, td for data and for cells acting as both 1.2 boolean short int long double string datetime base64Binary simple onRequest simple replace onLoad new replace float date time boolean string true none condition simple embed simple onRequest new replace footnote endnote previous current next previous next name number number-and-name plain-number-and-name plain-number full path name name-and-extension full path name name-and-extension area title text:page-count text:paragraph-count text:word-count text:character-count text:table-count text:image-count text:object-count table query command text table text-box image object text:reference-ref text:bookmark-ref number-no-superior number-all-superior number category-and-value caption value page chapter direction text simple value unit gap float percentage currency date time boolean string value none value formula none value formula text:identifier text:address text:annote text:author text:booktitle text:chapter text:edition text:editor text:howpublished text:institution text:journal text:month text:note text:number text:organizations text:pages text:publisher text:school text:series text:title text:report-type text:volume text:year text:url text:custom1 text:custom2 text:custom3 text:custom4 text:custom5 text:isbn text:issn article book booklet conference custom1 custom2 custom3 custom4 custom5 email inbook incollection inproceedings journal manual mastersthesis misc phdthesis proceedings techreport unpublished www document chapter document chapter text category-and-value caption simple 1 2 3 separator name number number-and-name plain-number plain-number-and-name address annote author bibliography-type booktitle chapter custom1 custom2 custom3 custom4 custom5 edition editor howpublished identifier institution isbn issn journal month note number organizations pages publisher report-type school series title url volume year right left visible collapse filter ($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+ ($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+(:($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+$?[0-9]+)? ($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+:($?([^\. ']+|'([^']|'')+'))?\.$?[0-9]+ ($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+:($?([^\. ']+|'([^']|'')+'))?\.$?[A-Z]+ copy-all copy-results-only simple onRequest trace-dependents remove-dependents trace-precedents remove-precedents trace-errors from-another-table to-another-table from-same-table date enable disable none unsorted sort-ascending stop warning information column row none print-range filter repeat-row repeat-column column row alpha-numeric integer double text number automatic ascending descending text number automatic ascending descending auto average count countnums max min product stdev stdevp sum var varp self cell-range text number none row column both row column data hidden page auto average count countnums max min product stdev stdevp sum var varp auto average count countnums max min product stdev stdevp sum var varp from-top from-bottom data none manual name ascending descending tabular-layout outline-subtotals-top outline-subtotals-bottom named previous next none member-difference member-percentage member-percentage-difference running-total row-percentage column-percentage total-percentage index auto auto auto auto seconds minutes hours days months quarters years auto average count countnums max min product stdev stdevp sum var varp none row column both row column table row column table accepted rejected pending always screen printer none false true full section cut arc standard lines line curve page frame paragraph char as-char top-left top top-right left center right bottom-left bottom-right auto left right up down horizontal vertical scale scale-min scale scale-min simple embed onLoad simple onRequest new replace simple new replace nohref parallel perspective flat phong gouraud draft non-primitive flat phong gouraud draft parallel perspective \([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))([ ]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))){2}[ ]*\) -0.5 0.5 none segments rectangle normal path shape path shape title outline subtitle text graphic object chart table orgchart page notes handout header footer date-time page-number simple onRequest new replace none fade move stripes open close dissolve wavyline random lines laser appear hide move-short checkerboard rotate stretch none from-left from-top from-right from-bottom from-center from-upper-left from-upper-right from-lower-left from-lower-right to-left to-top to-right to-bottom to-upper-left to-upper-right to-lower-right to-lower-left path spiral-inward-left spiral-inward-right spiral-outward-left spiral-outward-right vertical horizontal to-center clockwise counter-clockwise slow medium fast default on-click with-previous after-previous timing-root main-sequence interactive-sequence custom entrance exit emphasis motion-path ole-action media-call none previous-page next-page first-page last-page hide stop execute show verb fade-out sound last-visited-page simple embed onRequest fixed current-date enabled disabled enabled disabled simple start end top bottom start center end top-start bottom-start top-end bottom-end wide high balanced custom none row column both x y z major minor simple simple none onRequest simple none onRequest equal-integer is-boolean equal-boolean equal-use-only-zero boolean short int long double string simple none onRequest bit boolean tinyint smallint integer bigint float real double numeric decimal char varchar longvarchar date time timestmp binary varbinary longvarbinary sqlnull other object distinct struct array blob clob ref no-nulls nullable primary unique foreign cascade restrict set-null no-action set-default cascade restrict set-null no-action set-default simple onRequest get post table query command none current parent records current page selection selection-indexes unchecked checked unknown horizontal vertical submit reset push url flat 3d center start end top bottom start center end table query sql sql-pass-through value-list table-fields void float percentage currency date time boolean string void 1 i I a A simple onRequest into-default-style-data-style into-english-number keep-text discrete linear paced spline rgb hsl clockwise counter-clockwise translate scale rotate skewX skewY forward reverse in out discrete linear paced spline none sum replace sum first last all media indefinite 0.0 remove freeze hold auto default transition remove freeze hold transition auto inherit never always whenNotActive default never always whenNotActive inherit 0 1 all left right mirrored row column normal ultra-condensed extra-condensed condensed semi-condensed semi-expanded expanded extra-expanded ultra-expanded simple onRequest short long short long short long short long short long short long short long short long short long fixed language short medium long gregorian gengou ROC hanja_yoil hanja hijri jewish buddhist text paragraph section ruby left right inner outer document chapter page text page section document address annote author bibliography-type booktitle chapter custom1 custom2 custom3 custom4 custom5 edition editor howpublished identifier institution isbn issn journal month note number organizations pages publisher report-type school series title url volume year table table-column table-row table-cell graphic presentation drawing-page linear axial radial ellipsoid square rectangular objectBoundingBox pad reflect repeat single double triple simple embed onLoad rect round chart default portrait landscape headers grid annotations objects charts drawings formulas zero-values ttb ltr continue horizontal vertical both none left center right none line both normal small-caps none lowercase uppercase capitalize font-color super sub roman swiss modern decorative script system fixed variable [A-Za-z][A-Za-z0-9._\-]* latin asian complex ignore normal normal italic oblique none embossed engraved none none single double none solid dotted dash long-dash dot-dash dot-dot-dash wave auto normal bold thin dash medium thick font-color font-color normal bold 100 200 300 400 500 600 700 800 900 continuous skip-white-space none letters lines none none accent dot circle disc above below 0 90 270 fixed line-height true none condition none normal start end left right center justify start center justify auto always left center right char font-color auto page no-limit word auto column page auto column page transparent no-repeat repeat stretch left center right top bottom left center right top center bottom auto always none ideograph-alpha simple hanging normal strict top middle bottom auto baseline lr-tb rl-tb tb-rl tb-lr lr rl tb page auto above below left center right distribute-letter distribute-space none solid dotted dashed dot-dashed top middle bottom left center right margins collapsing separating auto always top middle bottom automatic fix value-type ltr ttb auto 0 0deg 0rad 0grad no-wrap wrap none bottom top center none hidden-and-protected protected formula-hidden label-width-and-position label-alignment listtab space nothing none dash solid 0 1 miter round bevel middle none butt square round none solid bitmap gradient hatch no-repeat repeat stretch top-left top top-right left center right bottom-left bottom bottom-right horizontal vertical nonzero evenodd none scroll alternate slide left right up down top middle bottom justify left center right justify no-wrap wrap greyscale mono watermark standard visible hidden below above automatic left-outside inside right-outside automatic above below center automatic mm cm m km pt pc inch ft mi straight-line angled-line angled-connector-line fixed free horizontal vertical auto correct attractive enabled disabled standard double-sided object flat sphere normal inverse object parallel sphere object parallel sphere luminance intensity color enabled disabled replace modulate blend visible hidden none content position size left center right from-left inside outside from-inside page page-content page-start-margin page-end-margin frame frame-content frame-start-margin frame-end-margin paragraph paragraph-content paragraph-start-margin paragraph-end-margin char top middle bottom from-top below page page-content frame frame-content paragraph paragraph-content char line baseline text none left right parallel dynamic run-through biggest no-limit full outside foreground background clip auto-create-new-frame none vertical vertical vertical horizontal horizontal-on-odd horizontal-on-even auto rect\([ ]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)))|(auto))([ ]*,[ ]*((-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc))))|(auto)){3}[ ]*\) iterative once-concurrent once-successive ([0-9]+(\.[0-9]*)?|\.[0-9]+)(px) content thumbnail icon print-view none automatic named-symbol square diamond arrow-down arrow-up arrow-right arrow-left bow-tie hourglass circle star x plus asterisk horizontal-bar vertical-bar image none cubic-spline b-spline cuboid cylinder cone pyramid use-zero leave-gap ignore side-by-side stagger-even stagger-odd none value percentage value-and-percentage avoid-overlap center top top-right right bottom-right bottom bottom-left left top-left inside outside near-origin none variance standard-deviation percentage error-margin constant standard-error cell-range columns rows none linear logarithmic exponential power start end near-axis near-axis-other-side outside-start outside-end at-labels at-axis at-labels-and-axis manual automatic semi-automatic none fade-from-left fade-from-top fade-from-right fade-from-bottom fade-from-upperleft fade-from-upperright fade-from-lowerleft fade-from-lowerright move-from-left move-from-top move-from-right move-from-bottom move-from-upperleft move-from-upperright move-from-lowerleft move-from-lowerright uncover-to-left uncover-to-top uncover-to-right uncover-to-bottom uncover-to-upperleft uncover-to-upperright uncover-to-lowerleft uncover-to-lowerright fade-to-center fade-from-center vertical-stripes horizontal-stripes clockwise counterclockwise open-vertical open-horizontal close-vertical close-horizontal wavyline-from-left wavyline-from-top wavyline-from-right wavyline-from-bottom spiralin-left spiralin-right spiralout-left spiralout-right roll-from-top roll-from-left roll-from-right roll-from-bottom stretch-from-left stretch-from-top stretch-from-right stretch-from-bottom vertical-lines horizontal-lines dissolve random vertical-checkerboard horizontal-checkerboard interlocking-horizontal-left interlocking-horizontal-right interlocking-vertical-top interlocking-vertical-bottom fly-away open close melt forward reverse visible hidden full border true false [A-Za-z0-9]{1,8} [A-Za-z]{1,8} [A-Za-z0-9]{1,8} 1 -?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px)) ([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px)) ([0-9]*[1-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)) -?([0-9]+(\.[0-9]*)?|\.[0-9]+)% ([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)% -?([0-9]?[0-9](\.[0-9]*)?|100(\.0*)?|\.[0-9]+)% [0-9]+\* #[0-9a-fA-F]{6} (([\i-[:]][\c-[:]]*)?:)?.+ 1 \[(([\i-[:]][\c-[:]]*)?:)?.+\] 3 _self _blank _parent _top float time date percentage currency boolean string -?[0-9]+,-?[0-9]+([ ]+-?[0-9]+,-?[0-9]+)* \([ ]*-?([0-9]+(\.[0-9]*)?|\.[0-9]+)([ ]+-?([0-9]+(\.[0-9]*)?|\.[0-9]+)){2}[ ]*\) [0-9a-zA-Z_]+:[0-9a-zA-Z._\-]+ body { background-color: #ffffff; color: #2e3436; font-family: sans-serif; } a { color: #3456a4 } a:hover { color: #729fcf; } a:visited { color: #204a87; } a.footnote { vertical-align: super; } p { margin: 0.5em 0em 1em 0em; } hr { background-color: #204a87; border: none; height: 1px; } pre { background-color: #eeeeef; font-family: monospace; } table { border: 1px solid #babdb6; border-collapse: collapse; width: 100%; } thead td, thead th { background-color: #eeeeef; text-align: center; font-weight: bold; } tbody td { border: 1px solid #babdb6; } blockquote p:before, blockquote p:after { content: '"'; } blockquote p { margin-bottom: .5em; } blockquote cite { margin-left: 1em; color: #555753; } div.image, div.figure { margin: 1em; padding: 1px; border: 1px solid #babdb6; } div.image img, div.figure img { margin: 0px auto; } div.image p, div.figure p { margin: 0em; font-size: 90%; color: #555753; } p.note { margin-left: 2em; padding: .2em; border: 1px solid #8ae234; } p.notice { margin-left: 2em; padding: .2em; border: 1px solid #4e9a06; } p.warning { margin-left: 2em; padding: .2em; border: 1px solid #ce5c00; } p.attention { margin-left: 2em; padding: .2em; border: 1px solid #a40000; } p.danger { margin-left: 2em; padding: .2em; border: 2px solid #a40000; } ") * @Serializer\XmlList(entry = "plugin") * @Merger\Replace */ protected $plugins = array(); /** * @var Transformations[] contains a list of all templates and custom transformations that are to be executed during * the transformation process. * @Serializer\Type("phpDocumentor\Transformer\Configuration\Transformations") */ protected $transformations; /** * @var Translator\Configuration The settings used during translation. * @Serializer\Type("phpDocumentor\Translator\Configuration") */ protected $translator; /** * @var Partial[] A list of custom texts, or references thereto, that may be injected into templates. * @Serializer\Type("array") */ protected $partials = array(); /** * Initializes all settings with their default values. */ public function __construct() { $this->transformer = new Transformer\Configuration(); $this->transformations = new Transformer\Configuration\Transformations(); $this->files = new Parser\Configuration\Files(); $this->parser = new Parser\Configuration(); $this->logging = new Logging(); $this->translator = new Translator\Configuration(); } /** * Returns the title for the generated documentation. * * @return string */ public function getTitle() { return $this->title; } /** * Returns the configuration related to which files are to be parsed. * * @return Parser\Configuration\Files */ public function getFiles() { return $this->files; } /** * Returns the settings related to logging. * * @return Configuration\Logging */ public function getLogging() { return $this->logging; } /** * Returns the configuration used by the parser. * * @return Parser\Configuration */ public function getParser() { return $this->parser; } /** * Returns all partials that can be imported in the application. * * @return Partials\Partial[] */ public function getPartials() { return $this->partials; } /** * Returns a list of all plugins that should be loaded by the application. * * @return Plugin[] */ public function getPlugins() { return $this->plugins; } /** * Returns which templates and custom transformations need to be applied to the parsed data. * * @return Transformer\Configuration\Transformations */ public function getTransformations() { return $this->transformations; } /** * Returns the settings for the transformer. * * @return Transformer\Configuration */ public function getTransformer() { return $this->transformer; } /** * Returns the settings for the translator. * * @return Translator\Configuration */ public function getTranslator() { return $this->translator; } } setInterfaces(new Collection()); $this->setUsedTraits(new Collection()); $this->setConstants(new Collection()); $this->setProperties(new Collection()); $this->setMethods(new Collection()); } /** * {@inheritDoc} */ public function setParent($parents) { $this->parent = $parents; } /** * {@inheritDoc} */ public function getParent() { return $this->parent; } /** * {@inheritDoc} */ public function setInterfaces(Collection $implements) { $this->implements = $implements; } /** * {@inheritDoc} */ public function getInterfaces() { return $this->implements; } /** * {@inheritDoc} */ public function setFinal($final) { $this->final = $final; } /** * {@inheritDoc} */ public function isFinal() { return $this->final; } /** * {@inheritDoc} */ public function setAbstract($abstract) { $this->abstract = $abstract; } /** * {@inheritDoc} */ public function isAbstract() { return $this->abstract; } /** * {@inheritDoc} */ public function setConstants(Collection $constants) { $this->constants = $constants; } /** * {@inheritDoc} */ public function getConstants() { return $this->constants; } /** * {@inheritDoc} */ public function getInheritedConstants() { if (!$this->getParent() || (!$this->getParent() instanceof ClassDescriptor)) { return new Collection(); } $inheritedConstants = clone $this->getParent()->getConstants(); return $inheritedConstants->merge($this->getParent()->getInheritedConstants()); } /** * {@inheritDoc} */ public function setMethods(Collection $methods) { $this->methods = $methods; } /** * {@inheritDoc} */ public function getMethods() { return $this->methods; } /** * {@inheritDoc} */ public function getInheritedMethods() { $inheritedMethods = new Collection(); foreach ($this->getUsedTraits() as $trait) { if (!$trait instanceof TraitDescriptor) { continue; } $inheritedMethods = $inheritedMethods->merge(clone $trait->getMethods()); } if (!$this->getParent() || (!$this->getParent() instanceof ClassDescriptor)) { return $inheritedMethods; } $inheritedMethods = $inheritedMethods->merge(clone $this->getParent()->getMethods()); return $inheritedMethods->merge($this->getParent()->getInheritedMethods()); } /** * @return Collection */ public function getMagicMethods() { /** @var Collection $methodTags */ $methodTags = clone $this->getTags()->get('method', new Collection()); $methods = new Collection(); /** @var Tag\MethodDescriptor $methodTag */ foreach ($methodTags as $methodTag) { $method = new MethodDescriptor(); $method->setName($methodTag->getMethodName()); $method->setDescription($methodTag->getDescription()); $method->setParent($this); $returnTags = $method->getTags()->get('return', new Collection()); $returnTags->add($methodTag->getResponse()); foreach ($methodTag->getArguments() as $name => $argument) { $method->addArgument($name, $argument); } $methods->add($method); } if ($this->getParent() instanceof static) { $methods = $methods->merge($this->getParent()->getMagicMethods()); } return $methods; } /** * {@inheritDoc} */ public function setProperties(Collection $properties) { $this->properties = $properties; } /** * {@inheritDoc} */ public function getProperties() { return $this->properties; } /** * {@inheritDoc} */ public function getInheritedProperties() { $inheritedProperties = new Collection(); foreach ($this->getUsedTraits() as $trait) { if (!$trait instanceof TraitDescriptor) { continue; } $inheritedProperties = $inheritedProperties->merge(clone $trait->getProperties()); } if (!$this->getParent() || (!$this->getParent() instanceof ClassDescriptor)) { return $inheritedProperties; } $inheritedProperties = $inheritedProperties->merge(clone $this->getParent()->getProperties()); return $inheritedProperties->merge($this->getParent()->getInheritedProperties()); } /** * @return Collection */ public function getMagicProperties() { /** @var Collection $propertyTags */ $propertyTags = clone $this->getTags()->get('property', new Collection()); $propertyTags = $propertyTags->merge($this->getTags()->get('property-read', new Collection())); $propertyTags = $propertyTags->merge($this->getTags()->get('property-write', new Collection())); $properties = new Collection(); /** @var Tag\PropertyDescriptor $propertyTag */ foreach ($propertyTags as $propertyTag) { $property = new PropertyDescriptor(); $property->setName(ltrim($propertyTag->getVariableName(), '$')); $property->setDescription($propertyTag->getDescription()); $property->setTypes($propertyTag->getTypes()); $property->setParent($this); $properties->add($property); } if ($this->getParent() instanceof ClassDescriptor) { $properties = $properties->merge($this->getParent()->getMagicProperties()); } return $properties; } /** * @param string $package */ public function setPackage($package) { parent::setPackage($package); foreach ($this->getConstants() as $constant) { // TODO #840: Workaround; for some reason there are NULLs in the constants array. if ($constant) { $constant->setPackage($package); } } foreach ($this->getProperties() as $property) { // TODO #840: Workaround; for some reason there are NULLs in the properties array. if ($property) { $property->setPackage($package); } } foreach ($this->getMethods() as $method) { // TODO #840: Workaround; for some reason there are NULLs in the methods array. if ($method) { $method->setPackage($package); } } } /** * Sets a collection of all traits used by this class. * * @param Collection $usedTraits * * @return void */ public function setUsedTraits($usedTraits) { $this->usedTraits = $usedTraits; } /** * Returns the traits used by this class. * * Returned values may either be a string (when the Trait is not in this project) or a TraitDescriptor. * * @return Collection */ public function getUsedTraits() { return $this->usedTraits; } public function getInheritedElement() { return $this->getParent(); } } getFilePath(); $file = $this->getExampleFileContents($filename); if (! $file) { return "** File not found : {$filename} **"; } return implode('', array_slice($file, $descriptor->getStartingLine() - 1, $descriptor->getLineCount())); } /** * Registers the project's root directory where an 'examples' folder can be expected. * * @param string $directory * * @return void */ public function setSourceDirectory($directory = '') { $this->sourceDirectory = $directory; } /** * Returns the project's root directory where an 'examples' folder can be expected. * * @return string */ public function getSourceDirectory() { return $this->sourceDirectory; } /** * Registers a series of directories that may contain examples. * * @param string[] $directories */ public function setExampleDirectories(array $directories) { $this->exampleDirectories = $directories; } /** * Returns a series of directories that may contain examples. * * @return string[] */ public function getExampleDirectories() { return $this->exampleDirectories; } /** * Attempts to find the requested example file and returns its contents or null if no file was found. * * This method will try several methods in search of the given example file, the first one it encounters is * returned: * * 1. Iterates through all examples folders for the given filename * 2. Checks the source folder for the given filename * 3. Checks the 'examples' folder in the current working directory for examples * 4. Checks the path relative to the current working directory for the given filename * * @param string $filename * * @return string|null */ private function getExampleFileContents($filename) { $normalizedPath = null; foreach ($this->exampleDirectories as $directory) { $exampleFileFromConfig = $this->constructExamplePath($directory, $filename); if (is_readable($exampleFileFromConfig)) { $normalizedPath = $exampleFileFromConfig; break; } } if (! $normalizedPath) { if (is_readable($this->getExamplePathFromSource($filename))) { $normalizedPath = $this->getExamplePathFromSource($filename); } elseif (is_readable($this->getExamplePathFromExampleDirectory($filename))) { $normalizedPath = $this->getExamplePathFromExampleDirectory($filename); } elseif (is_readable($filename)) { $normalizedPath = $filename; } } return $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : null; } /** * Get example filepath based on the example directory inside your project. * * @param string $file * * @return string */ private function getExamplePathFromExampleDirectory($file) { return getcwd() . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $file; } /** * Returns a path to the example file in the given directory.. * * @param string $directory * @param string $file * * @return string */ private function constructExamplePath($directory, $file) { return rtrim($directory, '\\/') . DIRECTORY_SEPARATOR . $file; } /** * Get example filepath based on sourcecode. * * @param string $file * * @return string */ private function getExamplePathFromSource($file) { return sprintf( '%s%s%s', trim($this->getSourceDirectory(), '\\/'), DIRECTORY_SEPARATOR, trim($file, '"') ); } } setArguments(new Collection()); } /** * @param ClassDescriptor|InterfaceDescriptor|TraitDescriptor $parent */ public function setParent($parent) { $this->setFullyQualifiedStructuralElementName( $parent->getFullyQualifiedStructuralElementName() . '::' . $this->getName() . '()' ); // reset cached inherited element so that it can be re-detected. $this->inheritedElement = null; $this->parent = $parent; } /** * @return ClassDescriptor|InterfaceDescriptor|TraitDescriptor */ public function getParent() { return $this->parent; } /** * {@inheritDoc} */ public function setAbstract($abstract) { $this->abstract = $abstract; } /** * {@inheritDoc} */ public function isAbstract() { return $this->abstract; } /** * {@inheritDoc} */ public function setFinal($final) { $this->final = $final; } /** * {@inheritDoc} */ public function isFinal() { return $this->final; } /** * {@inheritDoc} */ public function setStatic($static) { $this->static = $static; } /** * {@inheritDoc} */ public function isStatic() { return $this->static; } /** * {@inheritDoc} */ public function setVisibility($visibility) { $this->visibility = $visibility; } /** * {@inheritDoc} */ public function getVisibility() { return $this->visibility; } /** * {@inheritDoc} */ public function setArguments(Collection $arguments) { foreach( $arguments as $argument) { $argument->setMethod($this); } $this->arguments = $arguments; } /** * @param string $name * @param ArgumentDescriptor $argument */ public function addArgument($name, ArgumentDescriptor $argument) { $argument->setMethod($this); $this->arguments->set($name, $argument); } /** * {@inheritDoc} */ public function getArguments() { return $this->arguments; } /** * {@inheritDoc} */ public function getResponse() { /** @var Collection|null $returnTags */ $returnTags = $this->getReturn(); return $returnTags instanceof Collection && $returnTags->count() > 0 ? current($returnTags->getAll()) : null; } /** * Returns the file associated with the parent class, interface or trait. * * @return FileDescriptor */ public function getFile() { return $this->getParent()->getFile(); } /** * @return Collection */ public function getReturn() { /** @var Collection $var */ $var = $this->getTags()->get('return', new Collection()); if ($var->count() != 0) { return $var; } $inheritedElement = $this->getInheritedElement(); if ($inheritedElement) { return $inheritedElement->getReturn(); } return new Collection(); } /** * @return Collection */ public function getParam() { /** @var Collection $var */ $var = $this->getTags()->get('param', new Collection()); if ($var instanceof Collection && $var->count() > 0) { return $var; } $inheritedElement = $this->getInheritedElement(); if ($inheritedElement) { return $inheritedElement->getParam(); } return new Collection(); } /** * Returns the Method from which this method should inherit its information, if any. * * The inheritance scheme for a method is more complicated than for most elements; the following business rules * apply: * * 1. if the parent class/interface extends another class or other interfaces (interfaces have multiple * inheritance!) then: * 1. Check each parent class/interface's parent if they have a method with the exact same name * 2. if a method is found with the same name; return the first one encountered. * 2. if the parent is a class and implements interfaces, check each interface for a method with the exact same * name. If such a method is found, return the first hit. * * @return MethodDescriptor|null */ public function getInheritedElement() { if ($this->inheritedElement !== null) { return $this->inheritedElement; } /** @var ClassDescriptor|InterfaceDescriptor|null $associatedClass */ $associatedClass = $this->getParent(); if (!$associatedClass instanceof ClassDescriptor && !$associatedClass instanceof InterfaceDescriptor) { return null; } /** @var ClassDescriptor|InterfaceDescriptor $parentClass|null */ $parentClass = $associatedClass->getParent(); if ($parentClass instanceof ClassDescriptor || $parentClass instanceof Collection) { // the parent of a class is always a class, but the parent of an interface is a collection of interfaces. $parents = $parentClass instanceof ClassDescriptor ? array($parentClass) : $parentClass->getAll(); foreach ($parents as $parent) { if ($parent instanceof ClassDescriptor || $parent instanceof InterfaceDescriptor) { $parentMethod = $parent->getMethods()->get($this->getName()); if ($parentMethod) { $this->inheritedElement = $parentMethod; return $this->inheritedElement; } } } } // also check all implemented interfaces next if the parent is a class and not an interface if ($associatedClass instanceof ClassDescriptor) { /** @var InterfaceDescriptor $interface */ foreach ($associatedClass->getInterfaces() as $interface) { if (!$interface instanceof InterfaceDescriptor) { continue; } $parentMethod = $interface->getMethods()->get($this->getName()); if ($parentMethod) { $this->inheritedElement = $parentMethod; return $this->inheritedElement; } } } return null; } } unresolvedParentClassesCount = 0; $elementCounter = array(); foreach ($this->findAllElements($projectDescriptor) as $element) { $elementCounter = $this->addElementToCounter($elementCounter, $element); $this->incrementUnresolvedParentCounter($element); } $this->descriptorCountByType = $elementCounter; $this->fileCount = count($projectDescriptor->getFiles()); $this->topLevelNamespaceCount = count($projectDescriptor->getNamespace()->getChildren()); } /** * Returns a textual report of the findings of this class. * * @return string */ public function __toString() { $logString = <<descriptorCountByType as $class => $count) { $logString .= sprintf(' %8d %s elements' . PHP_EOL, $count, $class); } return sprintf( $logString, $this->fileCount, $this->topLevelNamespaceCount, $this->unresolvedParentClassesCount ); } /** * Increments the counter for element's class in the class counters. * * @param array $classCounters * @param DescriptorAbstract $element * * @return array */ protected function addElementToCounter($classCounters, $element) { if (!isset($classCounters[get_class($element)])) { $classCounters[get_class($element)] = 0; } $classCounters[get_class($element)]++; return $classCounters; } /** * Checks whether the given element is a class and if its parent could not be resolved; increment the counter. * * @param DescriptorAbstract $element */ protected function incrementUnresolvedParentCounter($element) { if (!$element instanceof ClassDescriptor) { return; } if (is_string($element->getParent())) { $this->unresolvedParentClassesCount++; } } /** * Returns all elements from the project descriptor. * * @param ProjectDescriptor $projectDescriptor * * @return DescriptorAbstract[] */ protected function findAllElements(ProjectDescriptor $projectDescriptor) { return $projectDescriptor->getIndexes()->get('elements', new Collection()); } } setArguments(new Collection()); } /** * {@inheritDoc} */ public function setArguments(Collection $arguments) { $this->arguments = $arguments; } /** * {@inheritDoc} */ public function getArguments() { return $this->arguments; } /** * {@inheritDoc} */ public function getResponse() { /** @var Collection|null $returnTags */ $returnTags = $this->getTags()->get('return'); return $returnTags instanceof Collection ? current($returnTags->getAll()) : null; } } setName($name); $this->errors = new Collection(); } /** * Sets the name for this tag. * * @param string $name * * @return void */ protected function setName($name) { $this->name = $name; } /** * Returns the name for this tag. * * @return string */ public function getName() { return $this->name; } /** * Sets a description for this tab instance. * * @param string $description * * @return void */ public function setDescription($description) { $this->description = $description; } /** * Returns the description for this tag, * * @return string */ public function getDescription() { return $this->description; } /** * Sets a list of errors found on the usage of this tag. * * @param Collection $errors * * @return void */ public function setErrors(Collection $errors) { $this->errors = $errors; } /** * Returns all errors associated with this tag. * * @return Collection */ public function getErrors() { return $this->errors; } } setProperties(new Collection()); $this->setMethods(new Collection()); $this->setUsedTraits(new Collection()); } /** * {@inheritDoc} */ public function setMethods(Collection $methods) { $this->methods = $methods; } /** * {@inheritDoc} */ public function getMethods() { return $this->methods; } /** * {@inheritDoc} */ public function getInheritedMethods() { return new Collection(); } /** * @return Collection */ public function getMagicMethods() { /** @var Collection $methodTags */ $methodTags = clone $this->getTags()->get('method', new Collection()); $methods = new Collection(); /** @var Tag\MethodDescriptor $methodTag */ foreach ($methodTags as $methodTag) { $method = new MethodDescriptor(); $method->setName($methodTag->getMethodName()); $method->setDescription($methodTag->getDescription()); $method->setParent($this); $methods->add($method); } return $methods; } /** * {@inheritDoc} */ public function setProperties(Collection $properties) { $this->properties = $properties; } /** * {@inheritDoc} */ public function getProperties() { return $this->properties; } /** * {@inheritDoc} */ public function getInheritedProperties() { return new Collection(); } /** * @return Collection */ public function getMagicProperties() { /** @var Collection $propertyTags */ $propertyTags = clone $this->getTags()->get('property', new Collection()); $propertyTags->merge($this->getTags()->get('property-read', new Collection())); $propertyTags->merge($this->getTags()->get('property-write', new Collection())); $properties = new Collection(); /** @var Tag\PropertyDescriptor $propertyTag */ foreach ($propertyTags as $propertyTag) { $property = new PropertyDescriptor(); $property->setName($propertyTag->getVariableName()); $property->setDescription($propertyTag->getDescription()); $property->setTypes($propertyTag->getTypes()); $property->setParent($this); $properties->add($property); } return $properties; } /** * @param string $package */ public function setPackage($package) { parent::setPackage($package); foreach ($this->getProperties() as $property) { $property->setPackage($package); } foreach ($this->getMethods() as $method) { $method->setPackage($package); } } /** * Sets a collection of all traits used by this class. * * @param Collection $usedTraits * * @return void */ public function setUsedTraits($usedTraits) { $this->usedTraits = $usedTraits; } /** * Returns the traits used by this class. * * Returned values may either be a string (when the Trait is not in this project) or a TraitDescriptor. * * @return Collection */ public function getUsedTraits() { return $this->usedTraits; } } method = $method; } /** * {@inheritDoc} */ public function setTypes($types) { $this->types = $types; } /** * {@inheritDoc} */ public function getTypes() { if (count($this->types)==0 && $this->getInheritedElement() !== null ) { $this->setTypes($this->getInheritedElement()->getTypes()); } return $this->types; } /** * @return null|ArgumentDescriptor */ public function getInheritedElement() { if ($this->method instanceof MethodDescriptor && $this->method->getInheritedElement() instanceof MethodDescriptor) { $parents = $this->method->getInheritedElement()->getArguments(); foreach($parents as $parentArgument) { if ($parentArgument->getName() === $this->getName()) { return $parentArgument; } } } return null; } /** * {@inheritDoc} */ public function setDefault($value) { $this->default = $value; } /** * {@inheritDoc} */ public function getDefault() { return $this->default; } /** * {@inheritDoc} */ public function setByReference($byReference) { $this->byReference = $byReference; } /** * {@inheritDoc} */ public function isByReference() { return $this->byReference; } /** * Sets whether this argument represents a variadic argument. * * @param boolean $isVariadic * * @return false */ public function setVariadic($isVariadic) { $this->isVariadic = $isVariadic; } /** * Returns whether this argument represents a variadic argument. * * @return boolean */ public function isVariadic() { return $this->isVariadic; } } setChildren(new Collection()); $this->setFunctions(new Collection()); $this->setConstants(new Collection()); $this->setClasses(new Collection()); $this->setInterfaces(new Collection()); $this->setTraits(new Collection()); $this->setTags(new Collection()); } /** * Sets the parent namespace for this namespace. * * @param NamespaceDescriptor $parent * * @return void */ public function setParent($parent) { $this->parent = $parent; } /** * Returns the parent namespace for this namespace. * * @return NamespaceDescriptor|null */ public function getParent() { return $this->parent; } /** * Sets a list of all classes in this project. * * @param Collection $classes * * @return void */ public function setClasses(Collection $classes) { $this->classes = $classes; } /** * Returns a list of all classes in this namespace. * * @return Collection */ public function getClasses() { return $this->classes; } /** * Sets a list of all constants in this namespace. * * @param Collection $constants * * @return void */ public function setConstants(Collection $constants) { $this->constants = $constants; } /** * Returns a list of all constants in this namespace. * * @return Collection */ public function getConstants() { return $this->constants; } /** * Sets a list of all functions in this namespace. * * @param Collection $functions * * @return void */ public function setFunctions(Collection $functions) { $this->functions = $functions; } /** * Returns a list of all functions in this namespace. * * @return Collection */ public function getFunctions() { return $this->functions; } /** * Sets a list of all interfaces in this namespace. * * @param Collection $interfaces * * @return void */ public function setInterfaces(Collection $interfaces) { $this->interfaces = $interfaces; } /** * Returns a list of all interfaces in this namespace. * * @return Collection */ public function getInterfaces() { return $this->interfaces; } /** * Sets a list of all child namespaces in this namespace. * * @param Collection $children * * @return void */ public function setChildren(Collection $children) { $this->children = $children; } /** * Returns a list of all namespaces contained in this namespace and its children. * * @return Collection */ public function getChildren() { return $this->children; } /** * Sets a list of all traits contained in this namespace. * * @param Collection $traits * * @return void */ public function setTraits($traits) { $this->traits = $traits; } /** * Returns a list of all traits in this namespace. * * @return Collection */ public function getTraits() { return $this->traits; } } setHash($hash); $this->setNamespaceAliases(new Collection()); $this->setIncludes(new Collection()); $this->setConstants(new Collection()); $this->setFunctions(new Collection()); $this->setClasses(new Collection()); $this->setInterfaces(new Collection()); $this->setTraits(new Collection()); $this->setMarkers(new Collection()); } /** * Returns the hash of the contents for this file. * * @return string */ public function getHash() { return $this->hash; } /** * Sets the hash of the contents for this file. * * @param string $hash * * @return void */ protected function setHash($hash) { $this->hash = $hash; } /** * Retrieves the contents of this file. * * @return string|null */ public function getSource() { return $this->source; } /** * Sets the source contents for this file. * * @param string|null $source * * @return void */ public function setSource($source) { $this->source = $source; } /** * Returns the namespace aliases that have been defined in this file. * * @return Collection */ public function getNamespaceAliases() { return $this->namespaceAliases; } /** * Sets the collection of namespace aliases for this file. * * @param Collection $namespaceAliases * * @return void */ public function setNamespaceAliases(Collection $namespaceAliases) { $this->namespaceAliases = $namespaceAliases; } /** * Returns a list of all includes that have been declared in this file. * * @return Collection */ public function getIncludes() { return $this->includes; } /** * Sets a list of all includes that have been declared in this file. * * @param Collection $includes * * @return void */ public function setIncludes(Collection $includes) { $this->includes = $includes; } /** * Returns a list of constant descriptors contained in this file. * * @return Collection */ public function getConstants() { return $this->constants; } /** * Sets a list of constant descriptors contained in this file. * * @param Collection $constants * * @return void */ public function setConstants(Collection $constants) { $this->constants = $constants; } /** * Returns a list of function descriptors contained in this file. * * @return Collection|FunctionInterface[] */ public function getFunctions() { return $this->functions; } /** * Sets a list of function descriptors contained in this file. * * @param Collection $functions * * @return void */ public function setFunctions(Collection $functions) { $this->functions = $functions; } /** * Returns a list of class descriptors contained in this file. * * @return Collection|ClassInterface[] */ public function getClasses() { return $this->classes; } /** * Sets a list of class descriptors contained in this file. * * @param Collection $classes * * @return void */ public function setClasses(Collection $classes) { $this->classes = $classes; } /** * Returns a list of interface descriptors contained in this file. * * @return Collection|InterfaceInterface[] */ public function getInterfaces() { return $this->interfaces; } /** * Sets a list of interface descriptors contained in this file. * * @param Collection $interfaces * * @return void */ public function setInterfaces(Collection $interfaces) { $this->interfaces = $interfaces; } /** * Returns a list of trait descriptors contained in this file. * * @return Collection|TraitInterface[] */ public function getTraits() { return $this->traits; } /** * Sets a list of trait descriptors contained in this file. * * @param Collection $traits * * @return void */ public function setTraits(Collection $traits) { $this->traits = $traits; } /** * Returns a series of markers contained in this file. * * A marker is a special inline comment that starts with a keyword and is followed by a single line description. * * Example: * ``` * // TODO: This is an item that needs to be done. * ``` * * @return Collection */ public function getMarkers() { return $this->markers; } /** * Sets a series of markers contained in this file. * * @param Collection $markers * * @see getMarkers() for more information on markers. * * @return void */ public function setMarkers(Collection $markers) { $this->markers = $markers; } /** * Returns a list of all errors in this file and all its child elements. * * @return Collection */ public function getAllErrors() { $errors = $this->getErrors(); $types = $this->getClasses()->merge($this->getInterfaces())->merge($this->getTraits()); $elements = $this->getFunctions()->merge($this->getConstants())->merge($types); foreach ($elements as $element) { if (!$element) { continue; } $errors = $errors->merge($element->getErrors()); } foreach ($types as $element) { if (!$element) { continue; } foreach ($element->getMethods() as $item) { if (!$item) { continue; } $errors = $errors->merge($item->getErrors()); } if (method_exists($element, 'getConstants')) { foreach ($element->getConstants() as $item) { if (!$item) { continue; } $errors = $errors->merge($item->getErrors()); } } if (method_exists($element, 'getProperties')) { foreach ($element->getProperties() as $item) { if (!$item) { continue; } $errors = $errors->merge($item->getErrors()); } } } return $errors; } /** * Sets the file path for this file relative to the project's root. * * @param string $path * * @return void */ public function setPath($path) { $this->path = $path; } /** * Returns the file path relative to the project's root. * * @return string */ public function getPath() { return $this->path; } } builder = $builder; } /** * Filter Descriptor with based on visibility. * * @param DescriptorAbstract $value * * @return DescriptorAbstract|null */ public function filter($value) { if ($value instanceof VisibilityInterface && !$this->builder->isVisibilityAllowed($value->getVisibility()) ) { return null; } return $value; } } builder = $builder; } /** * If the ProjectDescriptor's settings allow internal tags then return the Descriptor, otherwise null to filter it. * * @param DescriptorAbstract $value * * @return DescriptorAbstract|null */ public function filter($value) { $isInternalAllowed = $this->builder->isVisibilityAllowed(Settings::VISIBILITY_INTERNAL); if ($isInternalAllowed) { $value->setDescription(preg_replace('/\{@internal\s(.+?)\}\}/', '$1', $value->getDescription())); return $value; } // remove inline @internal tags $value->setDescription(preg_replace('/\{@internal\s(.+?)\}\}/', '', $value->getDescription())); // if internal elements are not allowed; filter this element if ($value->getTags()->get('internal')) { return null; } return $value; } } factory = $factory; } /** * Attaches a filter to a specific FQCN. * * @param string $fqcn * @param FilterInterface $filter * @param int $priority [1000] * * @return void */ public function attach($fqcn, $filter, $priority = self::DEFAULT_PRIORITY) { $chain = $this->factory->getChainFor($fqcn); $chain->attach($filter, $priority); } /** * Filters the given Descriptor and returns the altered object. * * @param Filterable $descriptor * * @return Filterable|null */ public function filter(Filterable $descriptor) { $chain = $this->factory->getChainFor(get_class($descriptor)); return $chain->filter($descriptor); } } builder = $builder; } /** * Filter Descriptor with ignore tags. * * @param DescriptorAbstract $value * * @return DescriptorAbstract|null */ public function filter($value) { if (!is_null($value) && $value->getTags()->get('ignore')) { return null; } return $value; } } chains[$fqcn])) { $this->chains[$fqcn] = new FilterChain(); } return $this->chains[$fqcn]; } } arguments = new Collection(); } /** * @param string $methodName */ public function setMethodName($methodName) { $this->methodName = $methodName; } /** * @return string */ public function getMethodName() { return $this->methodName; } /** * @param mixed $arguments */ public function setArguments($arguments) { $this->arguments = $arguments; } /** * @return mixed */ public function getArguments() { return $this->arguments; } /** * @param mixed $response */ public function setResponse($response) { $this->response = $response; } /** * @return ReturnDescriptor */ public function getResponse() { return $this->response; } } link = $link; } /** * Returns the URL where this link points to. * * @return string */ public function getLink() { return $this->link; } } version; } /** * Sets the version since when the associated element was introduced. * * @param string $version * * @return void */ public function setVersion($version) { $this->version = $version; } } filePath = $filePath; } /** * Returns the location where this example points to. * * @return string */ public function getFilePath() { return $this->filePath; } /** * Returns the location where this example points to. * * @return void */ public function setStartingLine($startingLine) { $this->startingLine = $startingLine; } /** * Returns the location where this example points to. * * @return int */ public function getStartingLine() { return $this->startingLine; } /** * Returns the location where this example points to. * * @return void */ public function setLineCount($lineCount) { $this->lineCount = $lineCount; } /** * Returns the location where this example points to. * * @return int */ public function getLineCount() { return $this->lineCount; } /** * Returns the content of the example. * * @return void */ public function setExample($example) { $this->example = $example; } /** * Returns the content of the example. * * @return string */ public function getExample() { return $this->example; } } version; } /** * Sets the version since when the associated element was deprecated. * * @param string $version * * @return void */ public function setVersion($version) { $this->version = $version; } } reference; } /** * Sets the FQSEN to which this tag points. * * @param string $reference * * @return void */ public function setReference($reference) { $this->reference = $reference; } } variableName; } /** * Sets the variable name on this descriptor. * * @param string $variableName * * @return void */ public function setVariableName($variableName) { $this->variableName = $variableName; } } types = $types; } /** * Returns the list of types associated with this tag. * * @return Collection */ public function getTypes() { return $this->types; } } version; } /** * Sets the version for the associated element. * * @param string $version * * @return void */ public function setVersion($version) { $this->version = $version; } } reference = $reference; } /** * @return DescriptorAbstract|string */ public function getReference() { return $this->reference; } } builder; } /** * Registers the Builder with this Assembler. * * The Builder may be used to recursively assemble Descriptors using * the {@link ProjectDescriptorBuilder::buildDescriptor()} method. * * @param ProjectDescriptorBuilder $builder * * @return void */ public function setBuilder(ProjectDescriptorBuilder $builder) { $this->builder = $builder; } } setSummary($docBlock->getShortDescription()); $target->setDescription($docBlock->getLongDescription()->getContents()); /** @var DocBlock\Tag $tag */ foreach ($docBlock->getTags() as $tag) { $tagDescriptor = $this->builder->buildDescriptor($tag); // allow filtering of tags if (!$tagDescriptor) { continue; } $target->getTags() ->get($tag->getName(), new Collection()) ->add($tagDescriptor); } } /** * Extracts the package from the DocBlock. * * @param DocBlock $docBlock * * @return string|null */ protected function extractPackageFromDocBlock($docBlock) { $packageTags = $docBlock ? $docBlock->getTagsByName('package') : null; if (! $packageTags) { return null; } /** @var DocBlock\Tag $tag */ $tag = reset($packageTags); return trim($tag->getContent()); } } setFullyQualifiedStructuralElementName($data->getName()); $traitDescriptor->setName($data->getShortName()); $traitDescriptor->setLine($data->getLinenumber()); $traitDescriptor->setPackage($this->extractPackageFromDocBlock($data->getDocBlock()) ?: ''); // Reflection library formulates namespace as global but this is not wanted for phpDocumentor itself $traitDescriptor->setNamespace( '\\' . (strtolower($data->getNamespace()) == 'global' ? '' :$data->getNamespace()) ); $this->assembleDocBlock($data->getDocBlock(), $traitDescriptor); $this->addProperties($data->getProperties(), $traitDescriptor); $this->addMethods($data->getMethods(), $traitDescriptor); return $traitDescriptor; } /** * Registers the child properties with the generated Trait Descriptor. * * @param PropertyReflector[] $properties * @param TraitDescriptor $traitDescriptor * * @return void */ protected function addProperties($properties, $traitDescriptor) { foreach ($properties as $property) { $propertyDescriptor = $this->getBuilder()->buildDescriptor($property); if ($propertyDescriptor) { $propertyDescriptor->setParent($traitDescriptor); $traitDescriptor->getProperties()->set($propertyDescriptor->getName(), $propertyDescriptor); } } } /** * Registers the child methods with the generated Trait Descriptor. * * @param MethodReflector[] $methods * @param TraitDescriptor $traitDescriptor * * @return void */ protected function addMethods($methods, $traitDescriptor) { foreach ($methods as $method) { $methodDescriptor = $this->getBuilder()->buildDescriptor($method); if ($methodDescriptor) { $methodDescriptor->setParent($traitDescriptor); $traitDescriptor->getMethods()->set($methodDescriptor->getName(), $methodDescriptor); } } } } getHash()); $fileDescriptor->setPackage( $this->extractPackageFromDocBlock($data->getDocBlock()) ?: $data->getDefaultPackageName() ); $fileDescriptor->setName(basename($data->getFilename())); $fileDescriptor->setPath($data->getFilename()); $fileDescriptor->setSource($data->getContents()); $fileDescriptor->setIncludes(new Collection($data->getIncludes())); $fileDescriptor->setNamespaceAliases(new Collection($data->getNamespaceAliases())); $this->assembleDocBlock($data->getDocBlock(), $fileDescriptor); $this->overridePackageTag($data, $fileDescriptor); $this->addMarkers($data->getMarkers(), $fileDescriptor); $this->addConstants($data->getConstants(), $fileDescriptor); $this->addFunctions($data->getFunctions(), $fileDescriptor); $this->addClasses($data->getClasses(), $fileDescriptor); $this->addInterfaces($data->getInterfaces(), $fileDescriptor); $this->addTraits($data->getTraits(), $fileDescriptor); return $fileDescriptor; } /** * Registers the child constants with the generated File Descriptor. * * @param ConstantReflector[] $constants * @param FileDescriptor $fileDescriptor * * @return void */ protected function addConstants($constants, $fileDescriptor) { foreach ($constants as $constant) { $constantDescriptor = $this->getBuilder()->buildDescriptor($constant); if ($constantDescriptor) { $constantDescriptor->setLocation($fileDescriptor, $constant->getLineNumber()); if (count($constantDescriptor->getTags()->get('package', new Collection())) == 0) { $constantDescriptor->getTags() ->set('package', $fileDescriptor->getTags()->get('package', new Collection())); } $fileDescriptor->getConstants()->set( $constantDescriptor->getFullyQualifiedStructuralElementName(), $constantDescriptor ); } } } /** * Registers the child functions with the generated File Descriptor. * * @param FunctionReflector[] $functions * @param FileDescriptor $fileDescriptor * * @return void */ protected function addFunctions($functions, $fileDescriptor) { foreach ($functions as $function) { $functionDescriptor = $this->getBuilder()->buildDescriptor($function); if ($functionDescriptor) { $functionDescriptor->setLocation($fileDescriptor, $function->getLineNumber()); if (count($functionDescriptor->getTags()->get('package', new Collection())) == 0) { $functionDescriptor->getTags() ->set('package', $fileDescriptor->getTags()->get('package', new Collection())); } $fileDescriptor->getFunctions()->set( $functionDescriptor->getFullyQualifiedStructuralElementName(), $functionDescriptor ); } } } /** * Registers the child classes with the generated File Descriptor. * * @param ClassReflector[] $classes * @param FileDescriptor $fileDescriptor * * @return void */ protected function addClasses($classes, $fileDescriptor) { foreach ($classes as $class) { $classDescriptor = $this->getBuilder()->buildDescriptor($class); if ($classDescriptor) { $classDescriptor->setLocation($fileDescriptor, $class->getLineNumber()); if (count($classDescriptor->getTags()->get('package', new Collection())) == 0) { $classDescriptor->getTags()->set( 'package', $fileDescriptor->getTags()->get('package', new Collection()) ); } $fileDescriptor->getClasses()->set( $classDescriptor->getFullyQualifiedStructuralElementName(), $classDescriptor ); } } } /** * Registers the child interfaces with the generated File Descriptor. * * @param InterfaceReflector[] $interfaces * @param FileDescriptor $fileDescriptor * * @return void */ protected function addInterfaces($interfaces, $fileDescriptor) { foreach ($interfaces as $interface) { $interfaceDescriptor = $this->getBuilder()->buildDescriptor($interface); if ($interfaceDescriptor) { $interfaceDescriptor->setLocation($fileDescriptor, $interface->getLineNumber()); if (count($interfaceDescriptor->getTags()->get('package', new Collection())) == 0) { $interfaceDescriptor->getTags() ->set('package', $fileDescriptor->getTags()->get('package', new Collection())); } $fileDescriptor->getInterfaces()->set( $interfaceDescriptor->getFullyQualifiedStructuralElementName(), $interfaceDescriptor ); } } } /** * Registers the child traits with the generated File Descriptor. * * @param TraitReflector[] $traits * @param FileDescriptor $fileDescriptor * * @return void */ protected function addTraits($traits, $fileDescriptor) { foreach ($traits as $trait) { $traitDescriptor = $this->getBuilder()->buildDescriptor($trait); if ($traitDescriptor) { $traitDescriptor->setLocation($fileDescriptor, $trait->getLineNumber()); if (count($traitDescriptor->getTags()->get('package', new Collection())) == 0) { $traitDescriptor->getTags() ->set('package', $fileDescriptor->getTags()->get('package', new Collection())); } $fileDescriptor->getTraits()->set( $traitDescriptor->getFullyQualifiedStructuralElementName(), $traitDescriptor ); } } } /** * Registers the markers that were found in a File with the File Descriptor. * * @param string[] $markers * @param FileDescriptor $fileDescriptor * * @return void */ protected function addMarkers($markers, $fileDescriptor) { foreach ($markers as $marker) { list($type, $message, $line) = $marker; $fileDescriptor->getMarkers()->add( array( 'type' => $type, 'message' => $message, 'line' => $line, ) ); } } /** * @param $data * @param $fileDescriptor */ protected function overridePackageTag($data, $fileDescriptor) { $packages = new Collection(); $package = $this->extractPackageFromDocBlock($data->getDocBlock()); if (! $package) { $package = $data->getDefaultPackageName(); } $tag = new TagDescriptor('package'); $tag->setDescription($package); $packages->add($tag); $fileDescriptor->getTags()->set('package', $packages); } } getName()); $descriptor->setDescription($data->getDescription()); $descriptor->setTypes( $this->builder->buildDescriptor(new Collection($data->getTypes())) ); return $descriptor; } } getName()); $descriptor->setDescription($data->getDescription()); return $descriptor; } } getName()); $descriptor->setDescription($data->getDescription()); $descriptor->setReference($data->getReference()); return $descriptor; } } getName()); $descriptor->setDescription($data->getDescription()); $descriptor->setVariableName($data->getVariableName()); /** @var Collection $types */ $types = $this->builder->buildDescriptor(new Collection($data->getTypes())); $descriptor->setTypes($types); return $descriptor; } } 'phpDocumentor\Descriptor\Type\StringDescriptor', 'int' => 'phpDocumentor\Descriptor\Type\IntegerDescriptor', 'integer' => 'phpDocumentor\Descriptor\Type\IntegerDescriptor', 'float' => 'phpDocumentor\Descriptor\Type\FloatDescriptor', 'boolean' => 'phpDocumentor\Descriptor\Type\BooleanDescriptor', 'bool' => 'phpDocumentor\Descriptor\Type\BooleanDescriptor', ); /** * Creates a Descriptor from the provided data. * * @param Collection $data * * @return DescriptorCollection */ public function create($data) { $collection = new DescriptorCollection(); foreach ($data as $type) { $collection->add($this->createDescriptorForType($type)); } return $collection; } /** * Creates a Type ValueObject (Descriptor) for the provided type string. * * @param string $type * * @return DescriptorAbstract */ protected function createDescriptorForType($type) { if (!$this->isArrayNotation($type)) { $className = $this->findClassNameForType($type); return $className ? new $className() : new UnknownTypeDescriptor($type); } $type = $this->extractTypeFromArrayNotation($type); $className = $this->findClassNameForType($type); $descriptor = $className ? new $className() : new UnknownTypeDescriptor($type); $descriptor = $this->convertToArrayDescriptor($descriptor); return $descriptor; } /** * Detects if the given string representing a type equals an array. * * @param string $type * * @return boolean */ protected function isArrayNotation($type) { return (substr($type, -2) == '[]'); } /** * Returns the value-type from an array notation. * * @param string $type * * @return string */ protected function extractTypeFromArrayNotation($type) { return substr($type, 0, -2); } /** * Wraps the given Descriptor inside a Collection Descriptor of type array and returns that. * * @param DescriptorAbstract $descriptor * * @return CollectionDescriptor */ protected function convertToArrayDescriptor($descriptor) { $arrayDescriptor = new CollectionDescriptor('array'); $arrayDescriptor->setTypes(array($descriptor)); $arrayDescriptor->setKeyTypes(array('mixed')); return $arrayDescriptor; } /** * Returns the class name of the Value Object class associated with a given type or false if the type is unknown. * * @param string $type * * @return string|boolean */ protected function findClassNameForType($type) { $className = (isset($this->typeToValueObjectClassName[$type])) ? $this->typeToValueObjectClassName[$type] : false; return $className; } } getName()); $descriptor->setDescription($data->getDescription()); return $descriptor; } } getName()); $descriptor->setLink($data->getLink()); $descriptor->setDescription($data->getDescription()); return $descriptor; } } getName()); $descriptor->setVariableName($data->getVariableName()); $descriptor->setDescription($data->getDescription()); $descriptor->setTypes( $this->builder->buildDescriptor(new Collection($data->getTypes())) ); return $descriptor; } } getName()); $descriptor->setDescription($data->getDescription()); $descriptor->setMethodName($data->getMethodName()); $response = new ReturnDescriptor('return'); $response->setTypes($this->builder->buildDescriptor(new Collection($data->getTypes()))); $descriptor->setResponse($response); foreach ($data->getArguments() as $argument) { $argumentDescriptor = $this->createArgumentDescriptorForMagicMethod($argument); $descriptor->getArguments()->set($argumentDescriptor->getName(), $argumentDescriptor); } return $descriptor; } /** * Construct an argument descriptor given the array representing an argument with a Method Tag in the Reflection * component. * * @param string[] $argument * * @return ArgumentDescriptor */ private function createArgumentDescriptorForMagicMethod($argument) { $argumentType = null; $argumentName = null; $argumentDefault = false; // false means we have not encountered the '=' yet. foreach ($argument as $part) { $part = trim($part); if (!$part) { continue; } if (!$argumentType && $part[0] != '$') { $argumentType = $part; } elseif (!$argumentName) { $argumentName = $part; } elseif ($argumentName && !$argumentType) { $argumentType = $part; } elseif ($part == '=') { $argumentDefault = null; } elseif ($argumentDefault === null) { $argumentDefault = $part; } } if ($argumentDefault === false) { $argumentDefault = null; } // if no name is set but a type is then the input is malformed and we correct for it if ($argumentType && !$argumentName) { $argumentName = $argumentType; $argumentType = null; } // if there is no type then we assume it is 'mixed' if (!$argumentType) { $argumentType = 'mixed'; } $argumentDescriptor = new ArgumentDescriptor(); $argumentDescriptor->setTypes($this->builder->buildDescriptor(new Collection(array($argumentType)))); $argumentDescriptor->setName($argumentName[0] == '$' ? $argumentName : '$' . $argumentName); $argumentDescriptor->setDefault($argumentDefault); return $argumentDescriptor; } } getName()); $descriptor->setDescription($data->getDescription()); $descriptor->setVersion($data->getVersion()); return $descriptor; } } getName()); $descriptor->setDescription($data->getDescription()); $descriptor->setVersion($data->getVersion()); return $descriptor; } } getName()); $descriptor->setDescription($data->getDescription()); $reference = $data->getReference(); if (substr($reference, 0, 7) !== 'http://' && substr($reference, 0, 8) !== 'https://' && $reference !== 'self' && $reference !== '$this' ) { // TODO: move this to the ReflectionDocBlock component // Expand FQCN part of the FQSEN $referenceParts = explode('::', $reference); if (count($referenceParts) > 1 && $reference[0] != '\\') { $type = current($referenceParts); $type = new Collection( array($type), $data->getDocBlock() ? $data->getDocBlock()->getContext() : null ); $referenceParts[0] = $type; } elseif (isset($reference[0]) && $reference[0] != '\\') { array_unshift($referenceParts, Linker::CONTEXT_MARKER); } $reference = implode('::', $referenceParts); } $descriptor->setReference($reference); return $descriptor; } } finder = $finder; } /** * Creates a new Descriptor from the given Reflector. * * @param ExampleTag $data * * @throws \InvalidArgumentException if the provided parameter is not of type ExampleTag; the interface won't let * up typehint the signature. * * @return ExampleDescriptor */ public function create($data) { if (! $data instanceof ExampleTag) { throw new \InvalidArgumentException( 'The ExampleAssembler expected an ExampleTag object to base the descriptor on' ); } $descriptor = new ExampleDescriptor($data->getName()); $descriptor->setFilePath((string) $data->getFilePath()); $descriptor->setStartingLine($data->getStartingLine()); $descriptor->setLineCount($data->getLineCount()); $descriptor->setDescription($data->getDescription()); $descriptor->setExample($this->finder->find($descriptor)); return $descriptor; } } getName()); $descriptor->setDescription($data->getDescription()); $descriptor->setVersion($data->getVersion()); return $descriptor; } } getName()); $descriptor->setDescription($data->getDescription()); $descriptor->setTypes( $this->builder->buildDescriptor(new Collection($data->getTypes())) ); return $descriptor; } } getName()); $descriptor->setDescription($data->getDescription()); $descriptor->setVariableName($data->getVariableName()); $types = $this->builder->buildDescriptor( new Collection($data->getVariableName() == '$this' ? array('$this') : $data->getTypes()) ); $descriptor->setTypes($types); return $descriptor; } } setFullyQualifiedStructuralElementName($data->getName()); $classDescriptor->setName($data->getShortName()); $classDescriptor->setPackage($this->extractPackageFromDocBlock($data->getDocBlock()) ?: ''); $classDescriptor->setLine($data->getLinenumber()); $classDescriptor->setParent($data->getParentClass()); $classDescriptor->setAbstract($data->isAbstract()); $classDescriptor->setFinal($data->isFinal()); // Reflection library formulates namespace as global but this is not wanted for phpDocumentor itself $classDescriptor->setNamespace( '\\' . (strtolower($data->getNamespace()) == 'global' ? '' :$data->getNamespace()) ); foreach ($data->getInterfaces() as $interfaceClassName) { $classDescriptor->getInterfaces()->set($interfaceClassName, $interfaceClassName); } $fqcn = $classDescriptor->getFullyQualifiedStructuralElementName(); $namespace = substr($fqcn, 0, strrpos($fqcn, '\\')); $classDescriptor->setNamespace($namespace); $this->assembleDocBlock($data->getDocBlock(), $classDescriptor); $this->addConstants($data->getConstants(), $classDescriptor); $this->addProperties($data->getProperties(), $classDescriptor); $this->addMethods($data->getMethods(), $classDescriptor); $this->addUses($data->getTraits(), $classDescriptor); return $classDescriptor; } /** * Registers the child constants with the generated Class Descriptor. * * @param ConstantReflector[] $constants * @param ClassDescriptor $classDescriptor * * @return void */ protected function addConstants($constants, $classDescriptor) { foreach ($constants as $constant) { $constantDescriptor = $this->getBuilder()->buildDescriptor($constant); if ($constantDescriptor) { $constantDescriptor->setParent($classDescriptor); $classDescriptor->getConstants()->set($constantDescriptor->getName(), $constantDescriptor); } } } /** * Registers the child properties with the generated Class Descriptor. * * @param ClassReflector\PropertyReflector[] $properties * @param ClassDescriptor $classDescriptor * * @return void */ protected function addProperties($properties, $classDescriptor) { foreach ($properties as $property) { $propertyDescriptor = $this->getBuilder()->buildDescriptor($property); if ($propertyDescriptor) { $propertyDescriptor->setParent($classDescriptor); $classDescriptor->getProperties()->set($propertyDescriptor->getName(), $propertyDescriptor); } } } /** * Registers the child methods with the generated Class Descriptor. * * @param ClassReflector\MethodReflector[] $methods * @param ClassDescriptor $classDescriptor * * @return void */ protected function addMethods($methods, $classDescriptor) { foreach ($methods as $method) { $methodDescriptor = $this->getBuilder()->buildDescriptor($method); if ($methodDescriptor) { $methodDescriptor->setParent($classDescriptor); $classDescriptor->getMethods()->set($methodDescriptor->getName(), $methodDescriptor); } } } /** * Registers the used traits with the generated Class Descriptor. * * @param string[] $traits * @param ClassDescriptor $classDescriptor * * @return void */ protected function addUses(array $traits, ClassDescriptor $classDescriptor) { $classDescriptor->setUsedTraits(new Collection($traits)); } } setName($data->getName()); $argumentDescriptor->setTypes( $this->builder->buildDescriptor( $data->getType() ? new Collection(array($data->getType())) : new Collection() ) ); foreach ($params as $paramDescriptor) { $this->overwriteTypeAndDescriptionFromParamTag($data, $paramDescriptor, $argumentDescriptor); } $argumentDescriptor->setDefault($data->getDefault()); $argumentDescriptor->setByReference($data->isByRef()); return $argumentDescriptor; } /** * Overwrites the type and description in the Argument Descriptor with that from the tag if the names match. * * @param ArgumentReflector $argument * @param ParamDescriptor $paramDescriptor * @param ArgumentDescriptor $argumentDescriptor * * @return void */ protected function overwriteTypeAndDescriptionFromParamTag( ArgumentReflector $argument, ParamDescriptor $paramDescriptor, ArgumentDescriptor $argumentDescriptor ) { if ($paramDescriptor->getVariableName() != $argument->getName()) { return; } $argumentDescriptor->setDescription($paramDescriptor->getDescription()); $argumentDescriptor->setTypes( $paramDescriptor->getTypes() ?: $this->builder->buildDescriptor( new Collection(array($argument->getType() ?: 'mixed')) ) ); } } setName($data->getShortName()); $constantDescriptor->setValue($data->getValue()); // Reflection library formulates namespace as global but this is not wanted for phpDocumentor itself $constantDescriptor->setNamespace( '\\' . (strtolower($data->getNamespace()) == 'global' ? '' :$data->getNamespace()) ); $constantDescriptor->setFullyQualifiedStructuralElementName( (trim($constantDescriptor->getNamespace(), '\\') ? $constantDescriptor->getNamespace() : '') . '\\' . $data->getShortName() ); $this->assembleDocBlock($data->getDocBlock(), $constantDescriptor); $constantDescriptor->setLine($data->getLinenumber()); return $constantDescriptor; } } setFullyQualifiedStructuralElementName($data->getName()); $propertyDescriptor->setName($data->getShortName()); $propertyDescriptor->setVisibility($data->getVisibility() ?: 'public'); $propertyDescriptor->setStatic($data->isStatic()); $propertyDescriptor->setDefault($data->getDefault()); $this->assembleDocBlock($data->getDocBlock(), $propertyDescriptor); $propertyDescriptor->setLine($data->getLinenumber()); return $propertyDescriptor; } } argumentAssembler = $argumentAssembler; } /** * Creates a Descriptor from the provided data. * * @param MethodReflector $data * * @return MethodDescriptor */ public function create($data) { $methodDescriptor = new MethodDescriptor(); $this->mapReflectorToDescriptor($data, $methodDescriptor); $this->assembleDocBlock($data->getDocBlock(), $methodDescriptor); $this->addArguments($data, $methodDescriptor); $this->addVariadicArgument($data, $methodDescriptor); return $methodDescriptor; } /** * Maps the fields to the reflector to the descriptor. * * @param MethodReflector $reflector * @param MethodDescriptor $descriptor * * @return void */ protected function mapReflectorToDescriptor($reflector, $descriptor) { $descriptor->setFullyQualifiedStructuralElementName($reflector->getName() . '()'); $descriptor->setName($reflector->getShortName()); $descriptor->setVisibility($reflector->getVisibility() ? : 'public'); $descriptor->setFinal($reflector->isFinal()); $descriptor->setAbstract($reflector->isAbstract()); $descriptor->setStatic($reflector->isStatic()); $descriptor->setLine($reflector->getLinenumber()); } /** * Adds the reflected Arguments to the Descriptor. * * @param MethodReflector $reflector * @param MethodDescriptor $descriptor * * @return void */ protected function addArguments($reflector, $descriptor) { foreach ($reflector->getArguments() as $argument) { $this->addArgument($argument, $descriptor); } } /** * Adds a single reflected Argument to the Method Descriptor. * * @param ArgumentReflector $argument * @param MethodDescriptor $descriptor * * @return void */ protected function addArgument($argument, $descriptor) { $params = $descriptor->getTags()->get('param', array()); if (!$this->argumentAssembler->getBuilder()) { $this->argumentAssembler->setBuilder($this->builder); } $argumentDescriptor = $this->argumentAssembler->create($argument, $params); $descriptor->addArgument($argumentDescriptor->getName(), $argumentDescriptor); } /** * Checks if there is a variadic argument in the `@param` tags and adds it to the list of Arguments in * the Descriptor unless there is already one present. * * @param MethodReflector $data * @param MethodDescriptor $methodDescriptor * * @return void */ protected function addVariadicArgument($data, $methodDescriptor) { if (!$data->getDocBlock()) { return; } $paramTags = $data->getDocBlock()->getTagsByName('param'); /** @var ParamTag $lastParamTag */ $lastParamTag = end($paramTags); if (!$lastParamTag) { return; } if ($lastParamTag->isVariadic() && !in_array($lastParamTag->getVariableName(), array_keys($methodDescriptor->getArguments()->getAll())) ) { $types = $this->builder->buildDescriptor(new Collection($lastParamTag->getTypes())); $argument = new ArgumentDescriptor(); $argument->setName($lastParamTag->getVariableName()); $argument->setTypes($types); $argument->setDescription($lastParamTag->getDescription()); $argument->setLine($methodDescriptor->getLine()); $argument->setVariadic(true); $methodDescriptor->getArguments()->set($argument->getName(), $argument); } } } argumentAssembler = $argumentAssembler; } /** * Creates a Descriptor from the provided data. * * @param FunctionReflector $data * * @return FunctionDescriptor */ public function create($data) { $functionDescriptor = new FunctionDescriptor(); $this->mapReflectorPropertiesOntoDescriptor($data, $functionDescriptor); $this->assembleDocBlock($data->getDocBlock(), $functionDescriptor); $this->addArgumentsToFunctionDescriptor($data->getArguments(), $functionDescriptor); return $functionDescriptor; } /** * Maps the properties of the Function reflector onto the Descriptor. * * @param FunctionReflector $reflector * @param FunctionDescriptor $descriptor * * @return void */ protected function mapReflectorPropertiesOntoDescriptor($reflector, $descriptor) { $packages = new Collection(); $package = $this->extractPackageFromDocBlock($reflector->getDocBlock()); if ($package) { $tag = new TagDescriptor('package'); $tag->setDescription($package); $packages->add($tag); } $descriptor->getTags()->set('package', $packages); $descriptor->setFullyQualifiedStructuralElementName($reflector->getName() . '()'); $descriptor->setName($reflector->getShortName()); $descriptor->setLine($reflector->getLinenumber()); $descriptor->setNamespace($this->getFullyQualifiedNamespaceName($reflector)); } /** * Converts each argument reflector to an argument descriptor and adds it to the function descriptor. * * @param FunctionReflector\ArgumentReflector[] $arguments * @param FunctionDescriptor $functionDescriptor * * @return void */ protected function addArgumentsToFunctionDescriptor(array $arguments, $functionDescriptor) { foreach ($arguments as $argument) { $this->addArgumentDescriptorToFunction( $functionDescriptor, $this->createArgumentDescriptor($functionDescriptor, $argument) ); } } /** * Adds the given argument to the function. * * @param FunctionDescriptor $functionDescriptor * @param ArgumentDescriptor $argumentDescriptor * * @return void */ protected function addArgumentDescriptorToFunction($functionDescriptor, $argumentDescriptor) { $functionDescriptor->getArguments()->set($argumentDescriptor->getName(), $argumentDescriptor); } /** * Creates a new ArgumentDescriptor from the given Reflector and Param. * * @param FunctionDescriptor $functionDescriptor * @param FunctionReflector\ArgumentReflector $argument * * @return ArgumentDescriptor */ protected function createArgumentDescriptor($functionDescriptor, $argument) { $params = $functionDescriptor->getTags()->get('param', array()); if (!$this->argumentAssembler->getBuilder()) { $this->argumentAssembler->setBuilder($this->builder); } return $this->argumentAssembler->create($argument, $params); } /** * Retrieves the Fully Qualified Namespace Name from the FunctionReflector. * * Reflection library formulates namespace as global but this is not wanted for phpDocumentor itself. * * @param FunctionReflector $reflector * * @return string */ protected function getFullyQualifiedNamespaceName($reflector) { return '\\' . (strtolower($reflector->getNamespace()) == 'global' ? '' : $reflector->getNamespace()); } } setFullyQualifiedStructuralElementName($data->getName()); $interfaceDescriptor->setName($data->getShortName()); $interfaceDescriptor->setLine($data->getLinenumber()); $interfaceDescriptor->setPackage($this->extractPackageFromDocBlock($data->getDocBlock()) ?: ''); // Reflection library formulates namespace as global but this is not wanted for phpDocumentor itself $interfaceDescriptor->setNamespace( '\\' . (strtolower($data->getNamespace()) == 'global' ? '' :$data->getNamespace()) ); $this->assembleDocBlock($data->getDocBlock(), $interfaceDescriptor); $this->addConstants($data->getConstants(), $interfaceDescriptor); $this->addMethods($data->getMethods(), $interfaceDescriptor); foreach ($data->getParentInterfaces() as $interfaceClassName) { $interfaceDescriptor->getParent()->set($interfaceClassName, $interfaceClassName); } return $interfaceDescriptor; } /** * Registers the child constants with the generated Interface Descriptor. * * @param ConstantReflector[] $constants * @param InterfaceDescriptor $interfaceDescriptor * * @return void */ protected function addConstants($constants, $interfaceDescriptor) { foreach ($constants as $constant) { $constantDescriptor = $this->getBuilder()->buildDescriptor($constant); if ($constantDescriptor) { $constantDescriptor->setParent($interfaceDescriptor); $interfaceDescriptor->getConstants()->set($constantDescriptor->getName(), $constantDescriptor); } } } /** * Registers the child methods with the generated Interface Descriptor. * * @param MethodReflector[] $methods * @param InterfaceDescriptor $interfaceDescriptor * * @return void */ protected function addMethods($methods, $interfaceDescriptor) { foreach ($methods as $method) { $methodDescriptor = $this->getBuilder()->buildDescriptor($method); if ($methodDescriptor) { $methodDescriptor->setParent($interfaceDescriptor); $interfaceDescriptor->getMethods()->set($methodDescriptor->getName(), $methodDescriptor); } } } } assemblers[] = array( 'matcher' => $matcher, 'assembler' => $assembler ); } /** * Registers an assembler instance to this factory that is to be executed after all other assemblers have been * checked. * * @param callable $matcher A callback function accepting the criteria as only parameter and which must * return a boolean. * @param AssemblerInterface $assembler An instance of the Assembler that will be returned if the callback returns * true with the provided criteria. * * @return void */ public function registerFallback($matcher, AssemblerInterface $assembler) { $this->fallbackAssemblers[] = array( 'matcher' => $matcher, 'assembler' => $assembler ); } /** * Retrieves a matching Assembler based on the provided criteria or null if none was found. * * @param mixed $criteria * * @return AssemblerInterface|null */ public function get($criteria) { foreach (array_merge($this->assemblers, $this->fallbackAssemblers) as $candidate) { $matcher = $candidate['matcher']; if ($matcher($criteria) === true) { return $candidate['assembler']; } } return null; } } assemblerFactory = $assemblerFactory; $this->validator = $validator; $this->filter = $filterManager; } public function createProjectDescriptor() { $this->project = new ProjectDescriptor(self::DEFAULT_PROJECT_NAME); } public function setProjectDescriptor(ProjectDescriptor $projectDescriptor) { $this->project = $projectDescriptor; } /** * Returns the project descriptor that is being built. * * @return ProjectDescriptor */ public function getProjectDescriptor() { return $this->project; } /** * Verifies whether the given visibility is allowed to be included in the Descriptors. * * This method is used anytime a Descriptor is added to a collection (for example, when adding a Method to a Class) * to determine whether the visibility of that element is matches what the user has specified when it ran * phpDocumentor. * * @param string|integer $visibility One of the visibility constants of the ProjectDescriptor class or the words * 'public', 'protected', 'private' or 'internal'. * * @see ProjectDescriptor where the visibility is stored and that declares the constants to use. * * @return boolean */ public function isVisibilityAllowed($visibility) { switch ($visibility) { case 'public': $visibility = Settings::VISIBILITY_PUBLIC; break; case 'protected': $visibility = Settings::VISIBILITY_PROTECTED; break; case 'private': $visibility = Settings::VISIBILITY_PRIVATE; break; case 'internal': $visibility = Settings::VISIBILITY_INTERNAL; break; } return $this->getProjectDescriptor()->isVisibilityAllowed($visibility); } public function buildFileUsingSourceData($data) { $descriptor = $this->buildDescriptor($data); if (!$descriptor) { return; } $this->getProjectDescriptor()->getFiles()->set($descriptor->getPath(), $descriptor); } /** * Takes the given data and attempts to build a Descriptor from it. * * @param mixed $data * * @throws \InvalidArgumentException if no Assembler could be found that matches the given data. * * @return DescriptorAbstract|Collection|null */ public function buildDescriptor($data) { $assembler = $this->getAssembler($data); if (!$assembler) { throw new \InvalidArgumentException( 'Unable to build a Descriptor; the provided data did not match any Assembler '. get_class($data) ); } if ($assembler instanceof Builder\AssemblerAbstract) { $assembler->setBuilder($this); } // create Descriptor and populate with the provided data $descriptor = $assembler->create($data); if (!$descriptor) { return null; } $descriptor = (!is_array($descriptor) && (!$descriptor instanceof Collection)) ? $this->filterAndValidateDescriptor($descriptor) : $this->filterAndValidateEachDescriptor($descriptor); return $descriptor; } /** * Attempts to find an assembler matching the given data. * * @param mixed $data * * @return AssemblerAbstract */ public function getAssembler($data) { return $this->assemblerFactory->get($data); } /** * Analyzes a Descriptor and alters its state based on its state or even removes the descriptor. * * @param Filterable $descriptor * * @return Filterable */ public function filter(Filterable $descriptor) { return $this->filter->filter($descriptor); } /** * Validates the contents of the Descriptor and outputs warnings and error if something is amiss. * * @param DescriptorAbstract $descriptor * * @return Collection */ public function validate($descriptor) { $violations = $this->validator->validate($descriptor); $errors = new Collection(); /** @var ConstraintViolation $violation */ foreach ($violations as $violation) { $errors->add( new Error( $this->mapCodeToSeverity($violation->getCode()), $violation->getMessageTemplate(), $descriptor->getLine(), $violation->getMessageParameters() + array($descriptor->getFullyQualifiedStructuralElementName()) ) ); } return $errors; } /** * Filters each descriptor, validates them, stores the validation results and returns a collection of transmuted * objects. * * @param DescriptorAbstract[] $descriptor * * @return Collection */ private function filterAndValidateEachDescriptor($descriptor) { $descriptors = new Collection(); foreach ($descriptor as $key => $item) { $item = $this->filterAndValidateDescriptor($item); if (!$item) { continue; } $descriptors[$key] = $item; } return $descriptors; } /** * Filters a descriptor, validates it, stores the validation results and returns the transmuted object or null * if it is supposed to be removed. * * @param DescriptorAbstract $descriptor * * @return DescriptorAbstract|null */ protected function filterAndValidateDescriptor($descriptor) { if (!$descriptor instanceof Filterable) { return $descriptor; } // filter the descriptor; this may result in the descriptor being removed! $descriptor = $this->filter($descriptor); if (!$descriptor) { return null; } // Validate the descriptor and store any errors $descriptor->setErrors($this->validate($descriptor)); return $descriptor; } /** * Map error code to severity. * * @param int $code * * @return string */ protected function mapCodeToSeverity($code) { if (is_int($code) && $this->translator->translate('VAL:ERRLVL-'.$code)) { $severity = $this->translator->translate('VAL:ERRLVL-'.$code); } else { $severity = LogLevel::ERROR; } return $severity; } /** * @param Translator $translator * * @return void */ public function setTranslator(Translator $translator) { $this->translator = $translator; } } addCache($app); $this->addAssemblers($app); $this->addFilters($app); $this->addValidators($app); $this->addBuilder($app); // I would prefer to extend it but due to a circular reference will pimple fatal $this->attachFiltersToManager($app['descriptor.filter'], $app); $app['descriptor.analyzer'] = function () { return new ProjectAnalyzer(); }; } /** * Registers the Assemblers used to convert Reflection objects to Descriptors. * * @param AssemblerFactory $factory * @param \Cilex\Application $app * * @return AssemblerFactory */ public function attachAssemblersToFactory(AssemblerFactory $factory, Application $app) { // @codingStandardsIgnoreStart because we limit the verbosity by making all closures single-line $fileMatcher = function ($criteria) { return $criteria instanceof FileReflector; }; $constantMatcher = function ($criteria) { return $criteria instanceof ConstantReflector || $criteria instanceof ClassConstant; }; $traitMatcher = function ($criteria) { return $criteria instanceof TraitReflector; }; $classMatcher = function ($criteria) { return $criteria instanceof ClassReflector; }; $interfaceMatcher = function ($criteria) { return $criteria instanceof InterfaceReflector; }; $propertyMatcher = function ($criteria) { return $criteria instanceof ClassReflector\PropertyReflector; }; $methodMatcher = function ($criteria) { return $criteria instanceof ClassReflector\MethodReflector; }; $argumentMatcher = function ($criteria) { return $criteria instanceof FunctionReflector\ArgumentReflector; }; $functionMatcher = function ($criteria) { return $criteria instanceof FunctionReflector; }; $authorMatcher = function ($criteria) { return $criteria instanceof AuthorTag; }; $deprecatedMatcher = function ($criteria) { return $criteria instanceof DeprecatedTag; }; $exampleMatcher = function ($criteria) { return $criteria instanceof ExampleTag; }; $linkMatcher = function ($criteria) { return $criteria instanceof LinkTag; }; $methodTagMatcher = function ($criteria) { return $criteria instanceof MethodTag; }; $propertyTagMatcher = function ($criteria) { return $criteria instanceof PropertyTag; }; $paramMatcher = function ($criteria) { return $criteria instanceof ParamTag; }; $throwsMatcher = function ($criteria) { return $criteria instanceof ThrowsTag; }; $returnMatcher = function ($criteria) { return $criteria instanceof ReturnTag; }; $usesMatcher = function ($criteria) { return $criteria instanceof UsesTag; }; $seeMatcher = function ($criteria) { return $criteria instanceof SeeTag; }; $sinceMatcher = function ($criteria) { return $criteria instanceof SinceTag; }; $varMatcher = function ($criteria) { return $criteria instanceof VarTag; }; $versionMatcher = function ($criteria) { return $criteria instanceof Tag\VersionTag; }; $typeCollectionMatcher = function ($criteria) { return $criteria instanceof TypeCollection; }; $tagFallbackMatcher = function ($criteria) { return $criteria instanceof Tag; }; // @codingStandardsIgnoreEnd $argumentAssembler = new ArgumentAssembler(); $factory->register($fileMatcher, new FileAssembler()); $factory->register($constantMatcher, new ConstantAssembler()); $factory->register($traitMatcher, new TraitAssembler()); $factory->register($classMatcher, new ClassAssembler()); $factory->register($interfaceMatcher, new InterfaceAssembler()); $factory->register($propertyMatcher, new PropertyAssembler()); $factory->register($argumentMatcher, $argumentAssembler); $factory->register($methodMatcher, new MethodAssembler($argumentAssembler)); $factory->register($functionMatcher, new FunctionAssembler($argumentAssembler)); $factory->register($authorMatcher, new AuthorAssembler()); $factory->register($deprecatedMatcher, new DeprecatedAssembler()); $factory->register($exampleMatcher, new ExampleAssembler($app['parser.example.finder'])); $factory->register($linkMatcher, new LinkAssembler()); $factory->register($methodTagMatcher, new MethodTagAssembler()); $factory->register($propertyTagMatcher, new PropertyTagAssembler()); $factory->register($varMatcher, new VarAssembler()); $factory->register($paramMatcher, new ParamAssembler()); $factory->register($throwsMatcher, new ThrowsAssembler()); $factory->register($returnMatcher, new ReturnAssembler()); $factory->register($usesMatcher, new UsesAssembler()); $factory->register($seeMatcher, new SeeAssembler()); $factory->register($sinceMatcher, new SinceAssembler()); $factory->register($versionMatcher, new VersionAssembler()); $factory->register($typeCollectionMatcher, new TypeCollectionAssembler()); $factory->registerFallback($tagFallbackMatcher, new GenericTagAssembler()); return $factory; } /** * Attaches filters to the manager. * * @param Filter $filterManager * @param Application $app * * @return Filter */ public function attachFiltersToManager(Filter $filterManager, Application $app) { $stripOnVisibility = new StripOnVisibility($app['descriptor.builder']); $filtersOnAllDescriptors = array( new StripInternal($app['descriptor.builder']), new StripIgnore($app['descriptor.builder']) ); foreach ($filtersOnAllDescriptors as $filter) { $filterManager->attach('phpDocumentor\Descriptor\ConstantDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\FunctionDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\InterfaceDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\TraitDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\PropertyDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\MethodDescriptor', $filter); } $filterManager->attach('phpDocumentor\Descriptor\PropertyDescriptor', $stripOnVisibility); $filterManager->attach('phpDocumentor\Descriptor\MethodDescriptor', $stripOnVisibility); return $filterManager; } /** * Adds validators to check the Descriptors. * * @param Validator $validator * * @return Validator */ public function attachValidators(Validator $validator) { /** @var ClassMetadata $fileMetadata */ $fileMetadata = $validator->getMetadataFor('phpDocumentor\Descriptor\FileDescriptor'); /** @var ClassMetadata $constantMetadata */ $constantMetadata = $validator->getMetadataFor('phpDocumentor\Descriptor\ConstantDescriptor'); /** @var ClassMetadata $functionMetadata */ $functionMetadata = $validator->getMetadataFor('phpDocumentor\Descriptor\FunctionDescriptor'); /** @var ClassMetadata $classMetadata */ $classMetadata = $validator->getMetadataFor('phpDocumentor\Descriptor\ClassDescriptor'); /** @var ClassMetadata $interfaceMetadata */ $interfaceMetadata = $validator->getMetadataFor('phpDocumentor\Descriptor\InterfaceDescriptor'); /** @var ClassMetadata $traitMetadata */ $traitMetadata = $validator->getMetadataFor('phpDocumentor\Descriptor\TraitDescriptor'); /** @var ClassMetadata $propertyMetadata */ $propertyMetadata = $validator->getMetadataFor('phpDocumentor\Descriptor\PropertyDescriptor'); /** @var ClassMetadata $methodMetadata */ $methodMetadata = $validator->getMetadataFor('phpDocumentor\Descriptor\MethodDescriptor'); $fileMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50000'))); $classMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50005'))); $propertyMetadata->addConstraint(new phpDocAssert\Property\HasSummary()); $methodMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50008'))); $interfaceMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50009'))); $traitMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50010'))); $functionMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50011'))); $functionMetadata->addConstraint(new phpDocAssert\Functions\IsReturnTypeNotAnIdeDefault()); $methodMetadata->addConstraint(new phpDocAssert\Functions\IsReturnTypeNotAnIdeDefault()); $functionMetadata->addConstraint(new phpDocAssert\Functions\IsParamTypeNotAnIdeDefault()); $methodMetadata->addConstraint(new phpDocAssert\Functions\IsParamTypeNotAnIdeDefault()); $functionMetadata->addConstraint(new phpDocAssert\Functions\AreAllArgumentsValid()); $methodMetadata->addConstraint(new phpDocAssert\Functions\AreAllArgumentsValid()); $classMetadata->addConstraint(new phpDocAssert\Classes\HasSinglePackage()); $interfaceMetadata->addConstraint(new phpDocAssert\Classes\HasSinglePackage()); $traitMetadata->addConstraint(new phpDocAssert\Classes\HasSinglePackage()); $fileMetadata->addConstraint(new phpDocAssert\Classes\HasSinglePackage()); $classMetadata->addConstraint(new phpDocAssert\Classes\HasSingleSubpackage()); $interfaceMetadata->addConstraint(new phpDocAssert\Classes\HasSingleSubpackage()); $traitMetadata->addConstraint(new phpDocAssert\Classes\HasSingleSubpackage()); $fileMetadata->addConstraint(new phpDocAssert\Classes\HasSingleSubpackage()); $classMetadata->addConstraint(new phpDocAssert\Classes\HasPackageWithSubpackage()); $interfaceMetadata->addConstraint(new phpDocAssert\Classes\HasPackageWithSubpackage()); $traitMetadata->addConstraint(new phpDocAssert\Classes\HasPackageWithSubpackage()); $fileMetadata->addConstraint(new phpDocAssert\Classes\HasPackageWithSubpackage()); return $validator; } /** * Adds the caching mechanism to the dependency injection container with key 'descriptor.cache'. * * @param Application $app * * @return void */ protected function addCache(Application $app) { $app['descriptor.cache'] = $app->share( function () { $cache = new Filesystem(); $cache->setOptions( array( 'namespace' => 'phpdoc-cache', 'cache_dir' => sys_get_temp_dir(), ) ); $plugin = new SerializerPlugin(); if (extension_loaded('igbinary')) { $options = new PluginOptions(); $options->setSerializer('igbinary'); $plugin->setOptions($options); } $cache->addPlugin($plugin); return $cache; } ); } /** * Adds the Building mechanism using the key 'descriptor.builder'. * * Please note that the type of serializer can be configured using the parameter 'descriptor.builder.serializer'; it * accepts any parameter that Zend\Serializer supports. * * @param Application $app * * @return void */ protected function addBuilder(Application $app) { if (extension_loaded('igbinary')) { $app['descriptor.builder.serializer'] = 'IgBinary'; } else { $app['descriptor.builder.serializer'] = 'PhpSerialize'; } $app['descriptor.builder'] = $app->share( function ($container) { $builder = new ProjectDescriptorBuilder( $container['descriptor.builder.assembler.factory'], $container['descriptor.filter'], $container['validator'] ); $builder->setTranslator($container['translator']); return $builder; } ); } /** * Adds the assembler factory and attaches the basic assemblers with key 'descriptor.builder.assembler.factory'. * * @param Application $app * * @return void */ protected function addAssemblers(Application $app) { $app['descriptor.builder.assembler.factory'] = $app->share( function () { return new AssemblerFactory(); } ); $provider = $this; $app['descriptor.builder.assembler.factory'] = $app->share( $app->extend( 'descriptor.builder.assembler.factory', function ($factory) use ($provider, $app) { return $provider->attachAssemblersToFactory($factory, $app); } ) ); } /** * Adds the descriptor filtering mechanism and using key 'descriptor.filter'. * * Please note that filters can only be attached after the builder is instantiated because it is needed; so the * filters can be attached by extending 'descriptor.builder'. * * @param Application $app * * @return void */ protected function addFilters(Application $app) { $app['descriptor.filter'] = $app->share( function () { return new Filter(new ClassFactory()); } ); } /** * Adds validators for the descriptors to the validator manager. * * @param Application $app * * @throws Exception\MissingDependencyException if the validator could not be found. * * @return void */ protected function addValidators(Application $app) { if (!isset($app['validator'])) { throw new Exception\MissingDependencyException('The validator manager is missing'); } $provider = $this; $app['validator'] = $app->share( $app->extend( 'validator', function ($validatorManager) use ($provider) { return $provider->attachValidators($validatorManager); } ) ); } } setFullyQualifiedStructuralElementName( $parent->getFullyQualifiedStructuralElementName() . '::' . $this->getName() ); $this->parent = $parent; } /** * @return ClassDescriptor|TraitDescriptor */ public function getParent() { return $this->parent; } /** * {@inheritDoc} */ public function setDefault($default) { $this->default = $default; } /** * {@inheritDoc} */ public function getDefault() { return $this->default; } /** * {@inheritDoc} */ public function setStatic($static) { $this->static = $static; } /** * {@inheritDoc} */ public function isStatic() { return $this->static; } /** * {@inheritDoc} */ public function setTypes(Collection $types) { $this->types = $types; } /** * {@inheritDoc} */ public function getTypes() { if (!$this->types) { $this->types = new Collection(); /** @var VarDescriptor $var */ $var = $this->getVar()->getIterator()->current(); if ($var) { $this->types = $var->getTypes(); } } return $this->types; } /** * {@inheritDoc} */ public function setVisibility($visibility) { $this->visibility = $visibility; } /** * {@inheritDoc} */ public function getVisibility() { return $this->visibility; } /** * @return Collection */ public function getVar() { /** @var Collection $var */ $var = $this->getTags()->get('var', new Collection()); if ($var->count() != 0) { return $var; } $inheritedElement = $this->getInheritedElement(); if ($inheritedElement) { return $inheritedElement->getVar(); } return new Collection(); } /** * Returns the file associated with the parent class or trait. * * @return FileDescriptor */ public function getFile() { return $this->getParent()->getFile(); } /** * Returns the property from which this one should inherit, if any. * * @return PropertyDescriptor|null */ public function getInheritedElement() { /** @var ClassDescriptor|InterfaceDescriptor|null $associatedClass */ $associatedClass = $this->getParent(); if (($associatedClass instanceof ClassDescriptor || $associatedClass instanceof InterfaceDescriptor) && ($associatedClass->getParent() instanceof ClassDescriptor || $associatedClass->getParent() instanceof InterfaceDescriptor ) ) { /** @var ClassDescriptor|InterfaceDescriptor $parentClass */ $parentClass = $associatedClass->getParent(); return $parentClass->getProperties()->get($this->getName()); } return null; } } setValueAndCheckIfModified('visibility', $visibilityFlag); } /** * Returns the bit flag representing which visibilities are allowed. * * @see self::isVisibilityAllowed() for a convenience method to easily check against a specific visibility. * * @return integer */ public function getVisibility() { return $this->visibility; } /** * Returns whether one of the values of this object was modified. * * @return boolean */ public function isModified() { return $this->isModified; } /** * Resets the flag indicating whether the settings have changed. * * @return void */ public function clearModifiedFlag() { $this->isModified = false; } /** * Sets a property's value and if it differs from the previous then mark these settings as modified. */ protected function setValueAndCheckIfModified($propertyName, $value) { if ($this->$propertyName != $value) { $this->isModified = true; } $this->$propertyName = $value; } } setName($name); $this->setSettings(new Settings()); $namespace = new NamespaceDescriptor(); $namespace->setName('\\'); $namespace->setFullyQualifiedStructuralElementName('\\'); $this->setNamespace($namespace); $this->setFiles(new Collection()); $this->setIndexes(new Collection()); $this->setPartials(new Collection()); } /** * Sets the name for this project. * * @param string $name * * @return void */ public function setName($name) { $this->name = $name; } /** * Returns the name of this project. * * @return string */ public function getName() { return $this->name; } /** * Sets all files on this project. * * @param Collection $files * * @return void */ public function setFiles($files) { $this->files = $files; } /** * Returns all files with their sub-elements. * * @return Collection|FileDescriptor[] */ public function getFiles() { return $this->files; } /** * Sets all indexes for this project. * * An index is a compilation of references to elements, usually constructed in a compiler step, that aids template * generation by providing a conveniently assembled list. An example of such an index is the 'marker' index where * a list of TODOs and FIXMEs are located in a central location for reporting. * * @param Collection $indexes * * @return void */ public function setIndexes(Collection $indexes) { $this->indexes = $indexes; } /** * Returns all indexes in this project. * * @see setIndexes() for more information on what indexes are. * * @return Collection */ public function getIndexes() { return $this->indexes; } /** * Sets the root namespace for this project together with all sub-namespaces. * * @param NamespaceDescriptor $namespace * * @return void */ public function setNamespace($namespace) { $this->namespace = $namespace; } /** * Returns the root (global) namespace. * * @return NamespaceDescriptor */ public function getNamespace() { return $this->namespace; } /** * Sets the settings used to build the documentation for this project. * * @param Settings $settings * * @return void */ public function setSettings($settings) { $this->settings = $settings; } /** * Returns the settings used to build the documentation for this project. * * @return Settings */ public function getSettings() { return $this->settings; } /** * Sets all partials that can be used in a template. * * Partials are blocks of text that can be inserted anywhere in a template using a special indicator. An example is * the introduction partial that can add a custom piece of text to the homepage. * * @param Collection $partials * * @return void */ public function setPartials(Collection $partials) { $this->partials = $partials; } /** * Returns a list of all partials. * * @see setPartials() for more information on partials. * * @return Collection */ public function getPartials() { return $this->partials; } /** * Checks whether the Project supports the given visibility. * * @param integer $visibility One of the VISIBILITY_* constants of the Settings class. * * @see Settings for a list of the available VISIBILITY_* constants. * * @return boolean */ public function isVisibilityAllowed($visibility) { $visibilityAllowed = $this->getSettings() ? $this->getSettings()->getVisibility() : Settings::VISIBILITY_DEFAULT; return (bool) ($visibilityAllowed & $visibility); } } items = $items; } /** * Adds a new item to this collection, generally a Descriptor. * * @param DescriptorAbstract|mixed $item * * @return void */ public function add($item) { $this->items[] = $item; } /** * Sets a new object onto the collection or clear it using null. * * @param string|integer $index An index value to recognize this item with. * @param DescriptorAbstract|mixed|null $item The item to store, generally a Descriptor but may be something else. * * @return void */ public function set($index, $item) { $this->offsetSet($index, $item); } /** * Retrieves a specific item from the Collection with its index. * * Please note that this method (intentionally) has the side effect that whenever a key does not exist that it will * be created with the value provided by the $valueIfEmpty argument. This will allow for easy initialization during * tree building operations. * * @param string|integer $index * @param mixed $valueIfEmpty If the index does not exist it will be created with this value and returned. * * @return mixed The contents of the element with the given index and the provided default if the key doesn't exist. */ public function get($index, $valueIfEmpty = null) { if (!$this->offsetExists($index) && $valueIfEmpty !== null) { $this->offsetSet($index, $valueIfEmpty); } return $this->offsetGet($index); } /** * Retrieves all items from this collection as PHP Array. * * @return mixed[] */ public function getAll() { return $this->items; } /** * Retrieves an iterator to traverse this object. * * @return \Traversable|\ArrayIterator */ public function getIterator() { return new \ArrayIterator($this->items); } /** * Returns a count of the number of elements in this collection. * * @return integer */ public function count() { return count($this->items); } /** * Empties the collection. * * @return void */ public function clear() { $this->items = array(); } /** * Retrieves an item as if it were a property of the collection. * * @param string $name * * @return mixed */ public function __get($name) { return $this->get($name); } /** * Checks whether an item in this collection exists. * * @param string|integer $offset The index to check on. * * @return boolean */ public function offsetExists($offset) { return isset($this->items[$offset]); } /** * Retrieves an item from the collection with the given index. * * @param string|integer $offset The offset to retrieve. * * @return mixed */ public function offsetGet($offset) { return ($this->offsetExists($offset)) ? $this->items[$offset] : null; } /** * Sets an item at the given index. * * @param string|integer $offset The offset to assign the value to. * @param mixed $value The value to set. * * @throws \InvalidArgumentException if the key is null or an empty string. * * @return void */ public function offsetSet($offset, $value) { if ($offset === '' || $offset === null) { throw new \InvalidArgumentException('The key of a collection must always be set'); } $this->items[$offset] = $value; } /** * Removes an item with the given index from the collection. * * @param string|integer $offset The offset to unset. * * @return void */ public function offsetUnset($offset) { unset($this->items[$offset]); } /** * Returns a new collection with the items from this collection and the provided combined. * * @param Collection $collection * * @return Collection */ public function merge(Collection $collection) { return new Collection(array_merge($this->items, $collection->getAll())); } } cache = $cache; } /** * Returns the Cache instance for this Mapper. * * @return IterableInterface|StorageInterface */ public function getCache() { return $this->cache; } /** * Returns the Project Descriptor from the cache. * * @param ProjectDescriptor $projectDescriptor * * @return void */ public function populate(ProjectDescriptor $projectDescriptor) { /** @var IteratorInterface $iteratorInterface */ $iteratorInterface = $this->getCache()->getIterator(); // load the settings object try { $settings = $this->getCache()->getItem(self::KEY_SETTINGS); } catch (\Exception $e) { $settings = $this->igBinaryCompatibleCacheClear(self::KEY_SETTINGS, $e); } if ($settings) { $projectDescriptor->setSettings($settings); } // FIXME: Workaround for: https://github.com/zendframework/zf2/pull/4154 if ($iteratorInterface->valid()) { foreach ($this->getCache() as $key) { try { $item = $this->getCache()->getItem($key); } catch (\Exception $e) { $this->igBinaryCompatibleCacheClear($key, $e); } if ($item instanceof FileDescriptor) { $projectDescriptor->getFiles()->set($item->getPath(), $item); } } } } /** * Clears the cache if a serialization exception was thrown * * @param string $key * @param \Exception $e * * @throws \Exception Rethrows exception if nessesary * * @return void */ protected function igBinaryCompatibleCacheClear($key, $e) { if (extension_loaded('igbinary')) { $this->getCache()->removeItem($key); } else { throw $e; } } /** * Stores a Project Descriptor in the Cache. * * @param ProjectDescriptor $projectDescriptor * * @return void */ public function save(ProjectDescriptor $projectDescriptor) { $keys = array(); $cache = $this->getCache(); /** @var IteratorInterface $iteratorInterface */ $iteratorInterface = $cache->getIterator(); // FIXME: Workaround for: https://github.com/zendframework/zf2/pull/4154 if ($iteratorInterface->valid()) { foreach ($cache as $key) { $keys[] = $key; } } // store the settings for this Project Descriptor $cache->setItem(self::KEY_SETTINGS, $projectDescriptor->getSettings()); // store cache items $usedKeys = array(self::KEY_SETTINGS); foreach ($projectDescriptor->getFiles() as $file) { $key = self::FILE_PREFIX . md5($file->getPath()); $usedKeys[] = $key; $cache->setItem($key, $file); } // remove any keys that are no longer used. $invalidatedKeys = array_diff($keys, $usedKeys); if ($invalidatedKeys) { $cache->removeItems($invalidatedKeys); } if ($cache instanceof OptimizableInterface) { $cache->optimize(); } } /** * Removes all files in cache that do not occur in the given FileSet Collection. * * @param Collection $collection * * @return void */ public function garbageCollect(Collection $collection) { $projectRoot = $collection->getProjectRoot(); $filenames = $collection->getFilenames(); foreach ($filenames as &$name) { // the cache key contains a path relative to the project root; here we expect absolute paths. $name = self::FILE_PREFIX . md5(substr($name, strlen($projectRoot))); } /** @var IteratorInterface $iteratorInterface */ $iteratorInterface = $this->getCache()->getIterator(); // FIXME: Workaround for: https://github.com/zendframework/zf2/pull/4154 if ($iteratorInterface->valid()) { foreach ($this->getCache() as $item) { if (substr($item, 0, strlen(self::FILE_PREFIX)) === self::FILE_PREFIX && !in_array($item, $filenames)) { $this->getCache()->removeItem($item); } } } } } setTags(new Collection()); $this->setErrors(new Collection()); } /** * Sets the Fully Qualified Structural Element Name (FQSEN) for this element. * * @param string $name * * @return void */ public function setFullyQualifiedStructuralElementName($name) { $this->fqsen = $name; } /** * Returns the Fully Qualified Structural Element Name (FQSEN) for this element. * * @return string */ public function getFullyQualifiedStructuralElementName() { return $this->fqsen; } /** * Sets the local name for this element. * * @param string $name * * @return void */ public function setName($name) { $this->name = $name; } /** * Returns the local name for this element. * * @return string */ public function getName() { return $this->name; } /** * Sets the namespace (name) for this element. * * @param NamespaceDescriptor|string $namespace */ public function setNamespace($namespace) { $this->namespace = $namespace; } /** * Returns the namespace for this element or null if none is attached. * * @return NamespaceDescriptor|string|null */ public function getNamespace() { return $this->namespace; } /** * Sets the summary describing this element in short. * * @param string $summary * * @return void */ public function setSummary($summary) { $this->summary = $summary; } /** * Returns the summary which describes this element. * * This method will automatically attempt to inherit the parent's summary if this one has none. * * @return string */ public function getSummary() { if ($this->summary && strtolower(trim($this->summary)) != '{@inheritdoc}') { return $this->summary; } $parent = $this->getInheritedElement(); if ($parent instanceof DescriptorAbstract) { return $parent->getSummary(); } return $this->summary; } /** * Sets a description for this element. * * @param string $description * * @return void */ public function setDescription($description) { $this->description = $description; } /** * Returns the description for this element. * * This method will automatically attempt to inherit the parent's description if this one has none. * * @return string */ public function getDescription() { if ($this->description && strpos(strtolower($this->description), '{@inheritdoc}') === false) { return $this->description; } $parentElement = $this->getInheritedElement(); if ($parentElement instanceof DescriptorAbstract) { $parentDescription = $parentElement->getDescription(); return $this->description ? str_ireplace('{@inheritdoc}', $parentDescription, $this->description) : $parentDescription; } return $this->description; } /** * Sets the file and linenumber where this element is at. * * @param FileDescriptor $file * @param int $line * * @return void */ public function setLocation(FileDescriptor $file, $line = 0) { $this->setFile($file); $this->line = $line; } /** * Returns the path to the file containing this element relative to the project's root. * * @return string */ public function getPath() { return $this->fileDescriptor ? $this->fileDescriptor->getPath() : ''; } /** * Returns the file in which this element resides or null in case the element is not bound to a file.. * * @return FileDescriptor|null */ public function getFile() { return $this->fileDescriptor; } /** * Sets the file to which this element is associated. * * @param FileDescriptor $file * * @return false */ public function setFile(FileDescriptor $file) { $this->fileDescriptor = $file; } /** * Returns the line number where the definition for this element can be found. * * @return int */ public function getLine() { return $this->line; } /** * Sets the line number for this element's location in the source file. * * @param integer $lineNumber * * @return void */ public function setLine($lineNumber) { $this->line = $lineNumber; } /** * Sets the tags associated with this element. * * @param Collection $tags * * @return void */ public function setTags(Collection $tags) { $this->tags = $tags; } /** * Returns the tags associated with this element. * * @return Collection */ public function getTags() { return $this->tags; } /** * Sets the name of the package to which this element belongs. * * @param PackageDescriptor $package * * @return void */ public function setPackage($package) { $this->package = $package; } /** * Returns the package name for this element. * * @return PackageDescriptor */ public function getPackage() { $inheritedElement = $this->getInheritedElement(); if ($this->package instanceof PackageDescriptor && ! ($this->package->getName() === '\\' && $inheritedElement)) { return $this->package; } if ($inheritedElement instanceof DescriptorAbstract) { return $inheritedElement->getPackage(); } return null; } /** * @return Collection */ public function getAuthor() { /** @var Collection $author */ $author = $this->getTags()->get('author', new Collection()); if ($author->count() != 0) { return $author; } $inheritedElement = $this->getInheritedElement(); if ($inheritedElement) { return $inheritedElement->getAuthor(); } return new Collection(); } /** * Returns the versions for this element. * * @return Collection */ public function getVersion() { /** @var Collection $version */ $version = $this->getTags()->get('version', new Collection()); if ($version->count() != 0) { return $version; } $inheritedElement = $this->getInheritedElement(); if ($inheritedElement) { return $inheritedElement->getVersion(); } return new Collection(); } /** * Returns the copyrights for this element. * * @return Collection */ public function getCopyright() { /** @var Collection $copyright */ $copyright = $this->getTags()->get('copyright', new Collection()); if ($copyright->count() != 0) { return $copyright; } $inheritedElement = $this->getInheritedElement(); if ($inheritedElement) { return $inheritedElement->getCopyright(); } return new Collection(); } /** * Checks whether this element is deprecated. * * @return boolean */ public function isDeprecated() { return isset($this->tags['deprecated']); } /** * Sets a list of all errors associated with this element. * * @param Collection $errors */ public function setErrors(Collection $errors) { $this->errors = $errors; } /** * Returns all errors that occur in this element. * * @return Collection */ public function getErrors() { return $this->errors; } /** * Dynamically constructs a set of getters to retrieve tag (collections) with. * * Important: __call() is not a fast method of access; it is preferred to directly use the getTags() collection. * This interface is provided to allow for uniform and easy access to certain tags. * * @param string $name * @param mixed[] $arguments * * @return Collection|null */ public function __call($name, $arguments) { if (substr($name, 0, 3) !== 'get') { return null; } $tagName = substr($name, 3); $tagName[0] = strtolower($tagName[0]); // lowercase the first letter return $this->getTags()->get($tagName, new Collection()); } /** * Represents this object by its unique identifier, the Fully Qualified Structural Element Name. * * @return string */ public function __toString() { return $this->getFullyQualifiedStructuralElementName(); } /** * @return DescriptorAbstract|null */ public function getInheritedElement() { return $this->inheritedElement; } } setParent(new Collection()); $this->setConstants(new Collection()); $this->setMethods(new Collection()); } /** * {@inheritDoc} */ public function setParent($parents) { $this->parents = $parents; } /** * {@inheritDoc} */ public function getParent() { return $this->parents; } /** * {@inheritDoc} */ public function setConstants(Collection $constants) { $this->constants = $constants; } /** * {@inheritDoc} */ public function getConstants() { return $this->constants; } /** * {@inheritDoc} */ public function getInheritedConstants() { if (!$this->getParent() || !$this->getParent() instanceof Collection || $this->getParent()->count() === 0) { return new Collection(); } $inheritedConstants = new Collection(); /** @var self $parent */ foreach ($this->getParent() as $parent) { if (!$parent instanceof Interfaces\InterfaceInterface) { continue; } $inheritedConstants = $inheritedConstants->merge($parent->getConstants()); $inheritedConstants = $inheritedConstants->merge($parent->getInheritedConstants()); } return $inheritedConstants; } /** * {@inheritDoc} */ public function setMethods(Collection $methods) { $this->methods = $methods; } /** * {@inheritDoc} */ public function getMethods() { return $this->methods; } /** * {@inheritDoc} */ public function getInheritedMethods() { if (!$this->getParent() || !$this->getParent() instanceof Collection || $this->getParent()->count() === 0) { return new Collection(); } $inheritedMethods = new Collection(); /** @var self $parent */ foreach ($this->getParent() as $parent) { if (!$parent instanceof Interfaces\InterfaceInterface) { continue; } $inheritedMethods = $inheritedMethods->merge($parent->getMethods()); $inheritedMethods = $inheritedMethods->merge($parent->getInheritedMethods()); } return $inheritedMethods; } public function setPackage($package) { parent::setPackage($package); foreach ($this->getConstants() as $constant) { $constant->setPackage($package); } foreach ($this->getMethods() as $method) { $method->setPackage($package); } } public function getInheritedElement() { return $this->getParent() && $this->getParent()->count() > 0 ? $this->getParent()->getIterator()->current() : null; } } severity = $severity; $this->code = $code; $this->line = $line; $this->context = $context; } /** * @return string $code */ public function getCode() { return $this->code; } /** * @return int $line */ public function getLine() { return $this->line; } /** * @return string $severity */ public function getSeverity() { return $this->severity; } /** * @return array $context */ public function getContext() { return $this->context; } } getName(); } } getName(); } } baseType = $baseType; } /** * Returns the name for this type. * * @return TypeInterface */ public function getName() { return $this->baseType instanceof TypeInterface ? $this->baseType->getName() : $this->baseType; } /** * Returns the base type for this Collection or null if there is no attached type. * * When the presented collection is governed by an object (such as a Collection object) then a reference to that * object will be returned. If however the base type for this collection is a simple type such as an 'array' then * we return null to indicate there is no object governing this type. * * @return TypeInterface|null */ public function getBaseType() { return $this->baseType instanceof TypeInterface ? $this->baseType : null; } /** * Registers the base type for this collection type. * * @param string|TypeInterface $baseType * * @return void */ public function setBaseType($baseType) { $this->baseType = $baseType; } /** * Register the type, or set of types, to which a value in this type of collection can belong. * * @param TypeInterface[] $types * * @return void */ public function setTypes(array $types) { $this->types = $types; } /** * Returns the type, or set of types, to which a value in this type of collection can belong. * * @return TypeInterface[] */ public function getTypes() { return $this->types; } /** * Registers the type, or set of types, to which a *key* in this type of collection can belong. * * @param TypeInterface[] $types * * @return void */ public function setKeyTypes(array $types) { $this->keyTypes = $types; } /** * Registers the type, or set of types, to which a *key* in this type of collection can belong. * * @return TypeInterface[] */ public function getKeyTypes() { return $this->keyTypes; } /** * Returns a human-readable representation for this type. * * @return string */ public function __toString() { $name = $this->getName(); $keyTypes = array(); foreach ($this->getKeyTypes() as $type) { $keyTypes[] = (string) $type; } $types = array(); foreach ($this->getTypes() as $type) { $types[] = (string) $type; } if (count($types) > 0) { $name .= '<' . ($keyTypes ? implode('|', $keyTypes) . ',' : '') . implode('|', $types) . '>'; } return $name; } } name = $name; } /** * Returns the name for this identifier. * * @return string */ public function getName() { return $this->name; } /** * Returns a human-readable name for this type. * * @return string */ public function __toString() { return $this->getName(); } } getName(); } } getName(); } } getFullyQualifiedStructuralElementName() . '::' . $this->getName() : $this->getName(); $this->setFullyQualifiedStructuralElementName($fqsen); $this->parent = $parent; } /** * @return null|ClassDescriptor|InterfaceDescriptor */ public function getParent() { return $this->parent; } /** * {@inheritDoc} */ public function setTypes(Collection $types) { $this->types = $types; } /** * {@inheritDoc} */ public function getTypes() { if ($this->types === null) { $this->types = new Collection(); /** @var VarDescriptor $var */ $var = $this->getVar()->get(0); if ($var) { $this->types = $var->getTypes(); } } return $this->types; } /** * {@inheritDoc} */ public function setValue($value) { $this->value = $value; } /** * {@inheritDoc} */ public function getValue() { return $this->value; } /** * @return Collection */ public function getVar() { /** @var Collection $var */ $var = $this->getTags()->get('var', new Collection()); if ($var->count() != 0) { return $var; } $inheritedElement = $this->getInheritedElement(); if ($inheritedElement) { return $inheritedElement->getVar(); } return new Collection(); } /** * Returns the file associated with the parent class, interface or trait when inside a container. * * @return FileDescriptor */ public function getFile() { return parent::getFile() ?: $this->getParent()->getFile(); } /** * Returns the Constant from which this one should inherit, if any. * * @return ConstantDescriptor|null */ public function getInheritedElement() { /** @var ClassDescriptor|InterfaceDescriptor|null $associatedClass */ $associatedClass = $this->getParent(); if (($associatedClass instanceof ClassDescriptor || $associatedClass instanceof InterfaceDescriptor) && ($associatedClass->getParent() instanceof ClassDescriptor || $associatedClass->getParent() instanceof InterfaceDescriptor ) ) { /** @var ClassDescriptor|InterfaceDescriptor $parentClass */ $parentClass = $associatedClass->getParent(); return $parentClass->getConstants()->get($this->getName()); } return null; } } initialize(); * * This will setup the autoloader and application, including Service Container, and return an instance of the * application ready to be ran using the `run` command. * * If you need more control you can do some of the steps manually: * * $bootstrap = Bootstap::createInstance(); * $autoloader = $bootstrap->createAutoloader(); * $app = new Application($autoloader) */ class Bootstrap { /** * Helper static function to get an instance of this class. * * Usually used to do a one-line initialization, such as: * * \phpDocumentor\Bootstrap::createInstance()->initialize(); * * @return Bootstrap */ public static function createInstance() { return new self(); } /** * Convenience method that does the complete initialization for phpDocumentor. * * @return Application */ public function initialize() { $vendorPath = $this->findVendorPath(); $autoloader = $this->createAutoloader($vendorPath); return new Application($autoloader, array('composer.vendor_path' => $vendorPath)); } /** * Sets up XHProf so that we can profile phpDocumentor using XHGUI. * * @return self */ public function registerProfiler() { // check whether xhprof is loaded $profile = (bool) (getenv('PHPDOC_PROFILE') === 'on'); $xhguiPath = getenv('XHGUI_PATH'); if ($profile && $xhguiPath && extension_loaded('xhprof')) { echo 'PROFILING ENABLED' . PHP_EOL; include($xhguiPath . '/external/header.php'); } return $this; } /** * Initializes and returns the autoloader. * * @param string|null $vendorDir A path (either absolute or relative to the current working directory) leading to * the vendor folder where composer installed the dependencies. * * @throws \RuntimeException if no autoloader could be found. * * @return ClassLoader */ public function createAutoloader($vendorDir = null) { if (! $vendorDir) { $vendorDir = __DIR__ . '/../../vendor'; } $autoloader_location = $vendorDir . '/autoload.php'; if (! file_exists($autoloader_location) || ! is_readable($autoloader_location)) { throw new \RuntimeException( 'phpDocumentor expected to find an autoloader at "' . $autoloader_location . '" but it was not there. ' . 'Usually this is because the "composer install" command has not been ran yet. If this is not the ' . 'case, please open an issue at http://github.com/phpDocumentor/phpDocumentor2 detailing what ' . 'installation method you used, which path is mentioned in this error message and any other relevant ' . 'information.' ); } return require $autoloader_location; } /** * Attempts to find the location of the vendor folder. * * This method tries to check for a composer.json in a directory 5 levels below the folder of this Bootstrap file. * This is the expected location if phpDocumentor is installed using composer because the current directory for * this file is expected to be 'vendor/phpdocumentor/phpdocumentor/src/phpDocumentor'. * * If a composer.json is found we will try to extract the vendor folder name using the 'vendor-dir' configuration * option of composer or assume it is vendor if that option is not set. * * * If no custom composer.json can be found, then we assume that the vendor folder is that of phpDocumentor itself, * which is `../../vendor` starting from this folder. * * If neither locations exist, then this method returns null because no vendor path could be found. * * @param $baseDir parameter for test purposes only. * @return string|null */ public function findVendorPath($baseDir = __DIR__) { // default installation $vendorDir = $baseDir . '/../../vendor'; // Composerised installation, vendor/phpdocumentor/phpdocumentor/src/phpDocumentor is __DIR__ $rootFolderWhenInstalledWithComposer = $baseDir . '/../../../../../'; $composerConfigurationPath = $rootFolderWhenInstalledWithComposer .'composer.json'; if (file_exists($composerConfigurationPath)) { $vendorDir = $rootFolderWhenInstalledWithComposer . $this->getCustomVendorPathFromComposer($composerConfigurationPath); } return file_exists($vendorDir) ? $vendorDir : null; } /** * Retrieves the custom vendor-dir from the given composer.json or returns 'vendor'. * * @param string $composerConfigurationPath the path pointing to the composer.json * * @return string */ protected function getCustomVendorPathFromComposer($composerConfigurationPath) { $composerFile = file_get_contents($composerConfigurationPath); $composerJson = json_decode($composerFile, true); return isset($composerJson['config']['vendor-dir']) ? $composerJson['config']['vendor-dir'] : 'vendor'; } } locale; } } getTranslator()->getLocale(); $app['translator'] = $app->share( function ($app) { $translator = new Translator(); $translator->setLocale($app['translator.locale']); return $translator; } ); } } 'translated message', * ); * ``` */ class Translator extends ZendTranslator { /** * The translation file type. * * This type is hardcoded into a constant to simplify the signature of the addTranslationFile and * addTranslationFilePattern methods. This will simplify the migration to another component in the future as an * incompatibility between two libraries may emerge due to differing types or typenames. * * This translator class may be used by plugin developers to have translating elements in their plugins; as such * the signatures here are considered to be stable / api. * @var string */ const TRANSLATION_FILE_TYPE = 'phparray'; /** @var string Represents the default locale for phpDocumentor */ const DEFAULT_LOCALE = 'en'; /** @var string Translation strings may be divided into 'domains', this is the default domain */ const DEFAULT_DOMAIN = 'default'; /** @var string the default name of files loaded by {@see self::addTranslationFolder()} */ const DEFAULT_PATTERN = '%s.php'; /** * Pre-set the translator with the default locale as fallback. */ public function __construct() { $this->setLocale(self::DEFAULT_LOCALE); $this->setFallbackLocale(self::DEFAULT_LOCALE); } /** * Sets the default locale to use when translating messages. * * @param string $locale * * @api * * @return Translator */ public function setLocale($locale) { return parent::setLocale($locale); } /** * Adds a translation file for a specific locale, or the default locale when none is provided. * * @param string $filename Name of the file to add. * @param string|null $locale The locale to assign to, matches * {@link http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes ISO-639-1} and defaults to en (English). * @param string $textDomain Translations may be divided into separate files / domains; this represents in * which domain the translation should be. * * @api * * @return $this */ public function addTranslations($filename, $locale = self::DEFAULT_LOCALE, $textDomain = self::DEFAULT_DOMAIN) { parent::addTranslationFile(self::TRANSLATION_FILE_TYPE, $filename, $textDomain, $locale); $this->messages = array(); return $this; } /** * Adds a folder with files containing translation sources. * * This method scans the provided folder for any file matching the following format: * * `[domain].[locale].php` * * If the domain matches the {@see self::DEFAULT_DOMAIN default domain} then that part is omitted and the filename * should match: * * `[locale].php` * * @link http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes for a list of ISO-639-1 locale codes as used by * this method. * * @param string $folder Name of the folder, it is recommended to use an absolute path. * @param string[] $domains One or more domains to load, when none is provided only the default is added. * * @api * * @return $this */ public function addTranslationFolder($folder, array $domains = array()) { if (empty($domains)) { $domains = array(self::DEFAULT_DOMAIN); } foreach ($domains as $domain) { $this->addTranslationsUsingPattern($folder, $domain); } return $this; } /** * Adds a series of translation files given a pattern. * * This method will search the base directory for a series of files matching the given pattern (where %s is replaces * by the two-letter locale shorthand) and adds any translations to the translation table. * * @param string $baseDir Directory to search in (not-recursive) * @param string $textDomain The domain to assign the translation messages to. * @param string $pattern The pattern used to load files for all languages, one variable `%s` is supported and * is replaced with the {@link http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes ISO-639-1 code} for each * locale that is requested by the translate method. * * @internal this method is not to be used by consumers; it is an extension of the Zend Translator component * and is overridden to clear the messages caching array so it may be rebuild. * * @see self::addTranslationFolder() to provide a series of translation files. * * @return $this|ZendTranslator */ public function addTranslationsUsingPattern( $baseDir, $textDomain = self::DEFAULT_DOMAIN, $pattern = self::DEFAULT_PATTERN ) { if ($textDomain !== self::DEFAULT_DOMAIN && $pattern === self::DEFAULT_PATTERN) { $pattern = $textDomain . '.' . $pattern; } parent::addTranslationFilePattern(self::TRANSLATION_FILE_TYPE, $baseDir, $pattern, $textDomain); $this->messages = array(); return $this; } /** * Attempts to translate the given message or code into the provided locale. * * @param string $message The message or code to translate. * @param string $textDomain A message may be located in a domain, here you can provide in which. * @param null $locale The locale to translate to or the default if not set. * * @return string */ public function translate($message, $textDomain = self::DEFAULT_DOMAIN, $locale = null) { return parent::translate($message, $textDomain, $locale); } } priority = $priority; return $this; } } message = $message; return $this; } /** * Returns the message that was provided with this event. * * @return string */ public function getMessage() { return $this->message; } /** * Returns the priority level associated with this logging event. * * @return int */ public function getPriority() { return $this->priority; } /** * Sets additional context (parameters) to use when translating messages. * * @param string[] $context * * @return self */ public function setContext(array $context) { $this->context = $context; return $this; } /** * Returns the context for this event. * * @return string[] */ public function getContext() { return $this->context; } } subject = $subject; } /** * Returns the object that is the subject of this event. * * @return object */ public function getSubject() { return $this->subject; } /** * Creates a new instance of a derived object and return that. * * Used as convenience method for fluent interfaces. * * @param object $subject * * @return static */ public static function createInstance($subject) { return new static($subject); } } ") * @var Parameter[] parameters that are configured by the user */ protected $parameters = array(); /** * Initialize the plugin configuration definition with the given class name. * * @param string $className */ public function __construct($className) { $this->className = $className; } /** * Returns the class name for this plugin. * * @return string */ public function getClassName() { return $this->className; } /** * Returns the parameters associated with this plugin. * * @return Parameter[] */ public function getParameters() { return $this->parameters; } } getSource()); $this->$type_method($project, $transformation); } /** * Creates a class inheritance diagram. * * @param ProjectDescriptor $project * @param Transformation $transformation * * @return void */ public function processClass(ProjectDescriptor $project, Transformation $transformation) { try { $this->checkIfGraphVizIsInstalled(); } catch (\Exception $e) { echo $e->getMessage(); return; } if ($transformation->getParameter('font') !== null && $transformation->getParameter('font')->getValue()) { $this->nodeFont = $transformation->getParameter('font')->getValue(); } else { $this->nodeFont = 'Courier'; } $filename = $this->getDestinationPath($transformation); $graph = GraphVizGraph::create() ->setRankSep('1.0') ->setCenter('true') ->setRank('source') ->setRankDir('RL') ->setSplines('true') ->setConcentrate('true'); $this->buildNamespaceTree($graph, $project->getNamespace()); $classes = $project->getIndexes()->get('classes', new Collection())->getAll(); $interfaces = $project->getIndexes()->get('interfaces', new Collection())->getAll(); $traits = $project->getIndexes()->get('traits', new Collection())->getAll(); /** @var ClassDescriptor[]|InterfaceDescriptor[]|TraitDescriptor[] $containers */ $containers = array_merge($classes, $interfaces, $traits); foreach ($containers as $container) { $from_name = $container->getFullyQualifiedStructuralElementName(); $parents = array(); $implemented = array(); if ($container instanceof ClassDescriptor) { if ($container->getParent()) { $parents[] = $container->getParent(); } $implemented = $container->getInterfaces()->getAll(); } if ($container instanceof InterfaceDescriptor) { $parents = $container->getParent()->getAll(); } /** @var string|ClassDescriptor|InterfaceDescriptor $parent */ foreach ($parents as $parent) { $edge = $this->createEdge($graph, $from_name, $parent); $edge->setArrowHead('empty'); $graph->link($edge); } /** @var string|ClassDescriptor|InterfaceDescriptor $parent */ foreach ($implemented as $parent) { $edge = $this->createEdge($graph, $from_name, $parent); $edge->setStyle('dotted'); $edge->setArrowHead('empty'); $graph->link($edge); } } $graph->export('svg', $filename); } /** * Creates a GraphViz Edge between two nodes. * * @param Graph $graph * @param string $from_name * @param string|ClassDescriptor|InterfaceDescriptor|TraitDescriptor $to * * @return Edge */ protected function createEdge($graph, $from_name, $to) { $to_name = !is_string($to) ? $to->getFullyQualifiedStructuralElementName() : $to; if (!isset($this->nodeCache[$from_name])) { $this->nodeCache[$from_name] = $this->createEmptyNode($from_name, $graph); } if (!isset($this->nodeCache[$to_name])) { $this->nodeCache[$to_name] = $this->createEmptyNode($to_name, $graph); } return Edge::create($this->nodeCache[$from_name], $this->nodeCache[$to_name]); } /** * @param string $name * @param Graph $graph * * @return Node */ protected function createEmptyNode($name, $graph) { $node = Node::create($name); $node->setFontColor('gray'); $node->setLabel($name); $graph->setNode($node); return $node; } /** * Builds a tree of namespace subgraphs with their classes associated. * * @param GraphVizGraph $graph * @param NamespaceDescriptor $namespace * * @return void */ protected function buildNamespaceTree(GraphVizGraph $graph, NamespaceDescriptor $namespace) { $full_namespace_name = $namespace->getFullyQualifiedStructuralElementName(); if ($full_namespace_name == '\\') { $full_namespace_name = 'Global'; } $sub_graph = GraphVizGraph::create('cluster_' . $full_namespace_name) ->setLabel($namespace->getName() == '\\' ? 'Global' : $namespace->getName()) ->setStyle('rounded') ->setColor('gray') ->setFontColor('gray') ->setFontSize('11') ->setRankDir('LR'); $elements = array_merge( $namespace->getClasses()->getAll(), $namespace->getInterfaces()->getAll(), $namespace->getTraits()->getAll() ); /** @var ClassDescriptor|InterfaceDescriptor|TraitDescriptor $sub_element */ foreach ($elements as $sub_element) { $node = Node::create($sub_element->getFullyQualifiedStructuralElementName(), $sub_element->getName()) ->setShape('box') ->setFontName($this->nodeFont) ->setFontSize('11'); if ($sub_element instanceof ClassDescriptor && $sub_element->isAbstract()) { $node->setLabel('<«abstract»
' . $sub_element->getName(). '>'); } //$full_name = $sub_element->getFullyQualifiedStructuralElementName(); //$node->setURL($this->class_paths[$full_name]); //$node->setTarget('_parent'); $this->nodeCache[$sub_element->getFullyQualifiedStructuralElementName()] = $node; $sub_graph->setNode($node); } foreach ($namespace->getChildren()->getAll() as $element) { $this->buildNamespaceTree($sub_graph, $element); } $graph->addGraph($sub_graph); } /** * @param \phpDocumentor\Transformer\Transformation $transformation * @return string */ protected function getDestinationPath(Transformation $transformation) { $filename = $transformation->getTransformer()->getTarget() . DIRECTORY_SEPARATOR . $transformation->getArtifact(); return $filename; } /** * Checks whether GraphViz is installed and throws an Exception otherwise. * * @throws ExtensionNotLoadedException if graphviz is not found. * * @return void */ protected function checkIfGraphVizIsInstalled() { // NOTE: the -V flag sends output using STDERR and STDOUT exec('dot -V 2>&1', $output, $error); if ($error != 0) { throw new ExtensionNotLoadedException( 'Unable to find the `dot` command of the GraphViz package. ' . 'Is GraphViz correctly installed and present in your path?' ); } } } entityName = $name; $this->lineNumber = $docblock ? $docblock->getLocation()->getLineNumber() : $source->getLineNumber(); $this->docblock = $docblock; $this->source = $source; } /** * Set the options that may be used whilst validating the docblocks. * Can contain configuration as long as each validator knows how to * interrogate it * * @param array $options Options that may be used during validation * * @return void */ public function setOptions($options) { $this->options = $options; } abstract public function isValid(BaseReflector $element); /** * Dispatches an event to the Event Dispatcher. * * This method tries to dispatch an event; if no Event Dispatcher has been * set than this method will explicitly not fail and return null. * * By not failing we make the Event Dispatcher optional and is it easier * for people to re-use this component in their own application. * * @param string $name Name of the event to dispatch. * @param EventAbstract $event Arguments for this event. * * @throws \Exception if there is a dispatcher but it is not of type EventDispatcher * * @return void */ public function dispatch($name, $event) { if (!$this->event_dispatcher) { return null; } if (!$this->event_dispatcher instanceof Dispatcher) { throw new \Exception( 'Expected the event dispatcher to be an instance of phpDocumentor\Event\Dispatcher' ); } $this->event_dispatcher->dispatch($name, $event); } /** * Dispatches a logging request. * * @param string $message The message to log. * @param string $priority The logging priority. * * @return void */ public function log($message, $priority = LogLevel::INFO) { $this->dispatch( 'system.log', LogEvent::createInstance($this) ->setMessage($message) ->setPriority($priority) ); } /** * Dispatches a parser error to be logged. * * @param string $type The logging priority as string * @param string $code The message to log. * @param string $line The line number where the error occurred.. * @param string[] $variables an array with message substitution variables. * * @return void */ public function logParserError($type, $code, $line, $variables = array()) { $message = $this->__($code, $variables); $this->log($message, LogLevel::ERROR); $this->dispatch( 'parser.log', LogEvent::createInstance($this) ->setMessage($message) ->setType($type) ->setCode($code) ->setLine($line) ); } /** * Dispatches a logging request to log a debug message. * * @param string $message The message to log. * * @return void */ public function debug($message) { $this->dispatch('system.debug', DebugEvent::createInstance($this)->setMessage($message)); } /** * Translates the ID or message in the given language. * * Translation messages may contain any formatting as used by the php * vsprintf function. * * @param string $message ID or message to translate. * @param array $variables Variables to use for substitution. * @codingStandardsIgnoreStart * * @return string */ public function __($message, $variables = array()) { if (!$this->translate) { return vsprintf($message, $variables); } $translator = $this->translate; return vsprintf($translator->translate($message), $variables); } /** * Returns the configuration for this object. * * @return \Zend\Config\Config */ public function getConfiguration() { return $this->configuration; } /** * Returns the event dispatcher. * * @return Dispatcher */ public function getEventDispatcher() { return $this->event_dispatcher; } /** * Returns the translation component. * * @return Translator|null */ public function getTranslator() { return $this->translate; } } getDocBlock(); if (null === $docBlock) { throw new \UnexpectedValueException( 'A DocBlock should be present (and validated) before this validator can be applied' ); } if ($docBlock->hasTag('return')) { $returnTag = current($docBlock->getTagsByName('return')); if ($returnTag->getType() == 'type') { return new Error(LogLevel::WARNING, 'PPC:ERR-50017', $element->getLinenumber()); } } return null; } /** * Returns an error if the given Reflector's arguments do not match expectations. * * @param FunctionReflector $element * * @return Error|null */ protected function validateArguments($element) { $params = $element->getDocBlock()->getTagsByName('param'); $arguments = $element->getArguments(); foreach (array_values($arguments) as $key => $argument) { if (!$this->isArgumentInDocBlock($key, $argument, $element, $params)) { continue; } $result = $this->doesArgumentNameMatchParam($params[$key], $argument, $element); if ($result) { return $result; } $result = $this->doesArgumentTypehintMatchParam($params[$key], $argument, $element); if ($result) { return $result; } } /** @var ParamTag $param */ foreach ($params as $param) { $param_name = $param->getVariableName(); if (isset($arguments[$param_name])) { continue; } return new Error( LogLevel::NOTICE, 'PPC:ERR-50013', $element->getLinenumber(), array($param_name, $element->getName()) ); } return null; } /** * Validates whether an argument is mentioned in the docblock. * * @param integer $index The position in the argument listing. * @param ArgumentReflector $argument The argument itself. * @param BaseReflector $element * @param Tag[] $params The list of param tags to validate against. * * @return bool whether an issue occurred. */ protected function isArgumentInDocBlock($index, ArgumentReflector $argument, BaseReflector $element, array $params) { if (isset($params[$index])) { return null; } return new Error( LogLevel::ERROR, 'PPC:ERR-50015', $argument->getLinenumber(), array($argument->getName(), $element->getName()) ); } /** * Validates whether the name of the argument is the same as that of the * param tag. * * If the param tag does not contain a name then this method will set it * based on the argument. * * @param ParamTag $param param to validate with. * @param ArgumentReflector $argument Argument to validate against. * @param BaseReflector $element * * @return Error|null whether an issue occurred */ protected function doesArgumentNameMatchParam(ParamTag $param, ArgumentReflector $argument, BaseReflector $element) { $param_name = $param->getVariableName(); if ($param_name == $argument->getName()) { return null; } if ($param_name == '') { $param->setVariableName($argument->getName()); return null; } return new Error( LogLevel::ERROR, 'PPC:ERR-50014', $argument->getLinenumber(), array($argument->getName(), $param_name, $element->getName()) ); } /** * Checks the typehint of the argument versus the @param tag. * * If the argument has no typehint we do not check anything. When multiple * type are given then the typehint needs to be one of them. * * @param ParamTag $param * @param ArgumentReflector $argument * @param BaseReflector $element * * @return Error|null */ protected function doesArgumentTypehintMatchParam( ParamTag $param, ArgumentReflector $argument, BaseReflector $element ) { if (!$argument->getType() || in_array($argument->getType(), $param->getTypes())) { return null; } elseif ($argument->getType() == 'array' && substr($param->getType(), -2) == '[]') { return null; } return new Error( LogLevel::ERROR, 'PPC:ERR-50016', $argument->getLinenumber(), array($argument->getName(), $element->getName()) ); } } // * @author Mike van Riel // * @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com) // * @license http://www.opensource.org/licenses/mit-license.php MIT // * @link http://phpdoc.org // */ // //namespace phpDocumentor\Plugin\Core\Descriptor\Validator; // ///** // * This class is responsible for validating which tags are required // * as defined in /src/phpDocumentor/Plugin/Core/plugin.xml // * // * @category phpDocumentor // * @package Parser // * @subpackage DocBlock_Validators // * @author Ben Selby // * @author Mike van Riel // * @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com) // * @license http://www.opensource.org/licenses/mit-license.php MIT // * @link http://phpdoc.org // */ //class RequiredValidator extends ValidatorAbstract //{ // /** // * Is the docblock valid based on the rules defined in plugin.xml // * // * // * // * // * // * // * @see ValidatorAbstract::isValid() // * // * @return void // */ // public function isValid() // { // $docType = get_class($this->source); // if (isset($this->options['required'][$docType])) { // $this->validateTags($docType); // } elseif (isset($this->options['required']['__ALL__'])) { // $this->validateTags('__ALL__'); // } // } // // /** // * Validate the tags based on the type of docblock being // * parsed etc // * // * @param string $key Access key to $this->options['required'] // * // * @return void // */ // protected function validateTags($key) // { // foreach ($this->options['required'][$key] as $tag) { // if (count($this->docblock->getTagsByName($tag)) == 0) { // $this->logParserError( // 'CRITICAL', // 'PPC:ERR-50020', // $this->lineNumber, // array($tag, $this->entityName) // ); // } // } // } //} parameter) || empty($value->argument)) { return null; } $parameterName = $value->parameter->getVariableName(); $argumentName = $value->argument->getName(); if ($parameterName == $argumentName) { return null; } if ($parameterName == '') { $value->parameter->setVariableName($argumentName); return null; } $violation = $this->context->addViolationAt( 'argument', $constraint->message, array($argumentName, $parameterName, $value->fqsen), null, null, $constraint->code ); } } getResponse(); if ($return instanceof ReturnDescriptor) { $types = $return->getTypes(); if (is_array($types) && !empty($types) && preg_grep('/^.*type$/', $types)) { $this->context->addViolationAt( 'response', $constraint->message, array($return->getName(), $value->getFullyQualifiedStructuralElementName()), null, null, $constraint->code ); } } } } arguments; $parameters = $value->parameters; if (count($arguments) > 0 && $parameters instanceof \ArrayAccess) { foreach ($parameters as $param) { $paramVarName = $param->getVariableName(); if (empty($paramVarName) || $arguments->offsetExists($paramVarName)) { continue; } $this->context->addViolationAt( 'argument', $constraint->message, array($paramVarName, $value->fqsen), null, null, $constraint->code ); } } return null; } } constraint = $constraint; $this->initValueObject($value); $violation = $this->processArgumentValidation(); if ($violation) { return $violation; } $this->checkParamsExists(); } protected function initValueObject($value) { $this->validationValue = new ValidationValueObject(); $this->validationValue->fqsen = $value->getFullyQualifiedStructuralElementName(); $this->validationValue->arguments = $value->getArguments(); $this->validationValue->parameters = $value->getParam(); $this->validationValue->name = $value->getName(); } /** * @return null */ protected function processArgumentValidation() { $arguments = $this->validationValue->arguments->getAll(); foreach (array_values($arguments) as $key => $argument) { $this->validationValue->key = $key; $this->validationValue->argument = $argument; $this->validationValue->index = $key; $this->validationValue->parameter = isset($this->validationValue->parameters[$key]) ? $this->validationValue->parameters[$key] : null; if ($this->checkArgumentInDocBlock()) { continue; } $violation = $this->checkArgumentNameMatchParam(); if ($violation) { return $violation; } $violation = $this->checkArgumentTypehintMatchParam(); if ($violation) { return $violation; } } return null; } /** * Check if argument is inside docblock. */ protected function checkArgumentInDocBlock() { $validator = new IsArgumentInDocBlockValidator(); $validator->initialize($this->context); return $validator->validate($this->validationValue, new IsArgumentInDocBlock); } /** * Check if argument matches parameter. */ protected function checkArgumentNameMatchParam() { $validator = new DoesArgumentNameMatchParamValidator; $validator->initialize($this->context); return $validator->validate($this->validationValue, new DoesArgumentNameMatchParam); } /** * Check if argument typehint matches parameter. */ protected function checkArgumentTypehintMatchParam() { $validator = new DoesArgumentTypehintMatchParamValidator; $validator->initialize($this->context); return $validator->validate($this->validationValue, new DoesArgumentTypehintMatchParam); } /** * Check if parameter exists for argument. * * @param Collection $params * @param Collection $arguments */ protected function checkParamsExists() { $validator = new DoesParamsExistsValidator(); $validator->initialize($this->context); return $validator->validate($this->validationValue, new DoesParamsExists); } } argument; $parameter = $value->parameter; if ($argument instanceof ArgumentDescriptor && $parameter instanceof ParamDescriptor) { if (count($argument->getTypes()) === 0 || in_array(current($argument->getTypes()->getAll()), $parameter->getTypes()->getAll()) ) { return null; } elseif (current($argument->getTypes()->getAll()) === 'array' && substr(current($parameter->getTypes()->getAll()), -2) == '[]' ) { return null; } $this->context->addViolationAt( 'argument', $constraint->message, array($argument->getName(), $value->fqsen), null, null, $constraint->code ); } } } argument) > 0) { $argument = $value->argument; /* @var $params \phpDocumentor\Descriptor\Collection */ $params = $value->parameters; $index = (int) $value->index; if ($params && $params->offsetExists($index)) { return null; } $this->context->addViolationAt( 'argument', $constraint->message, array($argument->getName(), $value->name), null, null, $constraint->code ); } } /** * Returns whether the list of param tags features the given argument. * * @param ParamDescriptor[]|Collection $parameters * @param ArgumentDescriptor $argument * * @return boolean */ private function existsParamTagWithArgument($parameters, ArgumentDescriptor $argument) { foreach ($parameters as $parameter) { if ($argument->getName() == $parameter->getVariableName()) { return true; } } return false; } } getParam(); foreach ($params as $param) { if (! $param instanceof ParamDescriptor) { continue; } /** @var UnknownTypeDescriptor[]|Collection $types */ $types = $param->getTypes(); foreach ($types as $type) { if (! $this->isTypeAnIdeDefault($type)) { continue; } $this->context->addViolationAt( 'params', $constraint->message, array($param->getVariableName(), $value->getFullyQualifiedStructuralElementName()), null, null, $constraint->code ); } } } /** * Verifies if this type is a possible IDE default. * * @param UnknownTypeDescriptor|TypeInterface $type * * @return bool */ private function isTypeAnIdeDefault(TypeInterface $type) { return $type->getName() === '\\type' || $type->getName() === '\\unknown'; } } getTags()->get('subpackage', new Collection())->count() > 0 && $value->getTags()->get('package', new Collection())->count() < 1) { $this->context->addViolationAt('package', $constraint->message, array(), null, null, $constraint->code); } } } getTags()->get('package', new Collection())->count() > 1) { $this->context->addViolationAt('package', $constraint->message, array(), null, null, $constraint->code); } } } getTags()->get('subpackage', new Collection())->count() > 1) { $this->context->addViolationAt('package', $constraint->message, array(), null, null, $constraint->code); } } } getVar(); if (! $value->getSummary() && ($var->count() == 0 || ! current($var->getAll())->getDescription())) { $this->context->addViolationAt('summary', $constraint->message, array(), null, null, $constraint->code); } } } // * @author Mike van Riel // * @copyright 2010-2011 Mike van Riel / Naenius. (http://www.naenius.com) // * @license http://www.opensource.org/licenses/mit-license.php MIT // * @link http://phpdoc.org // */ //class DeprecatedValidator extends ValidatorAbstract //{ // /** // * Is the docblock valid based on the rules defined in plugin.xml // * // * // * // * // * // * // * @see ValidatorAbstract::isValid() // * // * @return boolean // */ // public function isValid() // { // $docType = get_class($this->source); // if (isset($this->options['deprecated'][$docType])) { // $this->validateTags($docType); // } elseif (isset($this->options['deprecated']['__ALL__'])) { // $this->validateTags('__ALL__'); // } // } // // /** // * Validate the tags based on the type of docblock being // * parsed etc // * // * @param string $key Access key to $this->options['required'] // * // * @return void // */ // protected function validateTags($key) // { // foreach ($this->options['deprecated'][$key] as $tag) { // if (count($this->docblock->getTagsByName($tag)) < 1) { // continue; // } // $this->logParserError('CRITICAL', 'PPC:ERR-50006', $this->lineNumber, array($tag, $this->entityName)); // } // } //} '', 'argument' => '', 'parameter' => '', 'parameters' => '', 'fqsen' => '', 'name' => '', 'index' => 0, 'key' => 0, ); public function __get($name) { if (!isset($this->data[$name])) { throw new \BadMethodCallException("Property {$name} not supported."); } return $this->data[$name]; } public function __set($name, $value) { if (!isset($this->data[$name])) { throw new \BadMethodCallException("Property {$name} not supported."); } if (!empty($value)) { $this->data[$name] = $value; } } public function __isset($name) { return array_key_exists($name, $this->data); } } * * * ``` * * @param string $text * * @return string */ public static function markdown($text) { if (!is_string($text)) { return $text; } $markdown = \Parsedown::instance(); return $markdown->parse($text); } /** * Returns a relative URL from the webroot if the given FQSEN exists in the project. * * Example usage inside template would be (where @link is an attribute called link): * * ``` * * ``` * * @param string $fqsen * * @return bool|string */ public static function path($fqsen) { $projectDescriptor = self::$descriptorBuilder->getProjectDescriptor(); $elementList = $projectDescriptor->getIndexes()->get('elements'); $node = $fqsen; if (isset($elementList[$fqsen])) { $node = $elementList[$fqsen]; } elseif (isset($elementList['~\\' . $fqsen])) { $node = $elementList['~\\' . $fqsen]; } $rule = self::$routers->match($node); if (! $rule) { return ''; } $generatedUrl = $rule->generate($node); return $generatedUrl ? ltrim($generatedUrl, '/') : false; } } registerTranslationMessages($app); $this->registerWriters($app); $this->registerDependenciesOnXsltExtension($app); $app->register(new \phpDocumentor\Plugin\Graphs\ServiceProvider()); $app->register(new \phpDocumentor\Plugin\Twig\ServiceProvider()); } /** * Creates all writers for this plugin and adds them to the WriterCollection object. * * This action will enable transformations in templates to make use of these writers. * * @param Application $app * * @return void */ private function registerWriters(Application $app) { $writerCollection = $this->getWriterCollection($app); $writerCollection['FileIo'] = new Writer\FileIo(); $writerCollection['checkstyle'] = new Writer\Checkstyle(); $writerCollection['sourcecode'] = new Writer\Sourcecode(); $writerCollection['statistics'] = new Writer\Statistics(); $writerCollection['xml'] = new Writer\Xml($app['transformer.routing.standard']); $writerCollection['xsl'] = new Writer\Xsl($app['monolog']); $writerCollection['checkstyle']->setTranslator($this->getTranslator($app)); $writerCollection['xml']->setTranslator($this->getTranslator($app)); } /** * Registers the Messages folder in this plugin as a source of translations. * * @param Application $app * * @return void */ private function registerTranslationMessages(Application $app) { $this->getTranslator($app)->addTranslationFolder(__DIR__ . DIRECTORY_SEPARATOR . 'Messages'); } /** * Registers the Routing Queue and Descriptor Builder objects on the XSLT Extension class. * * In every template we use PHP helpers in order to be able to have routing that is universal between templates and * convert Markdown text into HTML (for example). The only way for XSL to do this is by having global functions or * static methods in a class because you cannot inject an object into an XSL processor. * * With this method we make sure that all dependencies used by the static methods are injected as static properties. * * @param Application $app * * @return void */ private function registerDependenciesOnXsltExtension(Application $app) { Xslt\Extension::$routers = $app['transformer.routing.queue']; Xslt\Extension::$descriptorBuilder = $app['descriptor.builder']; } /** * Returns the Translator service from the Service Locator. * * @param Application $app * * @return Translator */ private function getTranslator(Application $app) { return $app['translator']; } /** * Returns the WriterCollection service from the Service Locator. * * @param Application $app * * @return Collection */ private function getWriterCollection(Application $app) { return $app['transformer.writer.collection']; } } 'No summary was found for this file', 'PPC:ERR-50001' => 'Only one @package tag is allowed', 'PPC:ERR-50002' => 'Only one @subpackage tag is allowed', 'PPC:ERR-50004' => 'Cannot have a @subpackage when a @package tag is not present', 'PPC:ERR-50005' => 'No summary for class %2$s', 'PPC:ERR-50006' => 'Found deprecated tag "%s" in %s', 'PPC:ERR-50007' => 'No summary for property %s', 'PPC:ERR-50008' => 'No summary for method %2$s', 'PPC:ERR-50009' => 'No summary for interface %2$s', 'PPC:ERR-50010' => 'No summary for trait %2$s', 'PPC:ERR-50011' => 'No summary for function %2$s', 'PPC:ERR-50013' => 'Parameter %s could not be found in %s', 'PPC:ERR-50014' => 'Name of argument %s does not match with the DocBlock\'s name %s in %s', 'PPC:ERR-50015' => 'Argument %s is missing from the Docblock of %s', 'PPC:ERR-50016' => 'The type hint of the argument is incorrect for the type definition ' . 'of the @param tag with argument %s in %s', 'PPC:ERR-50017' => 'The type for the %s tag in %s is "type"; isn\'t this an IDE default?', 'PPC:ERR-50018' => 'The type for the param tag %s in %s is either "type" or "unknown"; isn\'t this an IDE default?', 'PPC:ERR-50020' => 'Not found required tag "%s" in %s', 'VAL:ERRLVL-50000' => 'error', 'VAL:ERRLVL-50001' => 'error', 'VAL:ERRLVL-50002' => 'error', 'VAL:ERRLVL-50004' => 'warning', 'VAL:ERRLVL-50005' => 'error', 'VAL:ERRLVL-50006' => 'critical', 'VAL:ERRLVL-50007' => 'error', 'VAL:ERRLVL-50008' => 'error', 'VAL:ERRLVL-50009' => 'error', 'VAL:ERRLVL-50010' => 'error', 'VAL:ERRLVL-50011' => 'error', 'VAL:ERRLVL-50013' => 'notice', 'VAL:ERRLVL-50014' => 'error', 'VAL:ERRLVL-50015' => 'error', 'VAL:ERRLVL-50016' => 'error', 'VAL:ERRLVL-50017' => 'error', 'VAL:ERRLVL-50018' => 'error', 'VAL:ERRLVL-50020' => 'critical', ); 'Es wurde keine Zusammenfassung in dieser Datei gefunden', 'PPC:ERR-50001' => 'Es ist nur ein @package Tag erlaubt', 'PPC:ERR-50002' => 'Es ist nur ein @subpackage Tag erlaubt', 'PPC:ERR-50004' => 'Es kann kein @subpackage vorkommen, ohne Angabe eines @package Tags', 'PPC:ERR-50005' => 'Keine Zusammenfassung für Klasse %2$s', 'PPC:ERR-50006' => 'Veraltetes Tag "%s" in %s gefunden', 'PPC:ERR-50007' => 'Keine Zusammenfassung für Property %s', 'PPC:ERR-50008' => 'Keine Zusammenfassung für Methode %2$s', 'PPC:ERR-50009' => 'Keine Zusammenfassung für Interface %s', 'PPC:ERR-50010' => 'Keine Zusammenfassung für Trait %s', 'PPC:ERR-50011' => 'Keine Zusammenfassung für Funktion %$2s', 'PPC:ERR-50013' => 'Parameter %s konnte nicht in %s gefunden werden', 'PPC:ERR-50014' => 'Der Name des Arguments %s stimmt nicht mit dem Namen %s aus dem DocBlock in %s überein', 'PPC:ERR-50015' => 'Argument %s fehlt im Docblock von %s', 'PPC:ERR-50016' => 'Der Type-Hint von dem Argument ist für die Typ-Definition ' . 'des @param Tags mit dem Argument %s in %s nicht korrekt', 'PPC:ERR-50017' => 'Der Typ für das %s Tag in %s ist "type"; ist das nicht ein IDE default?', 'PPC:ERR-50018' => 'Der Typ für das param Tag %s in %s ist entweder "type" oder "unknown"; ist das nicht ein ' . 'IDE default?', 'PPC:ERR-50020' => 'Benötigtes Tag "%s" wurde nicht in %s gefunden', 'VAL:ERRLVL-50000' => 'error', 'VAL:ERRLVL-50001' => 'error', 'VAL:ERRLVL-50002' => 'error', 'VAL:ERRLVL-50004' => 'warning', 'VAL:ERRLVL-50005' => 'error', 'VAL:ERRLVL-50006' => 'critical', 'VAL:ERRLVL-50007' => 'error', 'VAL:ERRLVL-50008' => 'error', 'VAL:ERRLVL-50009' => 'error', 'VAL:ERRLVL-50010' => 'error', 'VAL:ERRLVL-50011' => 'error', 'VAL:ERRLVL-50013' => 'notice', 'VAL:ERRLVL-50014' => 'error', 'VAL:ERRLVL-50015' => 'error', 'VAL:ERRLVL-50016' => 'error', 'VAL:ERRLVL-50017' => 'error', 'VAL:ERRLVL-50018' => 'error', 'VAL:ERRLVL-50020' => 'critical', ); appendChild($child); $child->setAttribute('line', $argument->getLine()); $child->setAttribute('by_reference', var_export($argument->isByReference(), true)); $child->appendChild(new \DOMElement('name', $argument->getName())); $child->appendChild(new \DOMElement('default')) ->appendChild(new \DOMText($argument->getDefault())); $types = $argument->getTypes(); $typeStrings = array(); foreach ($types as $type) { $typeStrings[] = $type instanceof DescriptorAbstract ? $type->getFullyQualifiedStructuralElementName() : $type; } $child->appendChild(new \DOMElement('type', implode('|', $typeStrings))); return $child; } } docBlockConverter = $docBlockConverter; } /** * Export the given reflected constant definition to the provided parent element. * * @param \DOMElement $parent Element to augment. * @param ConstantDescriptor $constant Element to export. * * @return \DOMElement */ public function convert(\DOMElement $parent, ConstantDescriptor $constant) { $fullyQualifiedNamespaceName = $constant->getNamespace() instanceof NamespaceDescriptor ? $constant->getNamespace()->getFullyQualifiedStructuralElementName() : $parent->getAttribute('namespace'); $child = new \DOMElement('constant'); $parent->appendChild($child); $child->setAttribute('namespace', ltrim($fullyQualifiedNamespaceName, '\\')); $child->setAttribute('line', $constant->getLine()); $child->appendChild(new \DOMElement('name', $constant->getName())); $child->appendChild(new \DOMElement('full_name', $constant->getFullyQualifiedStructuralElementName())); $child->appendChild(new \DOMElement('value'))->appendChild(new \DOMText($constant->getValue())); $this->docBlockConverter->convert($child, $constant); return $child; } } getDescription($tag); $child = new \DOMElement('tag'); $parent->appendChild($child); $child->setAttribute('name', str_replace('&', '&', $tag->getName())); $child->setAttribute('line', $parent->getAttribute('line')); $child->setAttribute('description', str_replace('&', '&', $description)); $this->addTypes($tag, $child); // TODO: make the tests below configurable from the outside so that more could be added using plugins if (method_exists($tag, 'getVariableName')) { $child->setAttribute('variable', str_replace('&', '&', $tag->getVariableName())); } if (method_exists($tag, 'getReference')) { $child->setAttribute('link', str_replace('&', '&', $tag->getReference())); } if (method_exists($tag, 'getLink')) { $child->setAttribute('link', str_replace('&', '&', $tag->getLink())); } if (method_exists($tag, 'getMethodName')) { $child->setAttribute('method_name', str_replace('&', '&', $tag->getMethodName())); } return $child; } /** * Returns the description from the Tag with the version prepended when applicable. * * @param TagDescriptor $tag * * @todo the version should not be prepended here but in templates; remove this. * * @return string */ protected function getDescription(TagDescriptor $tag) { $description = ''; //@version, @deprecated, @since if (method_exists($tag, 'getVersion')) { $description .= $tag->getVersion() . ' '; } $description .= $tag->getDescription(); return trim($description); } /** * Adds type elements and a type attribute to the tag if a method 'getTypes' is present. * * @param TagDescriptor $tag * @param \DOMElement $child * * @return void */ protected function addTypes(TagDescriptor $tag, \DOMElement $child) { if (!method_exists($tag, 'getTypes')) { return; } $typeString = ''; foreach ($tag->getTypes() as $type) { $typeString .= $type . '|'; /** @var \DOMElement $typeNode */ $typeNode = $child->appendChild(new \DOMElement('type')); $typeNode->appendChild(new \DOMText($type)); } $child->setAttribute('type', str_replace('&', '&', rtrim($typeString, '|'))); } } argumentConverter = $argumentConverter; $this->docBlockConverter = $docBlockConverter; } /** * Export the given reflected method definition to the provided parent element. * * @param \DOMElement $parent Element to augment. * @param MethodDescriptor $method Element to export. * * @return \DOMElement */ public function convert(\DOMElement $parent, MethodDescriptor $method) { $fullyQualifiedNamespaceName = $method->getNamespace() instanceof NamespaceDescriptor ? $method->getNamespace()->getFullyQualifiedStructuralElementName() : $parent->getAttribute('namespace'); $child = new \DOMElement('method'); $parent->appendChild($child); $child->setAttribute('final', var_export($method->isFinal(), true)); $child->setAttribute('abstract', var_export($method->isAbstract(), true)); $child->setAttribute('static', var_export($method->isStatic(), true)); $child->setAttribute('visibility', $method->getVisibility()); $child->setAttribute('namespace', $fullyQualifiedNamespaceName); $child->setAttribute('line', $method->getLine()); $child->appendChild(new \DOMElement('name', $method->getName())); $child->appendChild(new \DOMElement('full_name', $method->getFullyQualifiedStructuralElementName())); $this->docBlockConverter->convert($child, $method); foreach ($method->getArguments() as $argument) { $this->argumentConverter->convert($child, $argument); } return $child; } } docBlockConverter = $docBlockConverter; $this->methodConverter = $methodConverter; $this->constantConverter = $constantConverter; } /** * Export the given reflected interface definition to the provided parent element. * * This method creates a new child element on the given parent XML element * and takes the properties of the Reflection argument and sets the * elements and attributes on the child. * * If a child DOMElement is provided then the properties and attributes are * set on this but the child element is not appended onto the parent. This * is the responsibility of the invoker. Essentially this means that the * $parent argument is ignored in this case. * * @param \DOMElement $parent Element to augment. * @param InterfaceDescriptor $interface Element to export. * * @return \DOMElement */ public function convert(\DOMElement $parent, InterfaceDescriptor $interface) { $child = new \DOMElement('interface'); $parent->appendChild($child); /** @var InterfaceDescriptor $parentInterface */ foreach ($interface->getParent() as $parentInterface) { $parentFqcn = is_string($parentInterface) === false ? $parentInterface->getFullyQualifiedStructuralElementName() : $parentInterface; $child->appendChild(new \DOMElement('extends', $parentFqcn)); } $namespace = $interface->getNamespace()->getFullyQualifiedStructuralElementName(); $child->setAttribute('namespace', ltrim($namespace, '\\')); $child->setAttribute('line', $interface->getLine()); $child->appendChild(new \DOMElement('name', $interface->getName())); $child->appendChild(new \DOMElement('full_name', $interface->getFullyQualifiedStructuralElementName())); $this->docBlockConverter->convert($child, $interface); foreach ($interface->getConstants() as $constant) { $this->constantConverter->convert($child, $constant); } foreach ($interface->getMethods() as $method) { $this->methodConverter->convert($child, $method); } return $child; } } docBlockConverter = $docBlockConverter; $this->methodConverter = $methodConverter; $this->propertyConverter = $propertyConverter; } /** * Export the given reflected Trait definition to the provided parent element. * * This method creates a new child element on the given parent XML element * and takes the properties of the Reflection argument and sets the * elements and attributes on the child. * * If a child DOMElement is provided then the properties and attributes are * set on this but the child element is not appended onto the parent. This * is the responsibility of the invoker. Essentially this means that the * $parent argument is ignored in this case. * * @param \DOMElement $parent Element to augment. * @param TraitDescriptor $trait Element to export. * * @return \DOMElement */ public function convert(\DOMElement $parent, TraitDescriptor $trait) { $child = new \DOMElement('trait'); $parent->appendChild($child); $namespace = $trait->getNamespace()->getFullyQualifiedStructuralElementName(); $child->setAttribute('namespace', ltrim($namespace, '\\')); $child->setAttribute('line', $trait->getLine()); $child->appendChild(new \DOMElement('name', $trait->getName())); $child->appendChild(new \DOMElement('full_name', $trait->getFullyQualifiedStructuralElementName())); $this->docBlockConverter->convert($child, $trait); foreach ($trait->getProperties() as $property) { $this->propertyConverter->convert($child, $property); } foreach ($trait->getMethods() as $method) { $this->methodConverter->convert($child, $method); } return $child; } } docBlockConverter = $docBlockConverter; } /** * Export the given reflected property definition to the provided parent element. * * @param \DOMElement $parent Element to augment. * @param PropertyDescriptor $property Element to export. * * @return \DOMElement */ public function convert(\DOMElement $parent, PropertyDescriptor $property) { $fullyQualifiedNamespaceName = $property->getNamespace() instanceof NamespaceDescriptor ? $property->getNamespace()->getFullyQualifiedStructuralElementName() : $parent->getAttribute('namespace'); $child = new \DOMElement('property'); $parent->appendChild($child); $child->setAttribute('static', var_export($property->isStatic(), true)); $child->setAttribute('visibility', $property->getVisibility()); $child->setAttribute('namespace', $fullyQualifiedNamespaceName); $child->setAttribute('line', $property->getLine()); $child->appendChild(new \DOMElement('name', '$' . $property->getName())); $child->appendChild(new \DOMElement('full_name', $property->getFullyQualifiedStructuralElementName())); $child->appendChild(new \DOMElement('default'))->appendChild(new \DOMText($property->getDefault())); $this->docBlockConverter->convert($child, $property); return $child; } } tagConverter = $tagConverter; $this->router = $router; } /** * Exports the given reflection object to the parent XML element. * * This method creates a new child element on the given parent XML element * and takes the properties of the Reflection argument and sets the * elements and attributes on the child. * * If a child DOMElement is provided then the properties and attributes are * set on this but the child element is not appended onto the parent. This * is the responsibility of the invoker. Essentially this means that the * $parent argument is ignored in this case. * * @param \DOMElement $parent The parent element to augment. * @param DescriptorAbstract $element The data source. * * @return \DOMElement */ public function convert(\DOMElement $parent, DescriptorAbstract $element) { $child = new \DOMElement('docblock'); $parent->appendChild($child); $child->setAttribute('line', $element->getLine()); $package = str_replace('&', '&', ltrim($element->getPackage(), '\\')); $parent->setAttribute('package', $package ?: 'global'); $this->addSummary($child, $element); $this->addDescription($child, $element); $this->addTags($child, $element); $this->addInheritedFromTag($child, $element); return $child; } /** * Adds the short description of $docblock to the given node as description * field. * * @param \DOMElement $node * @param DescriptorAbstract $element * * @return void */ protected function addSummary(\DOMElement $node, DescriptorAbstract $element) { $node->appendChild(new \DOMElement('description')) ->appendChild(new \DOMText($element->getSummary())); } /** * Adds the DocBlock's long description to the $child element, * * @param \DOMElement $node * @param DescriptorAbstract $element * * @return void */ protected function addDescription(\DOMElement $node, DescriptorAbstract $element) { $node->appendChild(new \DOMElement('long-description')) ->appendChild(new \DOMText($element->getDescription())); } /** * Adds each tag to the XML Node representing the DocBlock. * * The Descriptor contains an array of tag groups (that are tags grouped by their name), which in itself contains * an array of the individual tags. * * @param \DOMElement $docBlock * @param DescriptorAbstract $descriptor * * @return void */ protected function addTags(\DOMElement $docBlock, $descriptor) { foreach ($descriptor->getTags() as $tagGroup) { if (! $tagGroup) { continue; } foreach ($tagGroup as $tag) { $this->tagConverter->convert($docBlock, $tag); } } } /** * Adds the 'inherited_from' tag when a Descriptor inherits from another Descriptor. * * @param \DOMElement $docBlock * @param DescriptorAbstract $descriptor * * @return void */ protected function addInheritedFromTag(\DOMElement $docBlock, $descriptor) { $parentElement = $descriptor->getInheritedElement(); if (! $parentElement instanceof $descriptor) { return; } $child = new \DOMElement('tag'); $docBlock->appendChild($child); $rule = $this->router->match($parentElement); $child->setAttribute('name', 'inherited_from'); $child->setAttribute('description', $parentElement->getFullyQualifiedStructuralElementName()); $child->setAttribute('refers', $parentElement->getFullyQualifiedStructuralElementName()); $child->setAttribute('link', $rule ? $rule->generate($parentElement) : ''); } } walkObjectTree($object, $query); if (!is_array($node) && (!$node instanceof \Traversable)) { $node = array($node); } return $node; } return array($object); } /** * Walks an object graph and/or array using a twig query string. * * @param \Traversable|mixed $objectOrArray * @param string $query A path to walk separated by dots, i.e. `namespace.namespaces`. * * @return mixed */ private function walkObjectTree($objectOrArray, $query) { $node = $objectOrArray; $objectPath = explode('.', $query); // walk through the tree foreach ($objectPath as $pathNode) { if (is_array($node)) { if (isset($node[$pathNode])) { $node = $node[$pathNode]; continue; } } elseif (is_object($node)) { if (isset($node->$pathNode) || (method_exists($node, '__get') && $node->$pathNode)) { $node = $node->$pathNode; continue; } elseif (method_exists($node, $pathNode)) { $node = $node->$pathNode(); continue; } elseif (method_exists($node, 'get' . $pathNode)) { $pathNode = 'get' . $pathNode; $node = $node->$pathNode(); continue; } elseif (method_exists($node, 'is' . $pathNode)) { $pathNode = 'is' . $pathNode; $node = $node->$pathNode(); continue; } } return null; } return $node; } } * * * * 100 * 377 * 2 * * * * ``` * * @author Siad Ardroumli */ class Statistics extends Checkstyle { /** * This method generates the checkstyle.xml report * * @param ProjectDescriptor $project Document containing the structure. * @param Transformation $transformation Transformation to execute. * * @return void */ public function transform(ProjectDescriptor $project, Transformation $transformation) { $artifact = $this->getDestinationPath($transformation); $now = new \DateTime('now'); $date = $now->format(DATE_ATOM); $document = new \DOMDocument(); $document->formatOutput = true; $document->preserveWhiteSpace = false; if (is_file($artifact)) { $document->load($artifact); } else { $document = $this->appendPhpdocStatsElement($document); } $document = $this->appendStatElement($document, $project, $date); $this->saveCheckstyleReport($artifact, $document); } /** * Append phpdoc-stats element to the document. * * @param \DOMDocument $document * * @return \DOMDocument */ protected function appendPhpdocStatsElement(\DOMDocument $document) { $stats = $document->createElement('phpdoc-stats'); $stats->setAttribute('version', Application::$VERSION); $document->appendChild($stats); return $document; } /** * Appends a stat fragment. * * @param \DOMDocument $document * @param ProjectDescriptor $project * @param string $date * * @return \DOMDocument */ protected function appendStatElement(\DOMDocument $document, ProjectDescriptor $project, $date) { $stat = $document->createDocumentFragment(); $stat->appendXML( << {$this->getFilesCounter($project)} {$this->getDeprecatedCounter($project)} {$this->getErrorCounter($project)} {$this->getMarkerCounter($project)} STAT ); $document->documentElement->appendChild($stat); return $document; } /** * Get number of files. * * @param ProjectDescriptor $project * * @return int */ protected function getFilesCounter(ProjectDescriptor $project) { return $project->getFiles()->count(); } /** * Get number of deprecated elements. * * @param ProjectDescriptor $project * * @return int */ protected function getDeprecatedCounter(ProjectDescriptor $project) { $deprecatedCounter = 0; /** @var DescriptorAbstract $element */ foreach ($project->getIndexes()->get('elements') as $element) { if ($element->isDeprecated()) { $deprecatedCounter += 1; } } return $deprecatedCounter; } /** * Get number of errors. * * @param ProjectDescriptor $project * * @return int */ protected function getErrorCounter(ProjectDescriptor $project) { $errorCounter = 0; /* @var FileDescriptor $fileDescriptor */ foreach ($project->getFiles()->getAll() as $fileDescriptor) { $errorCounter += count($fileDescriptor->getAllErrors()->getAll()); } return $errorCounter; } /** * Get number of markers. * * @param ProjectDescriptor $project * * @return int */ protected function getMarkerCounter(ProjectDescriptor $project) { $markerCounter = 0; /* @var $fileDescriptor FileDescriptor */ foreach ($project->getFiles()->getAll() as $fileDescriptor) { $markerCounter += $fileDescriptor->getMarkers()->count(); } return $markerCounter; } } translator; } /** * Sets a new object capable of translating strings on this writer. * * @param Translator $translator * * @return void */ public function setTranslator(Translator $translator) { $this->translator = $translator; } /** * This method generates the checkstyle.xml report * * @param ProjectDescriptor $project Document containing the structure. * @param Transformation $transformation Transformation to execute. * * @return void */ public function transform(ProjectDescriptor $project, Transformation $transformation) { $artifact = $this->getDestinationPath($transformation); $this->checkForSpacesInPath($artifact); $document = new \DOMDocument(); $document->formatOutput = true; $report = $document->createElement('checkstyle'); $report->setAttribute('version', '1.3.0'); $document->appendChild($report); /** @var FileDescriptor $fileDescriptor */ foreach ($project->getFiles()->getAll() as $fileDescriptor) { $file = $document->createElement('file'); $file->setAttribute('name', $fileDescriptor->getPath()); $report->appendChild($file); /** @var Error $error */ foreach ($fileDescriptor->getAllErrors()->getAll() as $error) { $item = $document->createElement('error'); $item->setAttribute('line', $error->getLine()); $item->setAttribute('severity', $error->getSeverity()); $item->setAttribute( 'message', vsprintf($this->getTranslator()->translate($error->getCode()), $error->getContext()) ); $item->setAttribute('source', 'phpDocumentor.file.'.$error->getCode()); $file->appendChild($item); } } $this->saveCheckstyleReport($artifact, $document); } /** * Retrieves the destination location for this artifact. * * @param \phpDocumentor\Transformer\Transformation $transformation * * @return string */ protected function getDestinationPath(Transformation $transformation) { $artifact = $transformation->getTransformer()->getTarget() . DIRECTORY_SEPARATOR . $transformation->getArtifact(); return $artifact; } /** * Save the checkstyle report to the artifact * * @param string $artifact Target name for the report * @param \DOMDocument $document The actual xml document being saved * * @return void */ protected function saveCheckstyleReport($artifact, \DOMDocument $document) { file_put_contents($artifact, $document->saveXML()); } } getTransformer()->getTarget() . DIRECTORY_SEPARATOR . $transformation->getArtifact(); $transformation->setArtifact($artifact); $method = 'executeQuery' . ucfirst($transformation->getQuery()); if (!method_exists($this, $method)) { throw new \InvalidArgumentException( 'The query ' . $method . ' is not supported by the FileIo writer, supported operation is "copy"' ); } $this->$method($transformation); } /** * Copies files or folders to the Artifact location. * * @param Transformation $transformation Transformation to use as data source. * * @throws Exception * * @return void */ public function executeQueryCopy(Transformation $transformation) { $path = $transformation->getSourceAsPath(); if (!is_readable($path)) { throw new Exception('Unable to read the source file: ' . $path); } if (!is_writable($transformation->getTransformer()->getTarget())) { throw new Exception('Unable to write to: ' . dirname($transformation->getArtifact())); } $filesystem = new Filesystem(); if (is_file($path)) { $filesystem->copy($path, $transformation->getArtifact(), true); } else { $filesystem->mirror($path, $transformation->getArtifact(), null, array('override' => true)); } } } logger = $logger; } /** * Checks whether XSL handling is enabled with PHP as that is not enabled by default. * * To enable XSL handling you need either the xsl extension or the xslcache extension installed. * * @throws RequirementMissing if neither xsl extensions are installed. * * @return void */ public function checkRequirements() { if (!class_exists('XSLTProcessor') && (!extension_loaded('xslcache'))) { throw new RequirementMissing( 'The XSL writer was unable to find your XSLTProcessor; ' . 'please check if you have installed the PHP XSL extension or XSLCache extension' ); } } /** * Sets the routers that can be used to determine the path of links. * * @param Queue $routers * * @return void */ public function setRouters(Queue $routers) { $this->routers = $routers; } /** * This method combines the structure.xml and the given target template * and creates a static html page at the artifact location. * * @param ProjectDescriptor $project Document containing the structure. * @param Transformation $transformation Transformation to execute. * * @throws \RuntimeException if the structure.xml file could not be found. * @throws Exception if the structure.xml file's documentRoot could not be read because of encoding issues * or because it was absent. * * @return void */ public function transform(ProjectDescriptor $project, Transformation $transformation) { $structure = $this->loadAst($this->getAstPath($transformation)); $proc = $this->getXslProcessor($transformation); $proc->registerPHPFunctions(); $this->registerDefaultVariables($transformation, $proc, $structure); $this->setProcessorParameters($transformation, $proc); $artifact = $this->getArtifactPath($transformation); $this->checkForSpacesInPath($artifact); // if a query is given, then apply a transformation to the artifact // location by replacing ($} with the sluggified node-value of the // search result if ($transformation->getQuery() !== '') { $xpath = new \DOMXPath($structure); /** @var \DOMNodeList $qry */ $qry = $xpath->query($transformation->getQuery()); $count = $qry->length; foreach ($qry as $key => $element) { Dispatcher::getInstance()->dispatch( 'transformer.writer.xsl.pre', PreXslWriterEvent::createInstance($this)->setElement($element)->setProgress(array($key+1, $count)) ); $proc->setParameter('', $element->nodeName, $element->nodeValue); $file_name = $transformation->getTransformer()->generateFilename( $element->nodeValue ); if (! $artifact) { $url = $this->generateUrlForXmlElement($project, $element); if ($url === false || $url[0] !== DIRECTORY_SEPARATOR) { continue; } $filename = $transformation->getTransformer()->getTarget() . str_replace('/', DIRECTORY_SEPARATOR, $url); } else { $filename = str_replace('{$' . $element->nodeName . '}', $file_name, $artifact); } $relativeFileName = substr($filename, strlen($transformation->getTransformer()->getTarget()) + 1); $proc->setParameter('', 'root', str_repeat('../', substr_count($relativeFileName, '/'))); $this->writeToFile($filename, $proc, $structure); } } else { if (substr($transformation->getArtifact(), 0, 1) == '$') { // not a file, it must become a variable! $variable_name = substr($transformation->getArtifact(), 1); $this->xsl_variables[$variable_name] = $proc->transformToXml($structure); } else { $relativeFileName = substr($artifact, strlen($transformation->getTransformer()->getTarget()) + 1); $proc->setParameter('', 'root', str_repeat('../', substr_count($relativeFileName, '/'))); $this->writeToFile($artifact, $proc, $structure); } } } /** * Takes the filename and converts it into a correct URI for XSLTProcessor. * * @param string $filename * * @return string */ protected function getXsltUriFromFilename($filename) { // Windows requires an additional / after the scheme. If not provided then errno 22 (I/O Error: Invalid // Argument) will be raised. Thanks to @FnTmLV for finding the cause. See issue #284 for more information. // An exception to the above is when running from a Phar file; in this case the stream is handled as if on // linux; see issue #713 for more information on this exception. if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && ! \Phar::running()) { $filename = '/' . $filename; } return 'file://' . $filename; } /** * Sets the parameters of the XSLT processor. * * @param TransformationObject $transformation Transformation. * @param \XSLTProcessor $proc XSLTProcessor. * * @return void */ public function setProcessorParameters(TransformationObject $transformation, $proc) { foreach ($this->xsl_variables as $key => $variable) { // XSL does not allow both single and double quotes in a string if ((strpos($variable, '"') !== false) && ((strpos($variable, "'") !== false)) ) { $this->logger->warning( 'XSLT does not allow both double and single quotes in ' . 'a variable; transforming single quotes to a character ' . 'encoded version in variable: ' . $key ); $variable = str_replace("'", "'", $variable); } $proc->setParameter('', $key, $variable); } // add / overwrite the parameters with those defined in the // transformation entry $parameters = $transformation->getParameters(); if (isset($parameters['variables'])) { /** @var \DOMElement $variable */ foreach ($parameters['variables'] as $key => $value) { $proc->setParameter('', $key, $value); } } } /** * * * @param Transformation $transformation * * @return \XSLTCache|\XSLTProcessor */ protected function getXslProcessor(Transformation $transformation) { $xslTemplatePath = $transformation->getSourceAsPath(); $this->logger->debug('Loading XSL template: ' . $xslTemplatePath); if (!file_exists($xslTemplatePath)) { throw new Exception('Unable to find XSL template "' . $xslTemplatePath . '"'); } if (extension_loaded('xslcache')) { $proc = new \XSLTCache(); $proc->importStyleSheet($xslTemplatePath, true); return $proc; } else { $xsl = new \DOMDocument(); $xsl->load($xslTemplatePath); $proc = new \XSLTProcessor(); $proc->importStyleSheet($xsl); return $proc; } } /** * @param $structureFilename * @return \DOMDocument */ private function loadAst($structureFilename) { if (!is_readable($structureFilename)) { throw new \RuntimeException( 'Structure.xml file was not found in the target directory, is the XML writer missing from the ' . 'template definition?' ); } $structure = new \DOMDocument('1.0', 'utf-8'); libxml_use_internal_errors(true); $structure->load($structureFilename); if (empty($structure->documentElement)) { $message = 'Specified DOMDocument lacks documentElement, cannot transform.'; $error = libxml_get_last_error(); if ($error) { $message .= PHP_EOL . 'Apparently an error occurred with reading the structure.xml file, the reported ' . 'error was "' . trim($error->message) . '" on line ' . $error->line; } throw new Exception($message); } return $structure; } /** * @param Transformation $transformation * @param $proc * @param $structure */ private function registerDefaultVariables(Transformation $transformation, $proc, $structure) { $proc->setParameter('', 'title', $structure->documentElement->getAttribute('title')); if ($transformation->getParameter('search') !== null && $transformation->getParameter('search')->getValue()) { $proc->setParameter('', 'search_template', $transformation->getParameter('search')->getValue()); } else { $proc->setParameter('', 'search_template', 'none'); } $proc->setParameter('', 'version', Application::$VERSION); $proc->setParameter('', 'generated_datetime', date('r')); } /** * @param $filename * @param $proc * @param $structure */ private function writeToFile($filename, $proc, $structure) { if (!file_exists(dirname($filename))) { mkdir(dirname($filename), 0755, true); } $proc->transformToURI($structure, $this->getXsltUriFromFilename($filename)); } /** * @param Transformation $transformation * @return string */ private function getAstPath(Transformation $transformation) { return $transformation->getTransformer()->getTarget() . DIRECTORY_SEPARATOR . 'structure.xml'; } /** * Returns the path to the location where the artifact should be written, or null to automatically detect the * location using the router. * * @param Transformation $transformation * * @return string|null */ private function getArtifactPath(Transformation $transformation) { return $transformation->getArtifact() ? $transformation->getTransformer()->getTarget() . DIRECTORY_SEPARATOR . $transformation->getArtifact() : null; } /** * @param ProjectDescriptor $project * @param $element * @return false|string */ private function generateUrlForXmlElement(ProjectDescriptor $project, $element) { $elements = $project->getIndexes()->get('elements'); $elementFqcn = ($element->parentNode->nodeName === 'namespace' ? '~\\' : '') . $element->nodeValue; $node = (isset($elements[$elementFqcn])) ? $elements[$elementFqcn] : $element->nodeValue; // do not use the normalized version if the element is not found! $rule = $this->routers->match($node); if (!$rule) { throw new \InvalidArgumentException( 'No matching routing rule could be found for the given node, please provide an artifact location, ' . 'encountered: ' . ($node === null ? 'NULL' : get_class($node)) ); } $rule = new ForFileProxy($rule); $url = $rule->generate($node); return $url; } } docBlockConverter = new DocBlockConverter(new TagConverter(), $router); $this->argumentConverter = new ArgumentConverter(); $this->methodConverter = new MethodConverter($this->argumentConverter, $this->docBlockConverter); $this->propertyConverter = new PropertyConverter($this->docBlockConverter); $this->constantConverter = new ConstantConverter($this->docBlockConverter); $this->interfaceConverter = new InterfaceConverter( $this->docBlockConverter, $this->methodConverter, $this->constantConverter ); $this->traitConverter = new TraitConverter( $this->docBlockConverter, $this->methodConverter, $this->propertyConverter ); } /** * Returns an instance of the object responsible for translating content. * * @return Translator */ public function getTranslator() { return $this->translator; } /** * Sets a new object capable of translating strings on this writer. * * @param Translator $translator * * @return void */ public function setTranslator(Translator $translator) { $this->translator = $translator; } /** * This method generates the AST output * * @param ProjectDescriptor $project Document containing the structure. * @param Transformation $transformation Transformation to execute. * * @return void */ public function transform(ProjectDescriptor $project, Transformation $transformation) { $artifact = $this->getDestinationPath($transformation); $this->checkForSpacesInPath($artifact); $this->xml = new \DOMDocument('1.0', 'utf-8'); $this->xml->formatOutput = true; $document_element = new \DOMElement('project'); $this->xml->appendChild($document_element); $document_element->setAttribute('title', $project->getName()); $document_element->setAttribute('version', Application::$VERSION); $this->buildPartials($document_element, $project); $transformer = $transformation->getTransformer(); foreach ($project->getFiles() as $file) { $this->buildFile($document_element, $file, $transformer); } $this->finalize($project); file_put_contents($artifact, $this->xml->saveXML()); } protected function buildPartials(\DOMElement $parent, ProjectDescriptor $project) { $child = new \DOMElement('partials'); $parent->appendChild($child); foreach ($project->getPartials() as $name => $element) { $partial = new \DOMElement('partial'); $child->appendChild($partial); $partial->setAttribute('name', $name); $partial->appendChild(new \DOMText($element)); } } protected function buildFile(\DOMElement $parent, FileDescriptor $file, Transformer $transformer) { $child = new \DOMElement('file'); $parent->appendChild($child); $path = ltrim($file->getPath(), './'); $child->setAttribute('path', $path); $child->setAttribute( 'generated-path', $transformer->generateFilename($path) ); $child->setAttribute('hash', $file->getHash()); $this->docBlockConverter->convert($child, $file); // add namespace aliases foreach ($file->getNamespaceAliases() as $alias => $namespace) { $alias_obj = new \DOMElement('namespace-alias', $namespace); $child->appendChild($alias_obj); $alias_obj->setAttribute('name', $alias); } /** @var ConstantDescriptor $constant */ foreach ($file->getConstants() as $constant) { $this->constantConverter->convert($child, $constant); } /** @var FunctionDescriptor $function */ foreach ($file->getFunctions() as $function) { $this->buildFunction($child, $function); } /** @var InterfaceDescriptor $interface */ foreach ($file->getInterfaces() as $interface) { $this->interfaceConverter->convert($child, $interface); } /** @var ClassDescriptor $class */ foreach ($file->getClasses() as $class) { $this->buildClass($child, $class); } /** @var TraitDescriptor $class */ foreach ($file->getTraits() as $trait) { $this->traitConverter->convert($child, $trait); } // add markers if (count($file->getMarkers()) > 0) { $markers = new \DOMElement('markers'); $child->appendChild($markers); foreach ($file->getMarkers() as $marker) { if (! $marker['type']) { continue; } $marker_obj = new \DOMElement(strtolower($marker['type'])); $markers->appendChild($marker_obj); $marker_obj->appendChild(new \DOMText(trim($marker['message']))); $marker_obj->setAttribute('line', $marker['line']); } } $errors = $file->getAllErrors(); if (count($errors) > 0) { $parse_errors = new \DOMElement('parse_markers'); $child->appendChild($parse_errors); /** @var Error $error */ foreach ($errors as $error) { $this->createErrorEntry($error, $parse_errors); } } // if we want to include the source for each file; append a new // element 'source' which contains a compressed, encoded version // of the source if ($file->getSource()) { $child->appendChild(new \DOMElement('source', base64_encode(gzcompress($file->getSource())))); } } /** * Creates an entry in the ParseErrors collection of a file for a given error. * * @param Error $error * @param \DOMElement $parse_errors * * @return void */ protected function createErrorEntry($error, $parse_errors) { $marker_obj = new \DOMElement(strtolower($error->getSeverity())); $parse_errors->appendChild($marker_obj); $message = ($this->getTranslator()) ? vsprintf($this->getTranslator()->translate($error->getCode()), $error->getContext()) : $error->getCode(); $marker_obj->appendChild(new \DOMText($message)); $marker_obj->setAttribute('line', $error->getLine()); $marker_obj->setAttribute('code', $error->getCode()); } /** * Retrieves the destination location for this artifact. * * @param Transformation $transformation * * @return string */ protected function getDestinationPath(Transformation $transformation) { return $transformation->getTransformer()->getTarget() . DIRECTORY_SEPARATOR . $transformation->getArtifact(); } /** * Export this function definition to the given parent DOMElement. * * @param \DOMElement $parent Element to augment. * @param FunctionDescriptor $function Element to export. * @param \DOMElement $child if supplied this element will be augmented instead of freshly added. * * @return void */ public function buildFunction(\DOMElement $parent, FunctionDescriptor $function, \DOMElement $child = null) { if (!$child) { $child = new \DOMElement('function'); $parent->appendChild($child); } $namespace = $function->getNamespace() ? $function->getNamespace() : $parent->getAttribute('namespace'); $child->setAttribute('namespace', ltrim($namespace, '\\')); $child->setAttribute('line', $function->getLine()); $child->appendChild(new \DOMElement('name', $function->getName())); $child->appendChild(new \DOMElement('full_name', $function->getFullyQualifiedStructuralElementName())); $this->docBlockConverter->convert($child, $function); foreach ($function->getArguments() as $argument) { $this->argumentConverter->convert($child, $argument); } } /** * Exports the given reflection object to the parent XML element. * * This method creates a new child element on the given parent XML element * and takes the properties of the Reflection argument and sets the * elements and attributes on the child. * * If a child DOMElement is provided then the properties and attributes are * set on this but the child element is not appended onto the parent. This * is the responsibility of the invoker. Essentially this means that the * $parent argument is ignored in this case. * * @param \DOMElement $parent The parent element to augment. * @param ClassDescriptor $class The data source. * @param \DOMElement $child Optional: child element to use instead of creating a * new one on the $parent. * * @return void */ public function buildClass(\DOMElement $parent, ClassDescriptor $class, \DOMElement $child = null) { if (!$child) { $child = new \DOMElement('class'); $parent->appendChild($child); } $child->setAttribute('final', $class->isFinal() ? 'true' : 'false'); $child->setAttribute('abstract', $class->isAbstract() ? 'true' : 'false'); $parentFqcn = is_string($class->getParent()) ? $class->getParent() : $class->getParent()->getFullyQualifiedStructuralElementName(); $child->appendChild(new \DOMElement('extends', $parentFqcn)); /** @var InterfaceDescriptor $interface */ foreach ($class->getInterfaces() as $interface) { $interfaceFqcn = is_string($interface) ? $interface : $interface->getFullyQualifiedStructuralElementName(); $child->appendChild(new \DOMElement('implements', $interfaceFqcn)); } if ($child === null) { $child = new \DOMElement('interface'); $parent->appendChild($child); } $namespace = $class->getNamespace()->getFullyQualifiedStructuralElementName(); $child->setAttribute('namespace', ltrim($namespace, '\\')); $child->setAttribute('line', $class->getLine()); $child->appendChild(new \DOMElement('name', $class->getName())); $child->appendChild(new \DOMElement('full_name', $class->getFullyQualifiedStructuralElementName())); $this->docBlockConverter->convert($child, $class); foreach ($class->getConstants() as $constant) { // TODO #840: Workaround; for some reason there are NULLs in the constants array. if ($constant) { $this->constantConverter->convert($child, $constant); } } foreach ($class->getInheritedConstants() as $constant) { // TODO #840: Workaround; for some reason there are NULLs in the constants array. if ($constant) { $this->constantConverter->convert($child, $constant); } } foreach ($class->getProperties() as $property) { // TODO #840: Workaround; for some reason there are NULLs in the properties array. if ($property) { $this->propertyConverter->convert($child, $property); } } foreach ($class->getInheritedProperties() as $property) { // TODO #840: Workaround; for some reason there are NULLs in the properties array. if ($property) { $this->propertyConverter->convert($child, $property); } } foreach ($class->getMethods() as $method) { // TODO #840: Workaround; for some reason there are NULLs in the methods array. if ($method) { $this->methodConverter->convert($child, $method); } } foreach ($class->getInheritedMethods() as $method) { // TODO #840: Workaround; for some reason there are NULLs in the methods array. if ($method) { $methodElement = $this->methodConverter->convert($child, $method); $methodElement->appendChild( new \DOMElement( 'inherited_from', $method->getParent()->getFullyQualifiedStructuralElementName() ) ); } } } /** * Finalizes the processing and executing all post-processing actions. * * This method is responsible for extracting and manipulating the data that * is global to the project, such as: * * - Package tree * - Namespace tree * - Marker list * - Deprecated elements listing * - Removal of objects related to visibility * * @param ProjectDescriptor $projectDescriptor * * @return void */ protected function finalize(ProjectDescriptor $projectDescriptor) { // TODO: move all these behaviours to a central location for all template parsers $behaviour = new AuthorTag(); $behaviour->process($this->xml); $behaviour = new CoversTag(); $behaviour->process($this->xml); $behaviour = new IgnoreTag(); $behaviour->process($this->xml); $behaviour = new InternalTag( $projectDescriptor->isVisibilityAllowed(ProjectDescriptor\Settings::VISIBILITY_INTERNAL) ); $behaviour->process($this->xml); $behaviour = new LicenseTag(); $behaviour->process($this->xml); $behaviour = new MethodTag(); $behaviour->process($this->xml); $behaviour = new ParamTag(); $behaviour->process($this->xml); $behaviour = new PropertyTag(); $behaviour->process($this->xml); $behaviour = new ReturnTag(); $behaviour->process($this->xml); $behaviour = new UsesTag(); $behaviour->process($this->xml); $behaviour = new VarTag(); $behaviour->process($this->xml); $this->buildPackageTree($this->xml); $this->buildNamespaceTree($this->xml); $this->buildDeprecationList($this->xml); } /** * Collects all packages and subpackages, and adds a new section in the * DOM to provide an overview. * * @param \DOMDocument $dom Packages are extracted and a summary inserted * in this object. * * @return void */ protected function buildPackageTree(\DOMDocument $dom) { $xpath = new \DOMXPath($dom); $packages = array('global' => true); $qry = $xpath->query('//@package'); for ($i = 0; $i < $qry->length; $i++) { if (isset($packages[$qry->item($i)->nodeValue])) { continue; } $packages[$qry->item($i)->nodeValue] = true; } $packages = $this->generateNamespaceTree(array_keys($packages)); $this->generateNamespaceElements($packages, $dom->documentElement, 'package'); } /** * Collects all namespaces and sub-namespaces, and adds a new section in * the DOM to provide an overview. * * @param \DOMDocument $dom Namespaces are extracted and a summary inserted * in this object. * * @return void */ protected function buildNamespaceTree(\DOMDocument $dom) { $xpath = new \DOMXPath($dom); $namespaces = array(); $qry = $xpath->query('//@namespace'); for ($i = 0; $i < $qry->length; $i++) { if (isset($namespaces[$qry->item($i)->nodeValue])) { continue; } $namespaces[$qry->item($i)->nodeValue] = true; } $namespaces = $this->generateNamespaceTree(array_keys($namespaces)); $this->generateNamespaceElements($namespaces, $dom->documentElement); } /** * Adds a node to the xml for deprecations and the count value * * @param \DOMDocument $dom Markers are extracted and a summary inserted in this object. * * @return void */ protected function buildDeprecationList(\DOMDocument $dom) { $nodes = $this->getNodeListForTagBasedQuery($dom, 'deprecated'); $node = new \DOMElement('deprecated'); $dom->documentElement->appendChild($node); $node->setAttribute('count', $nodes->length); } /** * Build a tag based query string and return result * * @param \DOMDocument $dom Markers are extracted and a summary inserted * in this object. * @param string $marker The marker we're searching for throughout xml * * @return \DOMNodeList */ protected function getNodeListForTagBasedQuery($dom, $marker) { $xpath = new \DOMXPath($dom); $query = '/project/file/markers/'.$marker.'|'; $query .= '/project/file/docblock/tag[@name="'.$marker.'"]|'; $query .= '/project/file/class/docblock/tag[@name="'.$marker.'"]|'; $query .= '/project/file/class/*/docblock/tag[@name="'.$marker.'"]|'; $query .= '/project/file/interface/docblock/tag[@name="'.$marker.'"]|'; $query .= '/project/file/interface/*/docblock/tag[@name="'.$marker.'"]|'; $query .= '/project/file/function/docblock/tag[@name="'.$marker.'"]|'; $query .= '/project/file/constant/docblock/tag[@name="'.$marker.'"]'; $nodes = $xpath->query($query); return $nodes; } /** * Generates a hierarchical array of namespaces with their singular name * from a single level list of namespaces with their full name. * * @param array $namespaces the list of namespaces as retrieved from the xml. * * @return array */ protected function generateNamespaceTree($namespaces) { sort($namespaces); $result = array(); foreach ($namespaces as $namespace) { if (!$namespace) { $namespace = 'global'; } $namespace_list = explode('\\', $namespace); $node = &$result; foreach ($namespace_list as $singular) { if (!isset($node[$singular])) { $node[$singular] = array(); } $node = &$node[$singular]; } } return $result; } /** * Recursive method to create a hierarchical set of nodes in the dom. * * @param array[] $namespaces the list of namespaces to process. * @param \DOMElement $parent_element the node to receive the children of * the above list. * @param string $node_name the name of the summary element. * * @return void */ protected function generateNamespaceElements($namespaces, $parent_element, $node_name = 'namespace') { foreach ($namespaces as $name => $sub_namespaces) { $node = new \DOMElement($node_name); $parent_element->appendChild($node); $node->setAttribute('name', $name); $fullName = $parent_element->nodeName == $node_name ? $parent_element->getAttribute('full_name') . '\\' . $name : $name; $node->setAttribute('full_name', $fullName); $this->generateNamespaceElements($sub_namespaces, $node, $node_name); } } } getTransformer()->getTarget() . DIRECTORY_SEPARATOR . ($transformation->getArtifact() ? $transformation->getArtifact() : 'source'); /** @var FileDescriptor $file */ foreach ($project->getFiles() as $file) { $filename = $file->getPath(); $source = $file->getSource(); $root = str_repeat('../', count(explode(DIRECTORY_SEPARATOR, $filename))); $path = $artifact . DIRECTORY_SEPARATOR . $filename; if (!file_exists(dirname($path))) { mkdir(dirname($path), 0755, true); } $source = htmlentities($source); file_put_contents( $path.'.html', <<
$source
HTML ); } } } 'http://opensource.org/licenses/GPL-2.0', '#^\s*(GPL|GNU General Public License)((\s?v?|version)?3?)\s*$#i' => 'http://opensource.org/licenses/GPL-3.0', '#^\s*(LGPL|GNU (Lesser|Library) (General Public License|GPL))' .'((\s?v?|version)?2(\.1)?)\s*$#i' => 'http://opensource.org/licenses/LGPL-2.1', '#^\s*(LGPL|GNU (Lesser|Library) (General Public License|GPL))' .'((\s?v?|version)?3?)\s*$#i' => 'http://opensource.org/licenses/LGPL-3.0', '#^\s*((new |revised |modified |three-clause |3-clause )BSD' .'( License)?)\s*$#i' => 'http://opensource.org/licenses/BSD-3-Clause', '#^\s*((simplified |two-clause |2-clause |Free)BSD)( License)?\s*$#i' => 'http://opensource.org/licenses/BSD-2-Clause', '#^\s*MIT( License)?\s*$#i' => 'http://opensource.org/licenses/MIT', ); $xpath = new \DOMXPath($xml); $nodes = $xpath->query('//tag[@name="license"]/@description'); /** @var \DOMElement $node */ foreach ($nodes as $node) { $license = $node->nodeValue; // FIXME: migrate to '#^' . PHPDOC::LINK_REGEX . '(\s+(?P.+)) // ?$#u' once that const exists if (preg_match( '#^(?i)\b(?P(?:https?://|www\d{0,3}\.|[a-z0-9.\-]+\.' .'[a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+' .'(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|' .'[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))(\s+(?P.+))?$#u', $license, $matches )) { if (!isset($matches['text']) || !$matches['text']) { // set text to URL if not present $matches['text'] = $matches['url']; } $node->parentNode->setAttribute('link', $matches['url']); $node->nodeValue = $matches['text']; // bail out early continue; } // check map if any license matches foreach ($licenseMap as $regex => $url) { if (preg_match($regex, $license, $matches)) { $node->parentNode->setAttribute('link', $url); // we're done here break; } } } return $xml; } } tag to be consistent. * * @param \DOMDocument $xml Structure source to apply behaviour onto. * * @return \DOMDocument */ public function process(\DOMDocument $xml) { $qry = '//tag[@name=\''.$this->element_name.'\']/@description[. != ""]'; $xpath = new \DOMXPath($xml); $nodes = $xpath->query($qry); /** @var \DOMElement $node */ foreach ($nodes as $node) { // only transform using markdown if the text contains characters // other than word characters, whitespaces and punctuation characters. // This is because Markdown is a huge performance hit on the system if (!preg_match('/^[\w|\s|\.|,|;|\:|\&|\#]+$/', $node->nodeValue)) { $md = \Parsedown::instance(); $node->nodeValue = $md->parse($node->nodeValue); } else { // markdown will always surround the element with a paragraph; // we do the same here to make it consistent $node->nodeValue = '<p>' . $node->nodeValue . '</p>'; } } return $xml; } } query( '/project/file/class/docblock/tag[@name="property"]' .'|/project/file/class/docblock/tag[@name="property-read"]' .'|/project/file/class/docblock/tag[@name="property-write"]' ); /** @var \DOMElement $node */ foreach ($nodes as $node) { $class = $node->parentNode->parentNode; $property = new \DOMElement('property'); $class->appendChild($property); $property->setAttribute('final', 'false'); $property->setAttribute('static', 'false'); $property->setAttribute('visibility', 'public'); $property->setAttribute('line', $node->getAttribute('line')); $property->appendChild( new \DOMElement('name', $node->getAttribute('variable')) ); $property->appendChild(new \DOMElement('default')); $docblock = new \DOMElement('docblock'); $property->appendChild($docblock); $docblock->appendChild( new \DOMElement('description', $node->getAttribute('description')) ); $docblock->appendChild(new \DOMElement('long-description')); $var_tag = new \DOMElement('tag'); $docblock->appendChild($var_tag); $var_tag->setAttribute('name', 'var'); $var_tag->setAttribute('description', $node->getAttribute('description')); $var_tag->setAttribute('type', $node->getAttribute('type')); $var_tag->setAttribute('line', $node->getAttribute('line')); $var_tag_type = new \DOMElement('type', $node->getAttribute('type')); $var_tag->appendChild($var_tag_type); $var_tag_type->setAttribute('by_reference', 'false'); $magic_tag = new \DOMElement('tag'); $docblock->appendChild($magic_tag); $magic_tag->setAttribute('name', 'magic'); $magic_tag->setAttribute('line', $node->getAttribute('line')); $node->parentNode->removeChild($node); $docblock->appendChild($node); } return $xml; } } query('//tag[@name=\'uses\']'); /** @var \DOMElement $node */ foreach ($nodes as $node) { $refers = $node->getAttribute('refers'); $refers_array = explode('::', $refers); // determine the type so we know where to put the @usedby tag on $type = 'class'; if (isset($refers_array[1])) { // starts with $ = property, ends with () = method, // otherwise constant $type = $refers_array[1][0] == '$' ? 'property' : 'constant'; $type = substr($refers_array[1], -2) == '()' ? 'method' : $type; } switch ($type) { case 'class': // escape single quotes in the class name $xpath_refers = 'concat(\''.str_replace( array("'", '"'), array('\', "\'", \'', '\', \'"\' , \''), $refers ) . "', '')"; $qry = '/project/file/class[full_name=' . $xpath_refers . ']'; break; default: $class_name = $refers_array[0]; // escape single quotes in the class name $xpath_class_name = 'concat(\''.str_replace( array("'", '"'), array('\', "\'", \'', '\', \'"\' , \''), $class_name ) . "', '')"; // escape single quotes in the method name $xpath_method_name = 'concat(\''.str_replace( array("'", '"'), array('\', "\'", \'', '\', \'"\' , \''), rtrim($refers_array[1], '()') ) . "', '')"; $qry = '/project/file/class[full_name=' . $xpath_class_name . ']/'.$type.'[name=' . $xpath_method_name .']'; break; } /** @noinspection PhpUsageOfSilenceOperatorInspection as there is no pre-validation possible */ $referral_nodes = @$xpath->query($qry); // if the query is wrong; output a Critical error and continue to // the next @uses if ($referral_nodes === false) { continue; } // check if the result is unique; if not we error and continue // to the next @uses if ($referral_nodes->length > 1) { continue; } // if there is one matching element; link them together if ($referral_nodes->length > 0) { /** @var \DOMElement $referral */ $referral = $referral_nodes->item(0); $docblock = $referral->getElementsByTagName('docblock'); if ($docblock->length < 1) { $docblock = new \DOMElement('docblock'); $referral->appendChild($docblock); } else { $docblock = $docblock->item(0); } $used_by = new \DOMElement('tag'); $docblock->appendChild($used_by); $used_by->setAttribute('name', 'used_by'); $used_by->setAttribute('line', ''); // gather the name of the referring element and set that as refers // attribute if ($node->parentNode->parentNode->nodeName == 'class') { // if the element where the @uses is in is a class; nothing // more than the class name need to returned $referral_name = $node->parentNode->parentNode ->getElementsByTagName('full_name')->item(0)->nodeValue; } else { $referral_class_name = null; if ($node->parentNode->parentNode->nodeName == 'method') { // gather the name of the class where the @uses is in $referral_class_name = $node->parentNode->parentNode ->parentNode->getElementsByTagName('full_name')->item(0) ->nodeValue; } // gather the name of the subelement of the class where // the @uses is in $referral_name = $node->parentNode->parentNode ->getElementsByTagName('name')->item(0)->nodeValue; // if it is a method; suffix with () if ($node->parentNode->parentNode->nodeName == 'method' || $node->parentNode->parentNode->nodeName == 'function' ) { $referral_name .= '()'; } // only prefix class name if this is a class member if ($referral_class_name) { $referral_name = $referral_class_name . '::' . $referral_name; } } $used_by->setAttribute('description', $referral_name); $used_by->setAttribute('refers', $referral_name); } } return $xml; } } query($ignoreQry); /** @var \DOMElement $node */ foreach ($nodes as $node) { // if a node with name 'type' is selected we need to reach one // level further. $docblock = ($node->nodeName == 'type') ? $node->parentNode->parentNode : $node->parentNode; /** @var \DOMElement $method */ $method = $docblock->parentNode; // if the method is not a method but a global function: error! if ($method->nodeName != 'method') { continue; } $type = $method->parentNode->getElementsByTagName('full_name') ->item(0)->nodeValue; // nodes with name type need to set their content; otherwise we set // an attribute of the class itself if ($node->nodeName == 'type') { $node->nodeValue = $type; // add a new tag @fluent to indicate that this is a fluent interface // we only add it here since there should always be a node `type` $fluent_tag = new \DOMElement('tag'); $docblock->appendChild($fluent_tag); $fluent_tag->setAttribute('name', 'fluent'); $fluent_tag->setAttribute( 'description', 'This method is part of a fluent interface and will return ' . 'the same instance' ); } else { $node->setAttribute('type', $type); } // check if an excerpt is set and override that as well if ($node->hasAttribute('excerpt') && (($node->getAttribute('excerpt') == 'self') || ($node->getAttribute('excerpt') == '$this')) ) { $node->setAttribute('excerpt', $type); } } return $xml; } } query( '/project/file/class/docblock/tag[@name="method"]' ); /** @var \DOMElement $node */ foreach ($nodes as $node) { $class = $node->parentNode->parentNode; $method = new \DOMElement('method'); $class->appendChild($method); // set basic information $method->setAttribute('final', 'false'); $method->setAttribute('static', 'false'); $method->setAttribute('visibility', 'public'); $method->setAttribute('line', $node->getAttribute('line')); $method->appendChild( new \DOMElement('name', $node->getAttribute('method_name')) ); // fill docblock $docblock = new \DOMElement('docblock'); $method->appendChild($docblock); $docblock->appendChild( new \DOMElement('description', $node->getAttribute('description')) ); $docblock->appendChild(new \DOMElement('long-description')); // for each argument; create an @param tag and an argument element /** @var \DOMElement $argument */ foreach ($node->getElementsByTagName('argument') as $argument) { $param_tag = new \DOMElement('tag'); $docblock->appendChild($param_tag); $param_tag->setAttribute('name', 'param'); $param_tag->setAttribute( 'type', $argument->getElementsByTagName('type')->item(0)->nodeValue ); $param_tag->setAttribute( 'variable', $argument->getElementsByTagName('name')->item(0)->nodeValue ); $param_tag->setAttribute('line', $node->getAttribute('line')); $types = explode( '|', $argument->getElementsByTagName('type')->item(0)->nodeValue ); foreach ($types as $type) { $type_element = new \DOMElement('type', $type); $param_tag->appendChild($type_element); } $argument_element = $argument->cloneNode(true); $method->appendChild($argument_element); } // add a tag 'magic' $magic_tag = new \DOMElement('tag'); $docblock->appendChild($magic_tag); $magic_tag->setAttribute('name', 'magic'); $magic_tag->setAttribute('line', $node->getAttribute('line')); // add a @return tag $return_tag = new \DOMElement('tag'); $docblock->appendChild($return_tag); $return_tag->setAttribute('name', 'return'); $return_tag->setAttribute('line', $node->getAttribute('line')); $return_tag->setAttribute('type', $node->getAttribute('type')); // add type sub elements to the param foreach (explode('|', $node->getAttribute('type')) as $type) { $type_element = new \DOMElement('type', $type); $return_tag->appendChild($type_element); } // remove the tag, it is unneeded $node->parentNode->removeChild($node); $docblock->appendChild($node); } return $xml; } } query('//tag[@name=\'covers\']'); /** @var \DOMElement $node */ foreach ($nodes as $node) { $refers = $node->getAttribute('refers'); $refers_array = explode('::', $refers); // determine the type so we know where to put the @coveredby tag on $type = 'class'; if (isset($refers_array[1])) { // starts with $ = property, ends with () = method, // otherwise constant $type = $refers_array[1][0] == '$' ? 'property' : 'constant'; $type = substr($refers_array[1], -2) == '()' ? 'method' : $type; } switch ($type) { case 'class': // escape single quotes in the class name $xpath_refers = 'concat(\''.str_replace( array("'", '"'), array('\', "\'", \'', '\', \'"\' , \''), $refers ) . "', '')"; $qry = '/project/file/class[full_name=' . $xpath_refers . ']'; break; default: $class_name = $refers_array[0]; // escape single quotes in the class name $xpath_class_name = 'concat(\''.str_replace( array("'", '"'), array('\', "\'", \'', '\', \'"\' , \''), $class_name ) . "', '')"; // escape single quotes in the method name $xpath_method_name = 'concat(\''.str_replace( array("'", '"'), array('\', "\'", \'', '\', \'"\' , \''), rtrim($refers_array[1], '()') ) . "', '')"; $qry = '/project/file/class[full_name=' . $xpath_class_name . ']/'.$type.'[name=' . $xpath_method_name .']'; break; } /** @noinspection PhpUsageOfSilenceOperatorInspection as there is no pre-validation possible */ $referral_nodes = @$xpath->query($qry); // if the query is wrong; output a Critical error and continue to // the next @covers if ($referral_nodes === false) { // $this->log( // 'An XPath error occurs while processing @covers, the query used was: ' . $qry, // LogLevel::CRITICAL // ); continue; } // check if the result is unique; if not we error and continue // to the next @covers if ($referral_nodes->length > 1) { continue; } // if there is one matching element; link them together if ($referral_nodes->length > 0) { /** @var \DOMElement $referral */ $referral = $referral_nodes->item(0); $docblock = $referral->getElementsByTagName('docblock'); if ($docblock->length < 1) { $docblock = new \DOMElement('docblock'); $referral->appendChild($docblock); } else { $docblock = $docblock->item(0); } $used_by = new \DOMElement('tag'); $docblock->appendChild($used_by); $used_by->setAttribute('name', 'used_by'); $used_by->setAttribute('line', ''); // gather the name of the referring element and set that as refers // attribute if ($node->parentNode->parentNode->nodeName == 'class') { // if the element where the @covers is in is a class; nothing // more than the class name need to returned $referral_name = $node->parentNode->parentNode ->getElementsByTagName('full_name')->item(0)->nodeValue; } else { $referral_class_name = null; if ($node->parentNode->parentNode->nodeName == 'method') { // gather the name of the class where the @covers is in $referral_class_name = $node->parentNode->parentNode ->parentNode->getElementsByTagName('full_name')->item(0) ->nodeValue; } // gather the name of the subelement of the class where // the @covers is in $referral_name = $node->parentNode->parentNode ->getElementsByTagName('name')->item(0)->nodeValue; // if it is a method; suffix with () if ($node->parentNode->parentNode->nodeName == 'method' || $node->parentNode->parentNode->nodeName == 'function' ) { $referral_name .= '()'; } // only prefix class name if this is a class member if ($referral_class_name) { $referral_name = $referral_class_name . '::' . $referral_name; } } $used_by->setAttribute('description', $referral_name); $used_by->setAttribute('refers', $referral_name); } } return $xml; } } internalAllowed = $internalAllowed; } /** * Converts the 'internal' tags in Long Descriptions. * * @param \DOMDocument $xml Structure source to apply behaviour onto. * * @todo This behaviours actions should be moved to the parser / Reflector builder so that it can be cached * and is available to all writers. * * @return \DOMDocument */ public function process(\DOMDocument $xml) { $ignoreQry = '//long-description[contains(., "{@internal")]'; $xpath = new \DOMXPath($xml); $nodes = $xpath->query($ignoreQry); // either replace it with nothing or with the 'stored' value $replacement = $this->internalAllowed ? '$1' : ''; /** @var \DOMElement $node */ foreach ($nodes as $node) { $node->nodeValue = preg_replace('/\{@internal\s(.+?)\}\}/', $replacement, $node->nodeValue); } return $xml; } } tag . '\']'; $xpath = new \DOMXPath($xml); $nodes = $xpath->query($ignoreQry); /** @var \DOMElement $node */ foreach ($nodes as $node) { $remove = $node->parentNode->parentNode; // sometimes the parent node of the entity-to-be-removed is already // gone; for instance when a File docblock contains an @internal and // the underlying class also contains an @internal. // Because the File Docblock is found sooner, it is removed first. // Without the following check the application would fatal since // it cannot find, and then remove, this node from the parent. if (!isset($remove->parentNode)) { continue; } $remove->parentNode->removeChild($remove); } return $xml; } } // - Some Name // ignores leading and trailing whitespace // requires angled brackets when a name is given (that's what the // two (?(1)) conditions do) // requires closing angled bracket if email address is given with an // opening angled bracket but no name (that's what the (?(3)) // condition is for) $regex = '#^\s*(?P[^<]+?)?\s*((?(1)<|\b[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}\b)' .'(?(1)>|(?(3)>|>?)))\s*$#u'; $xpath = new \DOMXPath($xml); $nodes = $xpath->query('//tag[@name="author"]/@description'); /** @var \DOMElement $node */ foreach ($nodes as $node) { // FIXME: #193 if (preg_match($regex, $node->nodeValue, $matches)) { if ($matches['name']) { $value = $matches['name']; } else { // in case there were <> but no name... this cleans up the // output a bit $value = $matches['email']; } $node->nodeValue = $value; $node->parentNode->setAttribute( 'link', 'mailto:' . $matches['email'] ); } } return $xml; } } getPlugins(); if (! $plugins) { $app->register(new Core\ServiceProvider()); $app->register(new Scrybe\ServiceProvider()); return; } array_walk( $plugins, function ($plugin) use ($app) { /** @var Plugin $plugin */ $provider = (strpos($plugin->getClassName(), '\\') === false) ? sprintf('phpDocumentor\\Plugin\\%s\\ServiceProvider', $plugin->getClassName()) : $plugin->getClassName(); if (!class_exists($provider)) { throw new \RuntimeException('Loading Service Provider for ' . $provider . ' failed.'); } try { $app->register(new $provider($plugin)); } catch (\InvalidArgumentException $e) { throw new \RuntimeException($e->getMessage()); } } ); } } key; } /** * @return string */ public function getValue() { return $this->value; } } this plugin was generously provided by `@david0`. * @link https://github.com/phpDocumentor/phpDocumentor2/pull/1135 */ class ServiceProvider implements ServiceProviderInterface { /** @var Plugin */ private $plugin; /** * Construct plugin with a the relevant configuration * * @param Plugin $plugin **/ public function __construct(Plugin $plugin) { $this->plugin = $plugin; } /** * Registers services on the given app. * * @param Application $app An Application instance. */ public function register(Application $app) { $this->addNamespaceFilter($app['descriptor.builder'], $app['descriptor.filter']); } /** * Attaches the filter responsible for the conversion to all structural elements. * * @param ProjectDescriptorBuilder $builder * @param Filter $filterManager * * @return void */ private function addNamespaceFilter(ProjectDescriptorBuilder $builder, Filter $filterManager) { $filter = new LegacyNamespaceFilter($builder); // parse parameters foreach ($this->plugin->getParameters() as $param) { if ($param->getKey() == 'NamespacePrefix') { $filter->setNamespacePrefix($param->getValue()); } } $filterManager->attach('phpDocumentor\Descriptor\ConstantDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\FunctionDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\InterfaceDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\TraitDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\PropertyDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\FileDescriptor', $filter); $filterManager->attach('phpDocumentor\Descriptor\ClassDescriptor', $filter); } } this plugin was generously provided by `@david0`. * @link https://github.com/phpDocumentor/phpDocumentor2/pull/1135 */ class LegacyNamespaceFilter extends AbstractFilter { /** @var ProjectDescriptorBuilder $builder */ protected $builder; /** @var string */ private $namespacePrefix=''; /** * Initializes this filter with an instance of the builder to retrieve the latest ProjectDescriptor from. * * @param ProjectDescriptorBuilder $builder */ public function __construct(ProjectDescriptorBuilder $builder) { $this->builder = $builder; } /** * Overrides the name and namespace of an element with a separated version of the class name. * * If a class is separated by underscores than the last part is set as name and the first parts are set as * namespace with the namespace separator instead of an underscore. * * @param DescriptorAbstract $value * * @return DescriptorAbstract|null */ public function filter($value) { if ($value) { $namespace = $value->getNamespace()=='' ? '\\' . $this->namespacePrefix : $value->getNamespace(); $value->setNamespace($this->namespaceFromLegacyNamespace($namespace, $value->getName())); $value->setName($this->classNameFromLegacyNamespace($value->getName())); } return $value; } /** * Extracts the namespace from the class name. * * @param string $namespace * @param string $className * * @return string */ private function namespaceFromLegacyNamespace($namespace, $className) { $qcn = str_replace('_', '\\', $className); $lastBackslash = strrpos($qcn, '\\'); if ($lastBackslash) { $namespace = rtrim($namespace, '\\') . '\\' . substr($qcn, 0, $lastBackslash); } return $namespace; } /** * Extracts the class name without prefix from the full class name. * * @param string $className * * @return string */ private function classNameFromLegacyNamespace($className) { $lastUnderscore = strrpos($className, '_'); if ($lastUnderscore) { $className = substr($className, $lastUnderscore + 1); } return $className; } /** * Set a prefix for all elements without an namespace * * @param string $prefix */ public function setNamespacePrefix($prefix) { $this->namespacePrefix = $prefix; } } Legacy Namespace Converter Plugin ================================= This plugin will convert legacy/[PEAR-style namespaces](http://pear.php.net/manual/en/standards.naming.php) to real namespaces for phpDocumentor. For example the class name `My_Special_ClassName` will be transformed into the class `ClassName` with namespace `My\Special`. Example configuration file: If your legacy class names did not contain a vendor prefix and you are mixing with [PSR-4-style](http://www.php-fig.org/psr/psr-4/) classes, you might want to add a vendor prefix to your legacy classes by configuring this plugin. You can archive this by configuring the parameter *NamespacePrefix*: .. VendorName .. If you're getting generation errors like: PPC:ERR-50008 PHP Notice: Undefined index: VAL:ERRLVL-50015 you probably need to add the default 'Core' plugin also: This is so because "when you define plugins you override the whole set so that you could replace everything should you want to.". For more info - [here](https://github.com/phpDocumentor/phpDocumentor2/issues/1534#issuecomment-128092193) builderMock = m::mock('phpDocumentor\Descriptor\ProjectDescriptorBuilder'); $this->filter = new LegacyNamespaceFilter($this->builderMock); } /** * @covers phpDocumentor\Plugin\LegacyNamespaceConverter\LegacyNamespaceFilter::filter */ public function testConvertClassNameWithUnderscoreWillBeConvertedToNamespace() { $descriptor = $this->createDescriptorMock(); $descriptor->shouldReceive('getName')->andReturn('LegacyNamespace_ClassName'); $descriptor->shouldReceive('getNamespace')->andReturn('\\'); $descriptor->shouldReceive('setName')->with('ClassName')->once(); $descriptor->shouldReceive('setNamespace')->with('\LegacyNamespace')->once(); $this->filter->filter($descriptor); $this->assertTrue(true); } /** * @covers phpDocumentor\Plugin\LegacyNamespaceConverter\LegacyNamespaceFilter::filter */ public function testMultiLevelLegacyNamespace() { $descriptor = $this->createDescriptorMock(); $descriptor->shouldReceive('getName')->andReturn('LegacyNamespace_Sub_ClassName'); $descriptor->shouldReceive('getNamespace')->andReturn('\\'); $descriptor->shouldReceive('setName')->with('ClassName')->once(); $descriptor->shouldReceive('setNamespace')->with('\LegacyNamespace\Sub')->once(); $this->filter->filter($descriptor); $this->assertTrue(true); } /** * @covers phpDocumentor\Plugin\LegacyNamespaceConverter\LegacyNamespaceFilter::filter */ public function testMixedNamespacesCanBeUnified() { $descriptor = $this->createDescriptorMock(); $descriptor->shouldReceive('getName')->andReturn('LegacyNamespace_ClassName'); $descriptor->shouldReceive('getNamespace')->andReturn('\\NewNamespace'); $descriptor->shouldReceive('setName')->with('ClassName')->once(); $descriptor->shouldReceive('setNamespace')->with('\\NewNamespace\\LegacyNamespace')->once(); $this->filter->filter($descriptor); $this->assertTrue(true); } /** * @covers phpDocumentor\Plugin\LegacyNamespaceConverter\LegacyNamespaceFilter::filter */ public function testClassNameWithNewNamespaceWillNotBeModified() { $descriptor = $this->createDescriptorMock(); $descriptor->shouldReceive('getName')->andReturn('ClassName'); $descriptor->shouldReceive('getNamespace')->andReturn('\\NewNamespace'); $descriptor->shouldReceive('setName')->with('ClassName')->once(); $descriptor->shouldReceive('setNamespace')->with('\\NewNamespace')->once(); $this->filter->filter($descriptor); $this->assertTrue(true); } /** * @covers phpDocumentor\Plugin\LegacyNamespaceConverter\LegacyNamespaceFilter::filter */ public function testClassNameWithEmptyNamespace() { $descriptor = $this->createDescriptorMock(); $descriptor->shouldReceive('getName')->andReturn('ClassName'); $descriptor->shouldReceive('getNamespace')->andReturn('\\'); $descriptor->shouldReceive('setName')->with('ClassName')->once(); $descriptor->shouldReceive('setNamespace')->with('\\')->once(); $this->filter->filter($descriptor); $this->assertTrue(true); } /** * @covers phpDocumentor\Plugin\LegacyNamespaceConverter\LegacyNamespaceFilter::filter */ public function testPrefixedNamespace() { $this->filter->setNamespacePrefix('Vendor'); $descriptor = $this->createDescriptorMock(); $descriptor->shouldReceive('getName')->andReturn('ClassName'); $descriptor->shouldReceive('getNamespace')->andReturn(''); $descriptor->shouldReceive('setName')->with('ClassName')->once(); $descriptor->shouldReceive('setNamespace')->with('\\Vendor')->once(); $this->filter->filter($descriptor); $this->assertTrue(true); } /** * @covers phpDocumentor\Plugin\LegacyNamespaceConverter\LegacyNamespaceFilter::filter */ public function testPrefixedNamespaceWithNamespacedClassWillNotBeModified() { $this->filter->setNamespacePrefix('Vendor'); $descriptor = $this->createDescriptorMock(); $descriptor->shouldReceive('getName')->andReturn('ClassName'); $descriptor->shouldReceive('getNamespace')->andReturn('\\'); $descriptor->shouldReceive('setName')->with('ClassName')->once(); $descriptor->shouldReceive('setNamespace')->with('\\')->once(); $this->filter->filter($descriptor); $this->assertTrue(true); } /** * Creates a mocked Descriptor. * * @return m\MockInterface|DescriptorAbstract */ private function createDescriptorMock() { return m::mock('phpDocumentor\Descriptor\DescriptorAbstract'); } } * ``` * * This example transformation would use this writer to transform the * index.twig template file in the twig template folder into index.html at * the destination location. * Since no Query is provided the 'node' global variable will contain * the Project Descriptor of the Object Graph. * * A complex example transformation line could be: * * ``` * * ``` * * This example transformation would use this writer to transform the * class.twig template file in the twig template folder into a file with * the 'name' property for an individual class inside the Object Graph. * Since a Query *is* provided will the 'node' global variable contain a * specific instance of a class applicable to the current iteration. * * @see self::getDestinationPath() for more information about variables in the * Artifact attribute. */ class Twig extends WriterAbstract implements Routable { /** @var Queue $routers */ protected $routers; /** @var Translator $translator */ protected $translator; /** * This method combines the ProjectDescriptor and the given target template * and creates a static html page at the artifact location. * * @param ProjectDescriptor $project Document containing the structure. * @param Transformation $transformation Transformation to execute. * * @return void */ public function transform(ProjectDescriptor $project, Transformation $transformation) { $template_path = $this->getTemplatePath($transformation); $finder = new Pathfinder(); $nodes = $finder->find($project, $transformation->getQuery()); foreach ($nodes as $node) { if (!$node) { continue; } $destination = $this->getDestinationPath($node, $transformation); if ($destination === false) { continue; } $environment = $this->initializeEnvironment($project, $transformation, $destination); $environment->addGlobal('node', $node); $html = $environment->render(substr($transformation->getSource(), strlen($template_path))); file_put_contents($destination, $html); } } /** * Initializes the Twig environment with the template, base extension and additionally defined extensions. * * @param ProjectDescriptor $project * @param Transformation $transformation * @param string $destination * * @return \Twig_Environment */ protected function initializeEnvironment(ProjectDescriptor $project, Transformation $transformation, $destination) { $callingTemplatePath = $this->getTemplatePath($transformation); $baseTemplatesPath = $transformation->getTransformer()->getTemplates()->getTemplatesPath(); $templateFolders = array( $baseTemplatesPath . '/..' . DIRECTORY_SEPARATOR . $callingTemplatePath, // http://twig.sensiolabs.org/doc/recipes.html#overriding-a-template-that-also-extends-itself $baseTemplatesPath ); // get all invoked template paths, they overrule the calling template path /** @var Template $template */ foreach ($transformation->getTransformer()->getTemplates() as $template) { $path = $baseTemplatesPath . DIRECTORY_SEPARATOR . $template->getName(); array_unshift($templateFolders, $path); } $env = new \Twig_Environment( new \Twig_Loader_Filesystem($templateFolders), array('cache' => sys_get_temp_dir() . '/phpdoc-twig-cache') ); $this->addPhpDocumentorExtension($project, $transformation, $destination, $env); $this->addExtensionsFromTemplateConfiguration($transformation, $project, $env); return $env; } /** * Adds the phpDocumentor base extension to the Twig Environment. * * @param ProjectDescriptor $project * @param Transformation $transformation * @param string $destination * @param \Twig_Environment $twigEnvironment * * @return void */ protected function addPhpDocumentorExtension( ProjectDescriptor $project, Transformation $transformation, $destination, \Twig_Environment $twigEnvironment ) { $base_extension = new Extension($project, $transformation); $base_extension->setDestination( substr($destination, strlen($transformation->getTransformer()->getTarget()) + 1) ); $base_extension->setRouters($this->routers); $base_extension->setTranslator($this->translator); $twigEnvironment->addExtension($base_extension); } /** * Tries to add any custom extensions that have been defined in the template or the transformation's configuration. * * This method will read the `twig-extension` parameter of the transformation (which inherits the template's * parameter set) and try to add those extensions to the environment. * * @param Transformation $transformation * @param ProjectDescriptor $project * @param \Twig_Environment $twigEnvironment * * @throws \InvalidArgumentException if a twig-extension should be loaded but it could not be found. * * @return void */ protected function addExtensionsFromTemplateConfiguration( Transformation $transformation, ProjectDescriptor $project, \Twig_Environment $twigEnvironment ) { $isDebug = $transformation->getParameter('twig-debug') ? $transformation->getParameter('twig-debug')->getValue() : false; if ($isDebug == 'true') { $twigEnvironment->enableDebug(); $twigEnvironment->enableAutoReload(); $twigEnvironment->addExtension(new \Twig_Extension_Debug()); } /** @var Template\Parameter $extension */ foreach ($transformation->getParametersWithKey('twig-extension') as $extension) { $extensionValue = $extension->getValue(); if (!class_exists($extensionValue)) { throw new \InvalidArgumentException('Unknown twig extension: ' . $extensionValue); } // to support 'normal' Twig extensions we check the interface to determine what instantiation to do. $implementsInterface = in_array( 'phpDocumentor\Plugin\Twig\ExtensionInterface', class_implements($extensionValue) ); $twigEnvironment->addExtension( $implementsInterface ? new $extensionValue($project, $transformation) : new $extensionValue() ); } } /** * Uses the currently selected node and transformation to assemble the destination path for the file. * * The Twig writer accepts the use of a Query to be able to generate output for multiple objects using the same * template. * * The given node is the result of such a query, or if no query given the selected element, and the transformation * contains the destination file. * * Since it is important to be able to generate a unique name per element can the user provide a template variable * in the name of the file. * Such a template variable always resides between double braces and tries to take the node value of a given * query string. * * Example: * * An artifact stating `classes/{{name}}.html` will try to find the * node 'name' as a child of the given $node and use that value instead. * * @param DescriptorAbstract $node * @param Transformation $transformation * * @throws \InvalidArgumentException if no artifact is provided and no routing rule matches. * @throws \UnexpectedValueException if the provided node does not contain anything. * * @return string|false returns the destination location or false if generation should be aborted. */ protected function getDestinationPath($node, Transformation $transformation) { $writer = $this; if (!$node) { throw new \UnexpectedValueException( 'The transformation node in the twig writer is not expected to be false or null' ); } if (!$transformation->getArtifact()) { $rule = $this->routers->match($node); if (!$rule) { throw new \InvalidArgumentException( 'No matching routing rule could be found for the given node, please provide an artifact location, ' . 'encountered: ' . ($node === null ? 'NULL' : get_class($node)) ); } $rule = new ForFileProxy($rule); $url = $rule->generate($node); if ($url === false || $url[0] !== DIRECTORY_SEPARATOR) { return false; } $path = $transformation->getTransformer()->getTarget() . str_replace('/', DIRECTORY_SEPARATOR, $url); } else { $path = $transformation->getTransformer()->getTarget() . DIRECTORY_SEPARATOR . $transformation->getArtifact(); } $finder = new Pathfinder(); $destination = preg_replace_callback( '/{{([^}]+)}}/', // explicitly do not use the unicode modifier; this breaks windows function ($query) use ($node, $writer, $finder) { // strip any surrounding \ or / $filepart = trim((string) current($finder->find($node, $query[1])), '\\/'); // make it windows proof if (extension_loaded('iconv')) { $filepart = iconv('UTF-8', 'ASCII//TRANSLIT', $filepart); } $filepart = strpos($filepart, '/') !== false ? implode('/', array_map('urlencode', explode('/', $filepart))) : implode('\\', array_map('urlencode', explode('\\', $filepart))); return $filepart; }, $path ); // replace any \ with the directory separator to be compatible with the // current filesystem and allow the next file_exists to do its work $destination = str_replace(array('/','\\'), DIRECTORY_SEPARATOR, $destination); // create directory if it does not exist yet if (!file_exists(dirname($destination))) { mkdir(dirname($destination), 0777, true); } return $destination; } /** * Returns the path belonging to the template. * * @param Transformation $transformation * * @return string */ protected function getTemplatePath($transformation) { $parts = preg_split('[\\\\|/]', $transformation->getSource()); return $parts[0] . DIRECTORY_SEPARATOR . $parts[1]; } /** * Sets the routers that can be used to determine the path of links. * * @param Queue $routers * * @return void */ public function setRouters(Queue $routers) { $this->routers = $routers; } /** * @param Translator $translator */ public function setTranslator($translator) { $this->translator = $translator; } } data = $project; $this->routeRenderer = new Renderer(new Queue()); } /** * Returns the name of this extension. * * @return string The extension name */ public function getName() { return 'phpdocumentor'; } /** * Sets the router used to render the URL where a Descriptor can be found. * * @param Queue $routers * * @return void */ public function setRouters($routers) { $this->routeRenderer->setRouters($routers); } /** * Sets the translation component. * * @param Translator $translator * * @return void */ public function setTranslator($translator) { $this->translator = $translator; } /** * Sets the destination directory relative to the Project's Root. * * The destination is the target directory containing the resulting * file. This destination is relative to the Project's root and can * be used for the calculation of nesting depths, etc. * * @param string $destination * * @see phpDocumentor\Plugin\Twig\Transformer\Writer\Twig for the invocation of this method. * * @return void */ public function setDestination($destination) { $this->routeRenderer->setDestination($destination); } /** * Returns the target directory relative to the Project's Root. * * @return string */ public function getDestination() { return $this->routeRenderer->getDestination(); } /** * Returns an array of global variables to inject into a Twig template. * * @return mixed[] */ public function getGlobals() { return array( 'project' => $this->data ); } /** * Returns a listing of all functions that this extension adds. * * This method is automatically used by Twig upon registering this * extension (which is done automatically by phpDocumentor) to determine * an additional list of functions. * * See the Class' DocBlock for a listing of functionality added by this * Extension. * * @return \Twig_FunctionInterface[] */ public function getFunctions() { return array( new \Twig_SimpleFunction('path', array($this->routeRenderer, 'convertToRootPath')) ); } /** * Returns a list of all filters that are exposed by this extension. * * @return \Twig_SimpleFilter[] */ public function getFilters() { $parser = \Parsedown::instance(); $translator = $this->translator; $routeRenderer = $this->routeRenderer; return array( 'markdown' => new \Twig_SimpleFilter( 'markdown', function ($value) use ($parser) { return $parser->text($value); } ), 'trans' => new \Twig_SimpleFilter( 'trans', function ($value, $context) use ($translator) { if (!$context) { $context = array(); } return vsprintf($translator->translate($value), $context); } ), 'route' => new \Twig_SimpleFilter( 'route', function ($value, $presentation = 'normal') use ($routeRenderer) { return $routeRenderer->render($value, $presentation); } ), 'sort' => new \Twig_SimpleFilter( 'sort_*', function ($direction, $collection) { if (!$collection instanceof Collection) { return $collection; } $iterator = $collection->getIterator(); $iterator->uasort( function ($a, $b) use ($direction) { $aElem = strtolower($a->getName()); $bElem = strtolower($b->getName()); if ($aElem === $bElem) { return 0; } if ($direction === 'asc' && $aElem > $bElem || $direction === 'desc' && $aElem < $bElem) { return 1; } return -1; } ); return $iterator; } ), ); } /** * Converts the given path to be relative to the root of the documentation * target directory. * * It is not possible to use absolute paths in documentation templates since * they may be used locally, or in a subfolder. As such we need to calculate * the number of levels to go up from the current document's directory and * then append the given path. * * For example: * * Suppose you are in /classes/my/class.html and you want open * /my/index.html then you provide 'my/index.html' to this method * and it will convert it into ../../my/index.html (/classes/my is * two nesting levels until the root). * * This method does not try to normalize or optimize the paths in order to * save on development time and performance, and because it adds no real * value. * * @param string $relative_path * * @return string */ public function convertToRootPath($relative_path) { return $this->routeRenderer->convertToRootPath($relative_path); } } setTranslator($translator); } } path = $templatePath; } /** * Sets the name for this template. * * @param string $name A template name that may be composed of alphanumeric characters, underscores and/or hyphens. * * @throws \InvalidArgumentException if the name does not match the prescribed format. * * @return void */ public function setName($name) { if (!preg_match('/^[0-9a-zA-Z\-\_]{3,}$/', $name)) { throw new \InvalidArgumentException( 'A template name may only be composed of alphanumeric ' .'characters, underscores or hyphens and have at least 3 ' .'characters.' ); } $this->name = $name; } /** * Returns the name of this template. * * See setName() for a specification of the format. * * @return string */ public function getName() { return $this->name; } /** * Sets the base path where the templates are stored. * * @param string $path * * @throws \InvalidArgumentException * * @return void */ public function setPath($path) { if (!file_exists($path) || !is_dir($path)) { throw new \InvalidArgumentException( 'Expected the template path to be an existing directory, received: '.$path ); } $this->path = $path; } /** * Returns the base path where the templates are stored. * * @return string */ public function getPath() { return $this->path; } /** * Sets the file extension used to determine the template filename. * * The file extension of the destination format needs to be set. This is used to retrieve the correct template. * * @param string $extension an extension (thus only containing alphanumeric characters and be between 2 and 4 * characters in size). * * @throws \InvalidArgumentException if the extension does not match the validation restrictions mentioned above. * * @return void */ public function setExtension($extension) { if (!preg_match('/^[a-zA-Z0-9]{2,4}$/', $extension)) { throw new \InvalidArgumentException( 'Extension should be only be composed of alphanumeric characters' . ' and should be at least 2 but no more than 4 characters' ); } $this->extension = $extension; } /** * Returns the extension of the destination file extension. * * @see setExtension for more information and the format of the extension. * * @return string */ public function getExtension() { return $this->extension; } /** * Applies the relevant template upon the given content. * * This method takes the combines the template with the given contents and generates a final piece of text * from that. * * The user may add additional options that are set as parameters in the template. * * @param string $contents * @param string[] $options * * @see getTemplateFileName() how the filename is assembled * * @return string */ public function decorate($contents, array $options = array()) { return $this->getTwigEnvironment()->render( $this->getTemplateFilename(), array_merge(array('contents' => $contents), $options) ); } /** * Returns a list of files that need to be copied to the destination location. * * Examples of assets can be: * * * CSS files * * Javascript files * * Images * * Assets for this template engine means every file that is contained in a subfolder of the template folder and * does not end with the extension twig. * * Thus every file in the root of the template folder is ignored and files and directories having only twig * templates (considered as being includes) are not included in this list. * * @return string[] */ public function getAssets() { $finder = new Finder(); return iterator_to_array( $finder->files() ->in($this->path.DIRECTORY_SEPARATOR . $this->name) ->depth('> 0') ->notName('*.twig') ->sortByName() ); } /** * Returns the filename for the template. * * The filename is composed of the following components: * * - the template base folder * - the template's name * - a path separator * - the literal 'layout' combined with the extension * - and as final extension the literal '.twig' * * @throws \DomainException if the template does not exist. * * @return string */ protected function getTemplateFilename() { $filename = $this->name.'/layout.' . $this->extension . '.twig'; $template_path = $this->path . DIRECTORY_SEPARATOR . $filename; if (!file_exists($template_path)) { throw new \DomainException('Template file "' . $template_path . '" could not be found'); } return $filename; } /** * Constructs and returns the twig environment. * * This uses the path as defined with this class to instantiate a new Environment and disables the escaping * mechanism since we use it to generate HTML; even embedded. * * @see $path for the template base path. * * @return \Twig_Environment */ protected function getTwigEnvironment() { $twig = new \Twig_Environment(new \Twig_Loader_Filesystem($this->path), array('autoescape' => false)); return $twig; } } $class) { $this->register($name, $class); } } /** * Associates a human-readable / simplified name with a class name representing a template engine. * * The class belonging to the given class name should implement the TemplateInterface. If it does not then * this method won't complain (as no instantiation is done here for performance reasons) but the `get()` method * will throw an exception. * * @param string $name * @param TemplateInterface $templateEngine * * @see get() to retrieve an instance for the given $name. * * @return void */ public function register($name, TemplateInterface $templateEngine) { $this->engines[$name] = $templateEngine; } /** * Returns a new instance of the template engine belonging to the given name. * * @param string $name * * @throws \InvalidArgumentException if the given name is not registered * * @return TemplateInterface */ public function get($name) { if (!isset($this->engines[$name])) { throw new \InvalidArgumentException('Template engine "'.$name.'" is not known or registered'); } return $this->engines[$name]; } } assertEquals('default', $fixture->getName()); $fixture->setName('my_template-one'); $this->assertEquals('my_template-one', $fixture->getName()); } /** * @dataProvider provideTestNamesForSetName * @covers \phpDocumentor\Plugin\Scrybe\Template\Twig::setName */ public function testSetTemplateNameValidity($name, $erroneous) { if ($erroneous) { $this->setExpectedException('\InvalidArgumentException'); } $fixture = new Twig(); $fixture->setName($name); $this->assertEquals($name, $fixture->getName()); } /** * Provides a dataset to test the different permutations of the template * name. * * @return string[][] */ public function provideTestNamesForSetName() { return array( array('1', true), array('12', true), array('123', false), array('Abc1', false), array('Abc-1', false), array('Abc-_1', false), array('Abc-_1!', true), array('Abc-_1 ', true), array(' Abc-_1', true), ); } /** * @covers \phpDocumentor\Plugin\Scrybe\Template\Twig::getExtension * @covers \phpDocumentor\Plugin\Scrybe\Template\Twig::setExtension */ public function testReadAndWriteExtension() { $fixture = new Twig(); $this->assertEquals('html', $fixture->getExtension()); $fixture->setExtension('pdf'); $this->assertEquals('pdf', $fixture->getExtension()); } /** * @dataProvider provideTestNamesForSetExtension * @covers \phpDocumentor\Plugin\Scrybe\Template\Twig::setExtension */ public function testSetExtensionValidity($extension, $erroneous) { if ($erroneous) { $this->setExpectedException('\InvalidArgumentException'); } $fixture = new Twig(); $fixture->setExtension($extension); $this->assertEquals($extension, $fixture->getExtension()); } /** * Provides a dataset to test the different permutations of the template * name. * * @return string[][] */ public function provideTestNamesForSetExtension() { return array( array('1', true), array('12', false), array('pdf', false), array('html', false), array('latex', true), array('p-f', true), array('p_f', true), ); } /** * @covers \phpDocumentor\Plugin\Scrybe\Template\Twig::getPath * @covers \phpDocumentor\Plugin\Scrybe\Template\Twig::setPath */ public function testReadAndWriteBaseTemplatePath() { $fixture = new Twig(); $this->assertEquals( realpath(__DIR__.'/../../../../data/templates'), $fixture->getPath() ); $fixture->setPath(__DIR__); $this->assertEquals(__DIR__, $fixture->getPath()); } /** * @covers \phpDocumentor\Plugin\Scrybe\Template\Twig::setPath * @expectedException InvalidArgumentException */ public function testSetNonExistingBaseTemplatePath() { $fixture = new Twig(); $fixture->setPath('bla'); } /** * @covers \phpDocumentor\Plugin\Scrybe\Template\Twig::setPath * @expectedException InvalidArgumentException */ public function testSetFileAsBaseTemplatePath() { $fixture = new Twig(); $fixture->setPath(__FILE__); } /** * @covers \phpDocumentor\Plugin\Scrybe\Template\Twig::getAssets */ public function testGetAssets() { $fixture = new Twig(''); $assets = $fixture->getAssets(); $this->assertInternalType('array', $assets); $this->assertGreaterThan(0, count($assets)); $this->assertInstanceOf('SplFileInfo', current($assets)); $this->assertStringStartsWith($fixture->getPath(), key($assets)); foreach (array_keys($assets) as $filename) { $this->assertStringEndsNotWith('.twig', $filename); } } } '\phpDocumentor\Plugin\Scrybe\Template\Mock\Template') ); $this->assertInstanceOf( '\phpDocumentor\Plugin\Scrybe\Template\Mock\Template', $factory->get('Mock') ); } /** * Tests whether this factory registers the twig template engine by default. * * @covers \phpDocumentor\Plugin\Scrybe\Template\Factory */ public function testHasTwigTemplateEngine() { $factory = new Factory(); $this->assertInstanceOf( '\phpDocumentor\Plugin\Scrybe\Template\Twig', $factory->get('twig') ); } /** * Tests whether a Template could be registered using the register method. * * @covers \phpDocumentor\Plugin\Scrybe\Template\Factory::register */ public function testRegisterTemplateEngine() { $factory = new Factory(); $factory->register('Mock', '\phpDocumentor\Plugin\Scrybe\Template\Mock\Template'); $this->assertInstanceOf( '\phpDocumentor\Plugin\Scrybe\Template\Mock\Template', $factory->get('Mock') ); } /** * @covers \phpDocumentor\Plugin\Scrybe\Template\Factory::register * @expectedException \InvalidArgumentException */ public function testRegisterInvalidName() { $factory = new Factory(); $factory->register(array(), ''); } /** * @covers \phpDocumentor\Plugin\Scrybe\Template\Factory::register * @expectedException \InvalidArgumentException */ public function testRegisterInvalidClassName() { $factory = new Factory(); $factory->register('', array()); } /** * @covers \phpDocumentor\Plugin\Scrybe\Template\Factory::get * @expectedException \InvalidArgumentException */ public function testGetUnknownTemplateEngine() { $factory = new Factory(); $factory->get('Mock'); } /** * @covers \phpDocumentor\Plugin\Scrybe\Template\Factory::get * @expectedException \RuntimeException */ public function testGetInvalidTemplateEngine() { $factory = new Factory(); $factory->register('Mock', '\DOMDocument'); $factory->get('Mock'); } } assertEquals('phpDocumentor Scrybe', $fixture['console']->getName()); $this->assertEquals(Application::VERSION, $fixture['console']->getVersion()); } /** * Tests whether the application has initialized the manual:to-pdf Command. * * @covers \phpDocumentor\Plugin\Scrybe\Application * * @return void */ public function testContainsToPdfCommand() { $this->markTestSkipped( 'PDF command is currently disabled until a new implementation is done' ); $fixture = new Application(); $this->assertTrue($fixture['console']->has('manual:to-pdf')); } /** * Tests whether the application has initialized the manual:to-html Command. * * @covers \phpDocumentor\Plugin\Scrybe\Application * * @return void */ public function testContainsToHtmlCommand() { $fixture = new Application(); $this->assertTrue($fixture['console']->has('manual:to-html')); } } assertSame($file, $module->getTableOfContentsRoot()); } } object = m::mock('phpDocumentor\Plugin\Scrybe\Converter\Metadata\TableOfContents\BaseEntry[]'); } /** * @covers phpDocumentor\Plugin\Scrybe\Converter\Metadata\TableOfContents\BaseEntry::getParent * @covers phpDocumentor\Plugin\Scrybe\Converter\Metadata\TableOfContents\BaseEntry::setParent */ public function testAddingAParentEntry() { $this->assertSame(null, $this->object->getParent()); $heading = new Heading(); $this->object->setParent($heading); $this->assertSame($heading, $this->object->getParent()); } /** * @expectedException \InvalidArgumentException * * @covers phpDocumentor\Plugin\Scrybe\Converter\Metadata\TableOfContents\BaseEntry::setParent */ public function testAddingAnInvalidParentEntry() { $toc = new TableOfContents(); $this->object->setParent($toc); } /** * @covers phpDocumentor\Plugin\Scrybe\Converter\Metadata\TableOfContents\BaseEntry::getChildren * @covers phpDocumentor\Plugin\Scrybe\Converter\Metadata\TableOfContents\BaseEntry::addChild */ public function testAddingChildren() { $this->assertEmpty($this->object->getChildren()); $heading = new Heading(); $this->object->addChild($heading); $this->assertCount(1, $this->object->getChildren()); $this->assertSame(array($heading), $this->object->getChildren()); } /** * @covers phpDocumentor\Plugin\Scrybe\Converter\Metadata\TableOfContents\BaseEntry::getName * @covers phpDocumentor\Plugin\Scrybe\Converter\Metadata\TableOfContents\BaseEntry::setName */ public function testSettingAName() { $this->assertSame('', $this->object->getName()); $this->object->setName('name'); $this->assertSame('name', $this->object->getName()); } } setFilename('test'); $this->assertSame('test', $file->getFilename()); } } object = new TableOfContents; } /** * @expectedException \InvalidArgumentException */ public function testAddInvalidFile() { $this->object[] = new TableOfContents\Heading(); } public function testAdd() { $file = new TableOfContents\File(); $file->setFilename('test'); $this->object[] = $file; $this->assertCount(1, $this->object); $this->assertTrue(isset($this->object['test'])); $this->assertSame($file, $this->object['test']); } public function testRecognizesModule() { $file = new TableOfContents\File(); $file->setFilename('test'); $file2 = new TableOfContents\File(); $file2->setFilename('test2'); $file3 = new TableOfContents\File(); $file3->setFilename('index'); $file4 = new TableOfContents\File(); $file4->setFilename('INDEX'); $file5 = new TableOfContents\File(); $file5->setFilename('test3'); $this->object[] = $file; $this->object[] = $file2; $this->object[] = $file3; $this->object[] = $file4; $this->assertCount(2, $this->object->getModules()); $this->assertSame(array($file3, $file4), $this->object->getModules()); } } object = new Discover($this->getDocumentMock(), ''); } protected function getDocumentMock() { if (!$this->document) { $file = $this->getMock( '\phpDocumentor\Fileset\File', array('getFilename'), array(), '', false ); $file->expects($this->any())->method('getFilename') ->will($this->returnValue(self::FILENAME)); $this->document = $this->getMock( '\phpDocumentor\Plugin\Scrybe\Converter\RestructuredText\Document', array('getConverter', 'getFile'), array(), '', false ); $this->document->expects($this->any()) ->method('getConverter') ->will($this->returnValue($this->getConverterMock())); $this->document->expects($this->any()) ->method('getFile')->will($this->returnValue($file)); } return $this->document; } protected function getConverterMock() { if (!$this->converter) { $this->converter = $this->getMock( '\phpDocumentor\Plugin\Scrybe\Converter\RestructuredText\ToHtml', array('getTableOfContents'), array(), '', false ); $this->converter->expects($this->any()) ->method('getTableOfContents') ->will($this->returnValue($this->getTableOfContentsMock())); } return $this->converter; } protected function getTableOfContentsMock() { if (!$this->table_of_contents) { $this->table_of_contents = $this->getMock( '\phpDocumentor\Plugin\Scrybe\Converter\Metadata\TableOfContents' ); } return $this->table_of_contents; } public function testRetrieveTableOfContents() { $this->assertSame( $this->getTableOfContentsMock(), $this->object->getTableOfContents() ); } public function testRetrieveFilename() { $this->markTestIncomplete("testRetrieveFilename() is not working..."); //$this->assertSame(self::FILENAME, $this->object->getFilename()); } public function testRetrieveDocument() { $this->assertSame( $this->getDocumentMock(), $this->object->getDocument() ); } } {% raw %} \documentclass[11pt,titlepage,a4paper]{report} \usepackage{amssymb,amsmath} \usepackage{graphicx} % We will generate all images so they have a width \maxwidth. This means % that they will get their normal width if they fit onto the page, but % are scaled down if they would overflow the margins. \makeatletter \def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth \else\Gin@nat@width\fi} \makeatother \let\Oldincludegraphics\includegraphics \renewcommand{\includegraphics}[1]{\Oldincludegraphics[width=\maxwidth]{#1}} \usepackage[breaklinks=true,unicode=true,pdfborder={0 0 0}]{hyperref} \setlength{\parindent}{0pt} \setlength{\parskip}{6pt plus 2pt minus 1pt} \setcounter{secnumdepth}{0} {% endraw %} \title{{'{'}} {% if coverlogo %}\includegraphics{{'{'}}{{coverlogo}}}{% endif %} \\{{title}} } \author{{'{'}}{{author}}} \date{\today} \begin{document} \sffamily {% if title or coverlogo %} \maketitle {% endif %} {% if toc %} \tableofcontents {% endif %} {{ contents }} \end{document}
  • {{ entry.name }}
      {% for entry in entry.children %} {% include 'default/toc.html.twig' %} {% endfor %}
  • {% raw %} \documentclass[11pt,titlepage,a4paper]{report} \usepackage{amssymb,amsmath} \usepackage{graphicx} % We will generate all images so they have a width \maxwidth. This means % that they will get their normal width if they fit onto the page, but % are scaled down if they would overflow the margins. \makeatletter \def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth \else\Gin@nat@width\fi} \makeatother \let\Oldincludegraphics\includegraphics \renewcommand{\includegraphics}[1]{\Oldincludegraphics[width=\maxwidth]{#1}} \usepackage[breaklinks=true,unicode=true,pdfborder={0 0 0}]{hyperref} \setlength{\parindent}{0pt} \setlength{\parskip}{6pt plus 2pt minus 1pt} \setcounter{secnumdepth}{0} {% endraw %} \title{{'{'}} {% if coverlogo %}\includegraphics{{'{'}}{{coverlogo}}}\\{% endif %} {{title}} } \author{{'{'}}{{author}}} \date{\today} \begin{document} \sffamily {% if title or coverlogo %} \maketitle {% endif %} {% if toc %} \tableofcontents {% endif %} {{ contents }} \end{document} {{title}} {##} {##} {##}

    {{ title }}

    Documentation

    {% if page_toc %}

    Table of Contents

      {% for entry in toc.usage.children %} {% include "default/toc.html.twig" %} {% endfor %}
    {% endif %}
    {{ contents }}
    {% for letter in 'a'..'z' %}

    {{ letter|upper}}

    {% for heading in toc if heading.name|lower|slice(0,1) == letter %} {{ heading.name }}
    {% endfor %} {% endfor %}
    article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;} audio,canvas,video{display:inline-block;*display:inline;*zoom:1;} audio:not([controls]){display:none;} html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;} a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} a:hover,a:active{outline:0;} sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;} sup{top:-0.5em;} sub{bottom:-0.25em;} img{max-width:100%;height:auto;border:0;-ms-interpolation-mode:bicubic;} button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;} button,input{*overflow:visible;line-height:normal;} button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;} button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;} input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;} input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;} textarea{overflow:auto;vertical-align:top;} body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333333;background-color:#ffffff;} a{color:#0088cc;text-decoration:none;} a:hover{color:#005580;text-decoration:underline;} .row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:20px;} .span1{width:60px;} .span2{width:140px;} .span3{width:220px;} .span4{width:300px;} .span5{width:380px;} .span6{width:460px;} .span7{width:540px;} .span8{width:620px;} .span9{width:700px;} .span10{width:780px;} .span11{width:860px;} .span12,.container{width:940px;} .offset1{margin-left:100px;} .offset2{margin-left:180px;} .offset3{margin-left:260px;} .offset4{margin-left:340px;} .offset5{margin-left:420px;} .offset6{margin-left:500px;} .offset7{margin-left:580px;} .offset8{margin-left:660px;} .offset9{margin-left:740px;} .offset10{margin-left:820px;} .offset11{margin-left:900px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid>[class*="span"]{float:left;margin-left:2.127659574%;} .row-fluid>[class*="span"]:first-child{margin-left:0;} .row-fluid .span1{width:6.382978723%;} .row-fluid .span2{width:14.89361702%;} .row-fluid .span3{width:23.404255317%;} .row-fluid .span4{width:31.914893614%;} .row-fluid .span5{width:40.425531911%;} .row-fluid .span6{width:48.93617020799999%;} .row-fluid .span7{width:57.446808505%;} .row-fluid .span8{width:65.95744680199999%;} .row-fluid .span9{width:74.468085099%;} .row-fluid .span10{width:82.97872339599999%;} .row-fluid .span11{width:91.489361693%;} .row-fluid .span12{width:99.99999998999999%;} .container{width:940px;margin-left:auto;margin-right:auto;*zoom:1;}.container:before,.container:after{display:table;content:"";} .container:after{clear:both;} .container-fluid{padding-left:20px;padding-right:20px;*zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";} .container-fluid:after{clear:both;} p{margin:0 0 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;}p small{font-size:11px;color:#999999;} .lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px;} h1,h2,h3,h4,h5,h6{margin:0;font-weight:bold;color:#333333;text-rendering:optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#999999;} h1{font-size:30px;line-height:36px;}h1 small{font-size:18px;} h2{font-size:24px;line-height:36px;}h2 small{font-size:18px;} h3{line-height:27px;font-size:18px;}h3 small{font-size:14px;} h4,h5,h6{line-height:18px;} h4{font-size:14px;}h4 small{font-size:12px;} h5{font-size:12px;} h6{font-size:11px;color:#999999;text-transform:uppercase;} .page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eeeeee;} .page-header h1{line-height:1;} ul,ol{padding:0;margin:0 0 9px 25px;} ul ul,ul ol,ol ol,ol ul{margin-bottom:0;} ul{list-style:disc;} ol{list-style:decimal;} li{line-height:18px;} ul.unstyled{margin-left:0;list-style:none;} dl{margin-bottom:18px;} dt,dd{line-height:18px;} dt{font-weight:bold;} dd{margin-left:9px;} hr{margin:18px 0;border:0;border-top:1px solid #e5e5e5;border-bottom:1px solid #ffffff;} strong{font-weight:bold;} em{font-style:italic;} .muted{color:#999999;} abbr{font-size:90%;text-transform:uppercase;border-bottom:1px dotted #ddd;cursor:help;} blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eeeeee;}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px;} blockquote small{display:block;line-height:18px;color:#999999;}blockquote small:before{content:'\2014 \00A0';} blockquote.pull-right{float:right;padding-left:0;padding-right:15px;border-left:0;border-right:5px solid #eeeeee;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;} q:before,q:after,blockquote:before,blockquote:after{content:"";} address{display:block;margin-bottom:18px;line-height:18px;font-style:normal;} small{font-size:100%;} cite{font-style:normal;} code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,"Courier New",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} code{padding:3px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;} pre{display:block;padding:8.5px;margin:0 0 9px;font-size:12px;line-height:18px;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;white-space:pre;white-space:pre-wrap;word-break:break-all;}pre.prettyprint{margin-bottom:18px;} pre code{padding:0;background-color:transparent;} form{margin:0 0 18px;} fieldset{padding:0;margin:0;border:0;} legend{display:block;width:100%;padding:0;margin-bottom:27px;font-size:19.5px;line-height:36px;color:#333333;border:0;border-bottom:1px solid #eee;} label,input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:18px;} label{display:block;margin-bottom:5px;color:#333333;} input,textarea,select,.uneditable-input{display:inline-block;width:210px;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555555;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .uneditable-textarea{width:auto;height:auto;} label input,label textarea,label select{display:block;} input[type="image"],input[type="checkbox"],input[type="radio"]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;border:0;cursor:pointer;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} input[type="file"]{padding:initial;line-height:initial;border:initial;background-color:#ffffff;background-color:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} input[type="button"],input[type="reset"],input[type="submit"]{width:auto;height:auto;} select,input[type="file"]{height:28px;*margin-top:4px;line-height:28px;} select{width:220px;background-color:#ffffff;} select[multiple],select[size]{height:auto;} input[type="image"]{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} textarea{height:auto;} input[type="hidden"]{display:none;} .radio,.checkbox{padding-left:18px;} .radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px;} .controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px;} .radio.inline,.checkbox.inline{display:inline-block;margin-bottom:0;vertical-align:middle;} .radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px;} .controls>.radio.inline:first-child,.controls>.checkbox.inline:first-child{padding-top:0;} input,textarea{-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border linear 0.2s,box-shadow linear 0.2s;-moz-transition:border linear 0.2s,box-shadow linear 0.2s;-ms-transition:border linear 0.2s,box-shadow linear 0.2s;-o-transition:border linear 0.2s,box-shadow linear 0.2s;transition:border linear 0.2s,box-shadow linear 0.2s;} input:focus,textarea:focus{border-color:rgba(82, 168, 236, 0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);outline:0;outline:thin dotted \9;} input[type="file"]:focus,input[type="checkbox"]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} .input-mini{width:60px;} .input-small{width:90px;} .input-medium{width:150px;} .input-large{width:210px;} .input-xlarge{width:270px;} .input-xxlarge{width:530px;} input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{float:none;margin-left:0;} input.span1,textarea.span1,.uneditable-input.span1{width:50px;} input.span2,textarea.span2,.uneditable-input.span2{width:130px;} input.span3,textarea.span3,.uneditable-input.span3{width:210px;} input.span4,textarea.span4,.uneditable-input.span4{width:290px;} input.span5,textarea.span5,.uneditable-input.span5{width:370px;} input.span6,textarea.span6,.uneditable-input.span6{width:450px;} input.span7,textarea.span7,.uneditable-input.span7{width:530px;} input.span8,textarea.span8,.uneditable-input.span8{width:610px;} input.span9,textarea.span9,.uneditable-input.span9{width:690px;} input.span10,textarea.span10,.uneditable-input.span10{width:770px;} input.span11,textarea.span11,.uneditable-input.span11{width:850px;} input.span12,textarea.span12,.uneditable-input.span12{width:930px;} input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{background-color:#f5f5f5;border-color:#ddd;cursor:not-allowed;} .control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853;} .control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;border-color:#c09853;}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:0 0 6px #dbc59e;-moz-box-shadow:0 0 6px #dbc59e;box-shadow:0 0 6px #dbc59e;} .control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853;} .control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48;} .control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;border-color:#b94a48;}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:0 0 6px #d59392;-moz-box-shadow:0 0 6px #d59392;box-shadow:0 0 6px #d59392;} .control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48;} .control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847;} .control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;border-color:#468847;}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:0 0 6px #7aba7b;-moz-box-shadow:0 0 6px #7aba7b;box-shadow:0 0 6px #7aba7b;} .control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847;} input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b;}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;} .form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #ddd;} .uneditable-input{display:block;background-color:#ffffff;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;} :-moz-placeholder{color:#999999;} ::-webkit-input-placeholder{color:#999999;} .help-block{margin-top:5px;margin-bottom:0;color:#999999;} .help-inline{display:inline-block;*display:inline;*zoom:1;margin-bottom:9px;vertical-align:middle;padding-left:5px;} .input-prepend,.input-append{margin-bottom:5px;*zoom:1;}.input-prepend:before,.input-append:before,.input-prepend:after,.input-append:after{display:table;content:"";} .input-prepend:after,.input-append:after{clear:both;} .input-prepend input,.input-append input,.input-prepend .uneditable-input,.input-append .uneditable-input{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}.input-prepend input:focus,.input-append input:focus,.input-prepend .uneditable-input:focus,.input-append .uneditable-input:focus{position:relative;z-index:2;} .input-prepend .uneditable-input,.input-append .uneditable-input{border-left-color:#ccc;} .input-prepend .add-on,.input-append .add-on{float:left;display:block;width:auto;min-width:16px;height:18px;margin-right:-1px;padding:4px 5px;font-weight:normal;line-height:18px;color:#999999;text-align:center;text-shadow:0 1px 0 #ffffff;background-color:#f5f5f5;border:1px solid #ccc;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} .input-prepend .active,.input-append .active{background-color:#a9dba9;border-color:#46a546;} .input-prepend .add-on{*margin-top:1px;} .input-append input,.input-append .uneditable-input{float:left;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} .input-append .uneditable-input{border-right-color:#ccc;} .input-append .add-on{margin-right:0;margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;} .input-append input:first-child{*margin-left:-160px;}.input-append input:first-child+.add-on{*margin-left:-21px;} .search-query{padding-left:14px;padding-right:14px;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px;} .form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input{display:inline-block;margin-bottom:0;} .form-search label,.form-inline label,.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{display:inline-block;} .form-search .input-append .add-on,.form-inline .input-prepend .add-on,.form-search .input-append .add-on,.form-inline .input-prepend .add-on{vertical-align:middle;} .control-group{margin-bottom:9px;} .form-horizontal legend+.control-group{margin-top:18px;-webkit-margin-top-collapse:separate;} .form-horizontal .control-group{margin-bottom:18px;*zoom:1;}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";} .form-horizontal .control-group:after{clear:both;} .form-horizontal .control-group>label{float:left;width:140px;padding-top:5px;text-align:right;} .form-horizontal .controls{margin-left:160px;} .form-horizontal .form-actions{padding-left:160px;} table{max-width:100%;border-collapse:collapse;border-spacing:0;} .table{width:100%;margin-bottom:18px;}.table th,.table td{padding:8px;line-height:18px;text-align:left;border-top:1px solid #ddd;} .table th{font-weight:bold;vertical-align:bottom;} .table td{vertical-align:top;} .table thead:first-child tr th,.table thead:first-child tr td{border-top:0;} .table tbody+tbody{border-top:2px solid #ddd;} .table-condensed th,.table-condensed td{padding:4px 5px;} .table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapsed;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th+th,.table-bordered td+td,.table-bordered th+td,.table-bordered td+th{border-left:1px solid #ddd;} .table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0;} .table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;border-radius:4px 0 0 0;} .table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0;} .table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;} .table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0;} .table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9;} table .span1{float:none;width:44px;margin-left:0;} table .span2{float:none;width:124px;margin-left:0;} table .span3{float:none;width:204px;margin-left:0;} table .span4{float:none;width:284px;margin-left:0;} table .span5{float:none;width:364px;margin-left:0;} table .span6{float:none;width:444px;margin-left:0;} table .span7{float:none;width:524px;margin-left:0;} table .span8{float:none;width:604px;margin-left:0;} table .span9{float:none;width:684px;margin-left:0;} table .span10{float:none;width:764px;margin-left:0;} table .span11{float:none;width:844px;margin-left:0;} table .span12{float:none;width:924px;margin-left:0;} [class^="icon-"]{display:inline-block;width:14px;height:14px;vertical-align:text-top;background-image:url(../../../../build/api/img/glyphicons-halflings.png);background-position:14px 14px;background-repeat:no-repeat;*margin-right:.3em;}[class^="icon-"]:last-child{*margin-left:0;} .icon-white{background-image:url(../../../../build/api/img/glyphicons-halflings-white.png);} .icon-glass{background-position:0 0;} .icon-music{background-position:-24px 0;} .icon-search{background-position:-48px 0;} .icon-envelope{background-position:-72px 0;} .icon-heart{background-position:-96px 0;} .icon-star{background-position:-120px 0;} .icon-star-empty{background-position:-144px 0;} .icon-user{background-position:-168px 0;} .icon-film{background-position:-192px 0;} .icon-th-large{background-position:-216px 0;} .icon-th{background-position:-240px 0;} .icon-th-list{background-position:-264px 0;} .icon-ok{background-position:-288px 0;} .icon-remove{background-position:-312px 0;} .icon-zoom-in{background-position:-336px 0;} .icon-zoom-out{background-position:-360px 0;} .icon-off{background-position:-384px 0;} .icon-signal{background-position:-408px 0;} .icon-cog{background-position:-432px 0;} .icon-trash{background-position:-456px 0;} .icon-home{background-position:0 -24px;} .icon-file{background-position:-24px -24px;} .icon-time{background-position:-48px -24px;} .icon-road{background-position:-72px -24px;} .icon-download-alt{background-position:-96px -24px;} .icon-download{background-position:-120px -24px;} .icon-upload{background-position:-144px -24px;} .icon-inbox{background-position:-168px -24px;} .icon-play-circle{background-position:-192px -24px;} .icon-repeat{background-position:-216px -24px;} .icon-refresh{background-position:-240px -24px;} .icon-list-alt{background-position:-264px -24px;} .icon-lock{background-position:-287px -24px;} .icon-flag{background-position:-312px -24px;} .icon-headphones{background-position:-336px -24px;} .icon-volume-off{background-position:-360px -24px;} .icon-volume-down{background-position:-384px -24px;} .icon-volume-up{background-position:-408px -24px;} .icon-qrcode{background-position:-432px -24px;} .icon-barcode{background-position:-456px -24px;} .icon-tag{background-position:0 -48px;} .icon-tags{background-position:-25px -48px;} .icon-book{background-position:-48px -48px;} .icon-bookmark{background-position:-72px -48px;} .icon-print{background-position:-96px -48px;} .icon-camera{background-position:-120px -48px;} .icon-font{background-position:-144px -48px;} .icon-bold{background-position:-167px -48px;} .icon-italic{background-position:-192px -48px;} .icon-text-height{background-position:-216px -48px;} .icon-text-width{background-position:-240px -48px;} .icon-align-left{background-position:-264px -48px;} .icon-align-center{background-position:-288px -48px;} .icon-align-right{background-position:-312px -48px;} .icon-align-justify{background-position:-336px -48px;} .icon-list{background-position:-360px -48px;} .icon-indent-left{background-position:-384px -48px;} .icon-indent-right{background-position:-408px -48px;} .icon-facetime-video{background-position:-432px -48px;} .icon-picture{background-position:-456px -48px;} .icon-pencil{background-position:0 -72px;} .icon-map-marker{background-position:-24px -72px;} .icon-adjust{background-position:-48px -72px;} .icon-tint{background-position:-72px -72px;} .icon-edit{background-position:-96px -72px;} .icon-share{background-position:-120px -72px;} .icon-check{background-position:-144px -72px;} .icon-move{background-position:-168px -72px;} .icon-step-backward{background-position:-192px -72px;} .icon-fast-backward{background-position:-216px -72px;} .icon-backward{background-position:-240px -72px;} .icon-play{background-position:-264px -72px;} .icon-pause{background-position:-288px -72px;} .icon-stop{background-position:-312px -72px;} .icon-forward{background-position:-336px -72px;} .icon-fast-forward{background-position:-360px -72px;} .icon-step-forward{background-position:-384px -72px;} .icon-eject{background-position:-408px -72px;} .icon-chevron-left{background-position:-432px -72px;} .icon-chevron-right{background-position:-456px -72px;} .icon-plus-sign{background-position:0 -96px;} .icon-minus-sign{background-position:-24px -96px;} .icon-remove-sign{background-position:-48px -96px;} .icon-ok-sign{background-position:-72px -96px;} .icon-question-sign{background-position:-96px -96px;} .icon-info-sign{background-position:-120px -96px;} .icon-screenshot{background-position:-144px -96px;} .icon-remove-circle{background-position:-168px -96px;} .icon-ok-circle{background-position:-192px -96px;} .icon-ban-circle{background-position:-216px -96px;} .icon-arrow-left{background-position:-240px -96px;} .icon-arrow-right{background-position:-264px -96px;} .icon-arrow-up{background-position:-289px -96px;} .icon-arrow-down{background-position:-312px -96px;} .icon-share-alt{background-position:-336px -96px;} .icon-resize-full{background-position:-360px -96px;} .icon-resize-small{background-position:-384px -96px;} .icon-plus{background-position:-408px -96px;} .icon-minus{background-position:-433px -96px;} .icon-asterisk{background-position:-456px -96px;} .icon-exclamation-sign{background-position:0 -120px;} .icon-gift{background-position:-24px -120px;} .icon-leaf{background-position:-48px -120px;} .icon-fire{background-position:-72px -120px;} .icon-eye-open{background-position:-96px -120px;} .icon-eye-close{background-position:-120px -120px;} .icon-warning-sign{background-position:-144px -120px;} .icon-plane{background-position:-168px -120px;} .icon-calendar{background-position:-192px -120px;} .icon-random{background-position:-216px -120px;} .icon-comment{background-position:-240px -120px;} .icon-magnet{background-position:-264px -120px;} .icon-chevron-up{background-position:-288px -120px;} .icon-chevron-down{background-position:-313px -119px;} .icon-retweet{background-position:-336px -120px;} .icon-shopping-cart{background-position:-360px -120px;} .icon-folder-close{background-position:-384px -120px;} .icon-folder-open{background-position:-408px -120px;} .icon-resize-vertical{background-position:-432px -119px;} .icon-resize-horizontal{background-position:-456px -118px;} .dropdown{position:relative;} .dropdown-toggle{*margin-bottom:-3px;} .dropdown-toggle:active,.open .dropdown-toggle{outline:0;} .caret{display:inline-block;width:0;height:0;text-indent:-99999px;*text-indent:0;vertical-align:top;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000000;opacity:0.3;filter:alpha(opacity=30);content:"\2193";} .dropdown .caret{margin-top:8px;margin-left:2px;} .dropdown:hover .caret,.open.dropdown .caret{opacity:1;filter:alpha(opacity=100);} .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;float:left;display:none;min-width:160px;max-width:220px;_width:160px;padding:4px 0;margin:0;list-style:none;background-color:#ffffff;border-color:#ccc;border-color:rgba(0, 0, 0, 0.2);border-style:solid;border-width:1px;-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;*border-right-width:2px;*border-bottom-width:2px;}.dropdown-menu.bottom-up{top:auto;bottom:100%;margin-bottom:2px;} .dropdown-menu .divider{height:1px;margin:5px 1px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;*width:100%;*margin:-5px 0 5px;} .dropdown-menu a{display:block;padding:3px 15px;clear:both;font-weight:normal;line-height:18px;color:#555555;white-space:nowrap;} .dropdown-menu li>a:hover,.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#ffffff;text-decoration:none;background-color:#0088cc;} .dropdown.open{*z-index:1000;}.dropdown.open .dropdown-toggle{color:#ffffff;background:#ccc;background:rgba(0, 0, 0, 0.3);} .dropdown.open .dropdown-menu{display:block;} .typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #eee;border:1px solid rgba(0, 0, 0, 0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);} .fade{-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-ms-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;opacity:0;}.fade.in{opacity:1;} .collapse{-webkit-transition:height 0.35s ease;-moz-transition:height 0.35s ease;-ms-transition:height 0.35s ease;-o-transition:height 0.35s ease;transition:height 0.35s ease;position:relative;overflow:hidden;height:0;}.collapse.in{height:auto;} .close{float:right;font-size:20px;font-weight:bold;line-height:18px;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20);}.close:hover{color:#000000;text-decoration:none;opacity:0.4;filter:alpha(opacity=40);cursor:pointer;} .btn{display:inline-block;padding:4px 10px 4px;font-size:13px;line-height:18px;color:#333333;text-align:center;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#fafafa;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);background-image:-ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);cursor:pointer;*margin-left:.3em;}.btn:first-child{*margin-left:0;} .btn:hover{color:#333333;text-decoration:none;background-color:#e6e6e6;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-ms-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;} .btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} .btn.active,.btn:active{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);background-color:#e6e6e6;background-color:#d9d9d9 \9;color:rgba(0, 0, 0, 0.5);outline:0;} .btn.disabled,.btn[disabled]{cursor:default;background-image:none;background-color:#e6e6e6;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .btn-large{padding:9px 14px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} .btn-large .icon{margin-top:1px;} .btn-small{padding:5px 9px;font-size:11px;line-height:16px;} .btn-small .icon{margin-top:-1px;} .btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover{text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);color:#ffffff;} .btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active{color:rgba(255, 255, 255, 0.75);} .btn-primary{background-color:#006dcc;background-image:-moz-linear-gradient(top, #0088cc, #0044cc);background-image:-ms-linear-gradient(top, #0088cc, #0044cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));background-image:-webkit-linear-gradient(top, #0088cc, #0044cc);background-image:-o-linear-gradient(top, #0088cc, #0044cc);background-image:linear-gradient(top, #0088cc, #0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#0044cc;} .btn-primary:active,.btn-primary.active{background-color:#003399 \9;} .btn-warning{background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-ms-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(top, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406;} .btn-warning:active,.btn-warning.active{background-color:#c67605 \9;} .btn-danger{background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-ms-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(top, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f;} .btn-danger:active,.btn-danger.active{background-color:#942a25 \9;} .btn-success{background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-ms-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(top, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351;} .btn-success:active,.btn-success.active{background-color:#408140 \9;} .btn-info{background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-ms-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(top, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4;} .btn-info:active,.btn-info.active{background-color:#24748c \9;} button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;} button.btn.large,input[type="submit"].btn.large{*padding-top:7px;*padding-bottom:7px;} button.btn.small,input[type="submit"].btn.small{*padding-top:3px;*padding-bottom:3px;} .btn-group{position:relative;*zoom:1;*margin-left:.3em;}.btn-group:before,.btn-group:after{display:table;content:"";} .btn-group:after{clear:both;} .btn-group:first-child{*margin-left:0;} .btn-group+.btn-group{margin-left:5px;} .btn-toolbar{margin-top:9px;margin-bottom:9px;}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1;} .btn-group .btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} .btn-group .btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;} .btn-group .btn:last-child,.btn-group .dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;} .btn-group .btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;} .btn-group .btn.large:last-child,.btn-group .large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;} .btn-group .btn:hover,.btn-group .btn:focus,.btn-group .btn:active,.btn-group .btn.active{z-index:2;} .btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;} .btn-group .dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);*padding-top:5px;*padding-bottom:5px;} .btn-group.open{*z-index:1000;}.btn-group.open .dropdown-menu{display:block;margin-top:1px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} .btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);} .btn .caret{margin-top:7px;margin-left:0;} .btn:hover .caret,.open.btn-group .caret{opacity:1;filter:alpha(opacity=100);} .btn-primary .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret{border-top-color:#ffffff;opacity:0.75;filter:alpha(opacity=75);} .btn-small .caret{margin-top:4px;} .alert{padding:8px 35px 8px 14px;margin-bottom:18px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .alert,.alert-heading{color:#c09853;} .alert .close{position:relative;top:-2px;right:-21px;line-height:18px;} .alert-success{background-color:#dff0d8;border-color:#d6e9c6;} .alert-success,.alert-success .alert-heading{color:#468847;} .alert-danger,.alert-error{background-color:#f2dede;border-color:#eed3d7;} .alert-danger,.alert-error,.alert-danger .alert-heading,.alert-error .alert-heading{color:#b94a48;} .alert-info{background-color:#d9edf7;border-color:#bce8f1;} .alert-info,.alert-info .alert-heading{color:#3a87ad;} .alert-block{padding-top:14px;padding-bottom:14px;} .alert-block>p,.alert-block>ul{margin-bottom:0;} .alert-block p+p{margin-top:5px;} .nav{margin-left:0;margin-bottom:18px;list-style:none;} .nav>li>a{display:block;} .nav>li>a:hover{text-decoration:none;background-color:#eeeeee;} .nav-list{padding-left:14px;padding-right:14px;margin-bottom:0;} .nav-list>li>a,.nav-list .nav-header{display:block;padding:3px 15px;margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);} .nav-list .nav-header{font-size:11px;font-weight:bold;line-height:18px;color:#999999;text-transform:uppercase;} .nav-list>li+.nav-header{margin-top:9px;} .nav-list .active>a,.nav-list .active>a:hover{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.2);background-color:#0088cc;} .nav-list [class^="icon-"]{margin-right:2px;} .nav-tabs,.nav-pills{*zoom:1;}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:"";} .nav-tabs:after,.nav-pills:after{clear:both;} .nav-tabs>li,.nav-pills>li{float:left;} .nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px;} .nav-tabs{border-bottom:1px solid #ddd;} .nav-tabs>li{margin-bottom:-1px;} .nav-tabs>li>a{padding-top:9px;padding-bottom:9px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd;} .nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555555;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;} .nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} .nav-pills .active>a,.nav-pills .active>a:hover{color:#ffffff;background-color:#0088cc;} .nav-stacked>li{float:none;} .nav-stacked>li>a{margin-right:0;} .nav-tabs.nav-stacked{border-bottom:0;} .nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} .nav-tabs.nav-stacked>li:first-child>a{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;} .nav-tabs.nav-stacked>li:last-child>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;} .nav-tabs.nav-stacked>li>a:hover{border-color:#ddd;z-index:2;} .nav-pills.nav-stacked>li>a{margin-bottom:3px;} .nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px;} .nav-tabs .dropdown-menu,.nav-pills .dropdown-menu{margin-top:1px;border-width:1px;} .nav-pills .dropdown-menu{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .nav-tabs .dropdown-toggle .caret,.nav-pills .dropdown-toggle .caret{border-top-color:#0088cc;margin-top:6px;} .nav-tabs .dropdown-toggle:hover .caret,.nav-pills .dropdown-toggle:hover .caret{border-top-color:#005580;} .nav-tabs .active .dropdown-toggle .caret,.nav-pills .active .dropdown-toggle .caret{border-top-color:#333333;} .nav>.dropdown.active>a:hover{color:#000000;cursor:pointer;} .nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>.open.active>a:hover{color:#ffffff;background-color:#999999;border-color:#999999;} .nav .open .caret,.nav .open.active .caret,.nav .open a:hover .caret{border-top-color:#ffffff;opacity:1;filter:alpha(opacity=100);} .tabs-stacked .open>a:hover{border-color:#999999;} .tabbable{*zoom:1;}.tabbable:before,.tabbable:after{display:table;content:"";} .tabbable:after{clear:both;} .tabs-below .nav-tabs,.tabs-right .nav-tabs,.tabs-left .nav-tabs{border-bottom:0;} .tab-content>.tab-pane,.pill-content>.pill-pane{display:none;} .tab-content>.active,.pill-content>.active{display:block;} .tabs-below .nav-tabs{border-top:1px solid #ddd;} .tabs-below .nav-tabs>li{margin-top:-1px;margin-bottom:0;} .tabs-below .nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.tabs-below .nav-tabs>li>a:hover{border-bottom-color:transparent;border-top-color:#ddd;} .tabs-below .nav-tabs .active>a,.tabs-below .nav-tabs .active>a:hover{border-color:transparent #ddd #ddd #ddd;} .tabs-left .nav-tabs>li,.tabs-right .nav-tabs>li{float:none;} .tabs-left .nav-tabs>li>a,.tabs-right .nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px;} .tabs-left .nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd;} .tabs-left .nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;} .tabs-left .nav-tabs>li>a:hover{border-color:#eeeeee #dddddd #eeeeee #eeeeee;} .tabs-left .nav-tabs .active>a,.tabs-left .nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#ffffff;} .tabs-right .nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd;} .tabs-right .nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;} .tabs-right .nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #eeeeee #dddddd;} .tabs-right .nav-tabs .active>a,.tabs-right .nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#ffffff;} .navbar{overflow:visible;margin-bottom:18px;} .navbar-inner{padding-left:20px;padding-right:20px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);} .btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);border-color:#222222 #222222 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);}.btn-navbar:hover,.btn-navbar:active,.btn-navbar.active,.btn-navbar.disabled,.btn-navbar[disabled]{background-color:#222222;} .btn-navbar:active,.btn-navbar.active{background-color:#080808 \9;} .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);-moz-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);} .btn-navbar .icon-bar+.icon-bar{margin-top:3px;} .nav-collapse.collapse{height:auto;} .navbar .brand:hover{text-decoration:none;} .navbar .brand{float:left;display:block;padding:8px 20px 12px;margin-left:-20px;font-size:20px;font-weight:200;line-height:1;color:#ffffff;} .navbar .navbar-text{margin-bottom:0;line-height:40px;color:#999999;}.navbar .navbar-text a:hover{color:#ffffff;background-color:transparent;} .navbar .btn,.navbar .btn-group{margin-top:5px;} .navbar .btn-group .btn{margin-top:0;} .navbar-form{margin-bottom:0;*zoom:1;}.navbar-form:before,.navbar-form:after{display:table;content:"";} .navbar-form:after{clear:both;} .navbar-form input,.navbar-form select{display:inline-block;margin-top:5px;margin-bottom:0;} .navbar-form .radio,.navbar-form .checkbox{margin-top:5px;} .navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px;} .navbar-search{position:relative;float:left;margin-top:6px;margin-bottom:0;}.navbar-search .search-query{padding:4px 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;color:#ffffff;color:rgba(255, 255, 255, 0.75);background:#666;background:rgba(255, 255, 255, 0.3);border:1px solid #111;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none;}.navbar-search .search-query :-moz-placeholder{color:#eeeeee;} .navbar-search .search-query::-webkit-input-placeholder{color:#eeeeee;} .navbar-search .search-query:hover{color:#ffffff;background-color:#999999;background-color:rgba(255, 255, 255, 0.5);} .navbar-search .search-query:focus,.navbar-search .search-query.focused{padding:5px 10px;color:#333333;text-shadow:0 1px 0 #ffffff;background-color:#ffffff;border:0;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);outline:0;} .navbar-fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030;} .navbar-fixed-top .navbar-inner{padding-left:0;padding-right:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} .navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0;} .navbar .nav.pull-right{float:right;} .navbar .nav>li{display:block;float:left;} .navbar .nav>li>a{float:none;padding:10px 10px 11px;line-height:19px;color:#999999;text-decoration:none;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);} .navbar .nav>li>a:hover{background-color:transparent;color:#ffffff;text-decoration:none;} .navbar .nav .active>a,.navbar .nav .active>a:hover{color:#ffffff;text-decoration:none;background-color:#222222;background-color:rgba(0, 0, 0, 0.5);} .navbar .divider-vertical{height:40px;width:1px;margin:0 9px;overflow:hidden;background-color:#222222;border-right:1px solid #333333;} .navbar .nav.pull-right{margin-left:10px;margin-right:0;} .navbar .dropdown-menu{margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.navbar .dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0, 0, 0, 0.2);position:absolute;top:-7px;left:9px;} .navbar .dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:10px;} .navbar .nav .dropdown-toggle .caret,.navbar .nav .open.dropdown .caret{border-top-color:#ffffff;} .navbar .nav .active .caret{opacity:1;filter:alpha(opacity=100);} .navbar .nav .open>.dropdown-toggle,.navbar .nav .active>.dropdown-toggle,.navbar .nav .open.active>.dropdown-toggle{background-color:transparent;} .navbar .nav .active>.dropdown-toggle:hover{color:#ffffff;} .navbar .nav.pull-right .dropdown-menu{left:auto;right:0;}.navbar .nav.pull-right .dropdown-menu:before{left:auto;right:12px;} .navbar .nav.pull-right .dropdown-menu:after{left:auto;right:13px;} .breadcrumb{padding:7px 14px;margin:0 0 18px;background-color:#fbfbfb;background-image:-moz-linear-gradient(top, #ffffff, #f5f5f5);background-image:-ms-linear-gradient(top, #ffffff, #f5f5f5);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5));background-image:-webkit-linear-gradient(top, #ffffff, #f5f5f5);background-image:-o-linear-gradient(top, #ffffff, #f5f5f5);background-image:linear-gradient(top, #ffffff, #f5f5f5);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;}.breadcrumb li{display:inline;text-shadow:0 1px 0 #ffffff;} .breadcrumb .divider{padding:0 5px;color:#999999;} .breadcrumb .active a{color:#333333;} .pagination{height:36px;margin:18px 0;} .pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);} .pagination li{display:inline;} .pagination a{float:left;padding:0 14px;line-height:34px;text-decoration:none;border:1px solid #ddd;border-left-width:0;} .pagination a:hover,.pagination .active a{background-color:#f5f5f5;} .pagination .active a{color:#999999;cursor:default;} .pagination .disabled a,.pagination .disabled a:hover{color:#999999;background-color:transparent;cursor:default;} .pagination li:first-child a{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} .pagination li:last-child a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;} .pagination-centered{text-align:center;} .pagination-right{text-align:right;} .pager{margin-left:0;margin-bottom:18px;list-style:none;text-align:center;*zoom:1;}.pager:before,.pager:after{display:table;content:"";} .pager:after{clear:both;} .pager li{display:inline;} .pager a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;} .pager a:hover{text-decoration:none;background-color:#f5f5f5;} .pager .next a{float:right;} .pager .previous a{float:left;} .modal-open .dropdown-menu{z-index:2050;} .modal-open .dropdown.open{*z-index:2050;} .modal-open .popover{z-index:2060;} .modal-open .tooltip{z-index:2070;} .modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000;}.modal-backdrop.fade{opacity:0;} .modal-backdrop,.modal-backdrop.fade.in{opacity:0.8;filter:alpha(opacity=80);} .modal{position:fixed;top:50%;left:50%;z-index:1050;max-height:500px;overflow:auto;width:560px;margin:-250px 0 0 -280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-ms-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;} .modal.fade.in{top:50%;} .modal-header{padding:9px 15px;border-bottom:1px solid #eee;}.modal-header .close{margin-top:2px;} .modal-body{padding:15px;} .modal-footer{padding:14px 15px 15px;margin-bottom:0;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;*zoom:1;}.modal-footer:before,.modal-footer:after{display:table;content:"";} .modal-footer:after{clear:both;} .modal-footer .btn{float:right;margin-left:5px;margin-bottom:0;} .tooltip{position:absolute;z-index:1020;display:block;visibility:visible;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.8;filter:alpha(opacity=80);} .tooltip.top{margin-top:-2px;} .tooltip.right{margin-left:2px;} .tooltip.bottom{margin-top:2px;} .tooltip.left{margin-left:-2px;} .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;} .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;} .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;} .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;} .tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .tooltip-arrow{position:absolute;width:0;height:0;} .popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px;}.popover.top{margin-top:-5px;} .popover.right{margin-left:5px;} .popover.bottom{margin-top:5px;} .popover.left{margin-left:-5px;} .popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;} .popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;} .popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;} .popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;} .popover .arrow{position:absolute;width:0;height:0;} .popover-inner{padding:3px;width:280px;overflow:hidden;background:#000000;background:rgba(0, 0, 0, 0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);} .popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;} .popover-content{padding:14px;background-color:#ffffff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0;} .thumbnails{margin-left:-20px;list-style:none;*zoom:1;}.thumbnails:before,.thumbnails:after{display:table;content:"";} .thumbnails:after{clear:both;} .thumbnails>li{float:left;margin:0 0 18px 20px;} .thumbnail{display:block;padding:4px;line-height:1;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);} a.thumbnail:hover{border-color:#0088cc;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);} .thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto;} .thumbnail .caption{padding:9px;} .label{padding:1px 3px 2px;font-size:9.75px;font-weight:bold;color:#ffffff;text-transform:uppercase;background-color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .label-important{background-color:#b94a48;} .label-warning{background-color:#f89406;} .label-success{background-color:#468847;} .label-info{background-color:#3a87ad;} @-webkit-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@-moz-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}.progress{overflow:hidden;height:18px;margin-bottom:18px;background-color:#f7f7f7;background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-ms-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(top, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .progress .bar{width:0%;height:18px;color:#ffffff;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-ms-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(top, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width 0.6s ease;-moz-transition:width 0.6s ease;-ms-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;} .progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px;} .progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite;} .progress-danger .bar{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-ms-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(top, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);} .progress-danger.progress-striped .bar{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);} .progress-success .bar{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-ms-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(top, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);} .progress-success.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);} .progress-info .bar{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-ms-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(top, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);} .progress-info.progress-striped .bar{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);} .accordion{margin-bottom:18px;} .accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .accordion-heading{border-bottom:0;} .accordion-heading .accordion-toggle{display:block;padding:8px 15px;} .accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;} .carousel{position:relative;margin-bottom:18px;line-height:1;} .carousel-inner{overflow:hidden;width:100%;position:relative;} .carousel .item{display:none;position:relative;-webkit-transition:0.6s ease-in-out left;-moz-transition:0.6s ease-in-out left;-ms-transition:0.6s ease-in-out left;-o-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left;} .carousel .item>img{display:block;line-height:1;} .carousel .active,.carousel .next,.carousel .prev{display:block;} .carousel .active{left:0;} .carousel .next,.carousel .prev{position:absolute;top:0;width:100%;} .carousel .next{left:100%;} .carousel .prev{left:-100%;} .carousel .next.left,.carousel .prev.right{left:0;} .carousel .active.left{left:-100%;} .carousel .active.right{left:100%;} .carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#ffffff;text-align:center;background:#222222;border:3px solid #ffffff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:0.5;filter:alpha(opacity=50);}.carousel-control.right{left:auto;right:15px;} .carousel-control:hover{color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90);} .carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:10px 15px 5px;background:#333333;background:rgba(0, 0, 0, 0.75);} .carousel-caption h4,.carousel-caption p{color:#ffffff;} .hero-unit{padding:60px;margin-bottom:30px;background-color:#f5f5f5;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;} .hero-unit p{font-size:18px;font-weight:200;line-height:27px;} .pull-right{float:right;} .pull-left{float:left;} .hide{display:none;} .show{display:block;} .invisible{visibility:hidden;} .hidden{display:none;visibility:hidden;} @media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0);} .page-header h1 small{display:block;line-height:18px;} input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;} .input-prepend input[class*="span"],.input-append input[class*="span"]{width:auto;} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc;} .form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left;} .form-horizontal .controls{margin-left:0;} .form-horizontal .control-list{padding-top:0;} .form-horizontal .form-actions{padding-left:10px;padding-right:10px;} .modal{position:absolute;top:10px;left:10px;right:10px;width:auto;margin:0;}.modal.fade.in{top:auto;} .modal-header .close{padding:10px;margin:-10px;} .carousel-caption{position:static;}}@media (max-width:768px){.container{width:auto;padding:0 20px;} .row-fluid{width:100%;} .row{margin-left:0;} .row>[class*="span"],.row-fluid>[class*="span"]{float:none;display:block;width:auto;margin:0;}}@media (min-width:768px) and (max-width:980px){.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:20px;} .span1{width:42px;} .span2{width:104px;} .span3{width:166px;} .span4{width:228px;} .span5{width:290px;} .span6{width:352px;} .span7{width:414px;} .span8{width:476px;} .span9{width:538px;} .span10{width:600px;} .span11{width:662px;} .span12,.container{width:724px;} .offset1{margin-left:82px;} .offset2{margin-left:144px;} .offset3{margin-left:206px;} .offset4{margin-left:268px;} .offset5{margin-left:330px;} .offset6{margin-left:392px;} .offset7{margin-left:454px;} .offset8{margin-left:516px;} .offset9{margin-left:578px;} .offset10{margin-left:640px;} .offset11{margin-left:702px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid>[class*="span"]{float:left;margin-left:2.762430939%;} .row-fluid>[class*="span"]:first-child{margin-left:0;} .row-fluid .span1{width:5.801104972%;} .row-fluid .span2{width:14.364640883%;} .row-fluid .span3{width:22.928176794%;} .row-fluid .span4{width:31.491712705%;} .row-fluid .span5{width:40.055248616%;} .row-fluid .span6{width:48.618784527%;} .row-fluid .span7{width:57.182320438000005%;} .row-fluid .span8{width:65.74585634900001%;} .row-fluid .span9{width:74.30939226%;} .row-fluid .span10{width:82.87292817100001%;} .row-fluid .span11{width:91.436464082%;} .row-fluid .span12{width:99.999999993%;} input.span1,textarea.span1,.uneditable-input.span1{width:32px;} input.span2,textarea.span2,.uneditable-input.span2{width:94px;} input.span3,textarea.span3,.uneditable-input.span3{width:156px;} input.span4,textarea.span4,.uneditable-input.span4{width:218px;} input.span5,textarea.span5,.uneditable-input.span5{width:280px;} input.span6,textarea.span6,.uneditable-input.span6{width:342px;} input.span7,textarea.span7,.uneditable-input.span7{width:404px;} input.span8,textarea.span8,.uneditable-input.span8{width:466px;} input.span9,textarea.span9,.uneditable-input.span9{width:528px;} input.span10,textarea.span10,.uneditable-input.span10{width:590px;} input.span11,textarea.span11,.uneditable-input.span11{width:652px;} input.span12,textarea.span12,.uneditable-input.span12{width:714px;}}@media (max-width:980px){body{padding-top:0;} .navbar-fixed-top{position:static;margin-bottom:18px;} .navbar-fixed-top .navbar-inner{padding:5px;} .navbar .container{width:auto;padding:0;} .navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px;} .navbar .nav-collapse{clear:left;} .navbar .nav{float:none;margin:0 0 9px;} .navbar .nav>li{float:none;} .navbar .nav>li>a{margin-bottom:2px;} .navbar .nav>.divider-vertical{display:none;} .navbar .nav>li>a,.navbar .dropdown-menu a{padding:6px 15px;font-weight:bold;color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .navbar .dropdown-menu li+li a{margin-bottom:2px;} .navbar .nav>li>a:hover,.navbar .dropdown-menu a:hover{background-color:#222222;} .navbar .dropdown-menu{position:static;top:auto;left:auto;float:none;display:block;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .navbar .dropdown-menu:before,.navbar .dropdown-menu:after{display:none;} .navbar .dropdown-menu .divider{display:none;} .navbar-form,.navbar-search{float:none;padding:9px 15px;margin:9px 0;border-top:1px solid #222222;border-bottom:1px solid #222222;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);} .navbar .nav.pull-right{float:none;margin-left:0;} .navbar-static .navbar-inner{padding-left:10px;padding-right:10px;} .btn-navbar{display:block;} .nav-collapse{overflow:hidden;height:0;}}@media (min-width:980px){.nav-collapse.collapse{height:auto !important;}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1;}.row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:30px;} .span1{width:70px;} .span2{width:170px;} .span3{width:270px;} .span4{width:370px;} .span5{width:470px;} .span6{width:570px;} .span7{width:670px;} .span8{width:770px;} .span9{width:870px;} .span10{width:970px;} .span11{width:1070px;} .span12,.container{width:1170px;} .offset1{margin-left:130px;} .offset2{margin-left:230px;} .offset3{margin-left:330px;} .offset4{margin-left:430px;} .offset5{margin-left:530px;} .offset6{margin-left:630px;} .offset7{margin-left:730px;} .offset8{margin-left:830px;} .offset9{margin-left:930px;} .offset10{margin-left:1030px;} .offset11{margin-left:1130px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid>[class*="span"]{float:left;margin-left:2.564102564%;} .row-fluid>[class*="span"]:first-child{margin-left:0;} .row-fluid .span1{width:5.982905983%;} .row-fluid .span2{width:14.529914530000001%;} .row-fluid .span3{width:23.076923077%;} .row-fluid .span4{width:31.623931624%;} .row-fluid .span5{width:40.170940171000005%;} .row-fluid .span6{width:48.717948718%;} .row-fluid .span7{width:57.264957265%;} .row-fluid .span8{width:65.81196581200001%;} .row-fluid .span9{width:74.358974359%;} .row-fluid .span10{width:82.905982906%;} .row-fluid .span11{width:91.45299145300001%;} .row-fluid .span12{width:100%;} input.span1,textarea.span1,.uneditable-input.span1{width:60px;} input.span2,textarea.span2,.uneditable-input.span2{width:160px;} input.span3,textarea.span3,.uneditable-input.span3{width:260px;} input.span4,textarea.span4,.uneditable-input.span4{width:360px;} input.span5,textarea.span5,.uneditable-input.span5{width:460px;} input.span6,textarea.span6,.uneditable-input.span6{width:560px;} input.span7,textarea.span7,.uneditable-input.span7{width:660px;} input.span8,textarea.span8,.uneditable-input.span8{width:760px;} input.span9,textarea.span9,.uneditable-input.span9{width:860px;} input.span10,textarea.span10,.uneditable-input.span10{width:960px;} input.span11,textarea.span11,.uneditable-input.span11{width:1060px;} input.span12,textarea.span12,.uneditable-input.span12{width:1160px;} .thumbnails{margin-left:-30px;} .thumbnails>li{margin-left:30px;}} /*! * Bootstrap v2.0.0 * * Copyright 2012 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */ article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; } audio:not([controls]) { display: none; } html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } a:focus { outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } a:hover, a:active { outline: 0; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } img { max-width: 100%; height: auto; border: 0; -ms-interpolation-mode: bicubic; } button, input, select, textarea { margin: 0; font-size: 100%; vertical-align: middle; } button, input { *overflow: visible; line-height: normal; } button::-moz-focus-inner, input::-moz-focus-inner { padding: 0; border: 0; } button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; } input[type="search"] { -webkit-appearance: textfield; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; } input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; } textarea { overflow: auto; vertical-align: top; } body { margin: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px; color: #333333; background-color: #ffffff; } a { color: #0088cc; text-decoration: none; } a:hover { color: #005580; text-decoration: underline; } .row { margin-left: -20px; *zoom: 1; } .row:before, .row:after { display: table; content: ""; } .row:after { clear: both; } [class*="span"] { float: left; margin-left: 20px; } .span1 { width: 60px; } .span2 { width: 140px; } .span3 { width: 220px; } .span4 { width: 300px; } .span5 { width: 380px; } .span6 { width: 460px; } .span7 { width: 540px; } .span8 { width: 620px; } .span9 { width: 700px; } .span10 { width: 780px; } .span11 { width: 860px; } .span12, .container { width: 940px; } .offset1 { margin-left: 100px; } .offset2 { margin-left: 180px; } .offset3 { margin-left: 260px; } .offset4 { margin-left: 340px; } .offset5 { margin-left: 420px; } .offset6 { margin-left: 500px; } .offset7 { margin-left: 580px; } .offset8 { margin-left: 660px; } .offset9 { margin-left: 740px; } .offset10 { margin-left: 820px; } .offset11 { margin-left: 900px; } .row-fluid { width: 100%; *zoom: 1; } .row-fluid:before, .row-fluid:after { display: table; content: ""; } .row-fluid:after { clear: both; } .row-fluid > [class*="span"] { float: left; margin-left: 2.127659574%; } .row-fluid > [class*="span"]:first-child { margin-left: 0; } .row-fluid .span1 { width: 6.382978723%; } .row-fluid .span2 { width: 14.89361702%; } .row-fluid .span3 { width: 23.404255317%; } .row-fluid .span4 { width: 31.914893614%; } .row-fluid .span5 { width: 40.425531911%; } .row-fluid .span6 { width: 48.93617020799999%; } .row-fluid .span7 { width: 57.446808505%; } .row-fluid .span8 { width: 65.95744680199999%; } .row-fluid .span9 { width: 74.468085099%; } .row-fluid .span10 { width: 82.97872339599999%; } .row-fluid .span11 { width: 91.489361693%; } .row-fluid .span12 { width: 99.99999998999999%; } .container { width: 940px; margin-left: auto; margin-right: auto; *zoom: 1; } .container:before, .container:after { display: table; content: ""; } .container:after { clear: both; } .container-fluid { padding-left: 20px; padding-right: 20px; *zoom: 1; } .container-fluid:before, .container-fluid:after { display: table; content: ""; } .container-fluid:after { clear: both; } p { margin: 0 0 9px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px; } p small { font-size: 11px; color: #999999; } .lead { margin-bottom: 18px; font-size: 20px; font-weight: 200; line-height: 27px; } h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: bold; color: #333333; text-rendering: optimizelegibility; } h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-weight: normal; color: #999999; } h1 { font-size: 30px; line-height: 36px; } h1 small { font-size: 18px; } h2 { font-size: 24px; line-height: 36px; } h2 small { font-size: 18px; } h3 { line-height: 27px; font-size: 18px; } h3 small { font-size: 14px; } h4, h5, h6 { line-height: 18px; } h4 { font-size: 14px; } h4 small { font-size: 12px; } h5 { font-size: 12px; } h6 { font-size: 11px; color: #999999; text-transform: uppercase; } .page-header { padding-bottom: 17px; margin: 18px 0; border-bottom: 1px solid #eeeeee; } .page-header h1 { line-height: 1; } ul, ol { padding: 0; margin: 0 0 9px 25px; } ul ul, ul ol, ol ol, ol ul { margin-bottom: 0; } ul { list-style: disc; } ol { list-style: decimal; } li { line-height: 18px; } ul.unstyled { margin-left: 0; list-style: none; } dl { margin-bottom: 18px; } dt, dd { line-height: 18px; } dt { font-weight: bold; } dd { margin-left: 9px; } hr { margin: 18px 0; border: 0; border-top: 1px solid #e5e5e5; border-bottom: 1px solid #ffffff; } strong { font-weight: bold; } em { font-style: italic; } .muted { color: #999999; } abbr { font-size: 90%; text-transform: uppercase; border-bottom: 1px dotted #ddd; cursor: help; } blockquote { padding: 0 0 0 15px; margin: 0 0 18px; border-left: 5px solid #eeeeee; } blockquote p { margin-bottom: 0; font-size: 16px; font-weight: 300; line-height: 22.5px; } blockquote small { display: block; line-height: 18px; color: #999999; } blockquote small:before { content: '\2014 \00A0'; } blockquote.pull-right { float: right; padding-left: 0; padding-right: 15px; border-left: 0; border-right: 5px solid #eeeeee; } blockquote.pull-right p, blockquote.pull-right small { text-align: right; } q:before, q:after, blockquote:before, blockquote:after { content: ""; } address { display: block; margin-bottom: 18px; line-height: 18px; font-style: normal; } small { font-size: 100%; } cite { font-style: normal; } code, pre { padding: 0 3px 2px; font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; color: #333333; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } code { padding: 3px 4px; color: #d14; background-color: #f7f7f9; border: 1px solid #e1e1e8; } pre { display: block; padding: 8.5px; margin: 0 0 9px; font-size: 12px; line-height: 18px; background-color: #f5f5f5; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.15); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; white-space: pre; white-space: pre-wrap; word-break: break-all; } pre.prettyprint { margin-bottom: 18px; } pre code { padding: 0; background-color: transparent; } form { margin: 0 0 18px; } fieldset { padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; padding: 0; margin-bottom: 27px; font-size: 19.5px; line-height: 36px; color: #333333; border: 0; border-bottom: 1px solid #eee; } label, input, button, select, textarea { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; line-height: 18px; } label { display: block; margin-bottom: 5px; color: #333333; } input, textarea, select, .uneditable-input { display: inline-block; width: 210px; height: 18px; padding: 4px; margin-bottom: 9px; font-size: 13px; line-height: 18px; color: #555555; border: 1px solid #ccc; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .uneditable-textarea { width: auto; height: auto; } label input, label textarea, label select { display: block; } input[type="image"], input[type="checkbox"], input[type="radio"] { width: auto; height: auto; padding: 0; margin: 3px 0; *margin-top: 0; /* IE7 */ line-height: normal; border: 0; cursor: pointer; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } input[type="file"] { padding: initial; line-height: initial; border: initial; background-color: #ffffff; background-color: initial; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } input[type="button"], input[type="reset"], input[type="submit"] { width: auto; height: auto; } select, input[type="file"] { height: 28px; /* In IE7, the height of the select element cannot be changed by height, only font-size */ *margin-top: 4px; /* For IE7, add top margin to align select with labels */ line-height: 28px; } select { width: 220px; background-color: #ffffff; } select[multiple], select[size] { height: auto; } input[type="image"] { -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } textarea { height: auto; } input[type="hidden"] { display: none; } .radio, .checkbox { padding-left: 18px; } .radio input[type="radio"], .checkbox input[type="checkbox"] { float: left; margin-left: -18px; } .controls > .radio:first-child, .controls > .checkbox:first-child { padding-top: 5px; } .radio.inline, .checkbox.inline { display: inline-block; margin-bottom: 0; vertical-align: middle; } .radio.inline + .radio.inline, .checkbox.inline + .checkbox.inline { margin-left: 10px; } .controls > .radio.inline:first-child, .controls > .checkbox.inline:first-child { padding-top: 0; } input, textarea { -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; -moz-transition: border linear 0.2s, box-shadow linear 0.2s; -ms-transition: border linear 0.2s, box-shadow linear 0.2s; -o-transition: border linear 0.2s, box-shadow linear 0.2s; transition: border linear 0.2s, box-shadow linear 0.2s; } input:focus, textarea:focus { border-color: rgba(82, 168, 236, 0.8); -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); outline: 0; outline: thin dotted \9; /* IE6-8 */ } input[type="file"]:focus, input[type="checkbox"]:focus, select:focus { -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .input-mini { width: 60px; } .input-small { width: 90px; } .input-medium { width: 150px; } .input-large { width: 210px; } .input-xlarge { width: 270px; } .input-xxlarge { width: 530px; } input[class*="span"], select[class*="span"], textarea[class*="span"], .uneditable-input { float: none; margin-left: 0; } input.span1, textarea.span1, .uneditable-input.span1 { width: 50px; } input.span2, textarea.span2, .uneditable-input.span2 { width: 130px; } input.span3, textarea.span3, .uneditable-input.span3 { width: 210px; } input.span4, textarea.span4, .uneditable-input.span4 { width: 290px; } input.span5, textarea.span5, .uneditable-input.span5 { width: 370px; } input.span6, textarea.span6, .uneditable-input.span6 { width: 450px; } input.span7, textarea.span7, .uneditable-input.span7 { width: 530px; } input.span8, textarea.span8, .uneditable-input.span8 { width: 610px; } input.span9, textarea.span9, .uneditable-input.span9 { width: 690px; } input.span10, textarea.span10, .uneditable-input.span10 { width: 770px; } input.span11, textarea.span11, .uneditable-input.span11 { width: 850px; } input.span12, textarea.span12, .uneditable-input.span12 { width: 930px; } input[disabled], select[disabled], textarea[disabled], input[readonly], select[readonly], textarea[readonly] { background-color: #f5f5f5; border-color: #ddd; cursor: not-allowed; } .control-group.warning > label, .control-group.warning .help-block, .control-group.warning .help-inline { color: #c09853; } .control-group.warning input, .control-group.warning select, .control-group.warning textarea { color: #c09853; border-color: #c09853; } .control-group.warning input:focus, .control-group.warning select:focus, .control-group.warning textarea:focus { border-color: #a47e3c; -webkit-box-shadow: 0 0 6px #dbc59e; -moz-box-shadow: 0 0 6px #dbc59e; box-shadow: 0 0 6px #dbc59e; } .control-group.warning .input-prepend .add-on, .control-group.warning .input-append .add-on { color: #c09853; background-color: #fcf8e3; border-color: #c09853; } .control-group.error > label, .control-group.error .help-block, .control-group.error .help-inline { color: #b94a48; } .control-group.error input, .control-group.error select, .control-group.error textarea { color: #b94a48; border-color: #b94a48; } .control-group.error input:focus, .control-group.error select:focus, .control-group.error textarea:focus { border-color: #953b39; -webkit-box-shadow: 0 0 6px #d59392; -moz-box-shadow: 0 0 6px #d59392; box-shadow: 0 0 6px #d59392; } .control-group.error .input-prepend .add-on, .control-group.error .input-append .add-on { color: #b94a48; background-color: #f2dede; border-color: #b94a48; } .control-group.success > label, .control-group.success .help-block, .control-group.success .help-inline { color: #468847; } .control-group.success input, .control-group.success select, .control-group.success textarea { color: #468847; border-color: #468847; } .control-group.success input:focus, .control-group.success select:focus, .control-group.success textarea:focus { border-color: #356635; -webkit-box-shadow: 0 0 6px #7aba7b; -moz-box-shadow: 0 0 6px #7aba7b; box-shadow: 0 0 6px #7aba7b; } .control-group.success .input-prepend .add-on, .control-group.success .input-append .add-on { color: #468847; background-color: #dff0d8; border-color: #468847; } input:focus:required:invalid, textarea:focus:required:invalid, select:focus:required:invalid { color: #b94a48; border-color: #ee5f5b; } input:focus:required:invalid:focus, textarea:focus:required:invalid:focus, select:focus:required:invalid:focus { border-color: #e9322d; -webkit-box-shadow: 0 0 6px #f8b9b7; -moz-box-shadow: 0 0 6px #f8b9b7; box-shadow: 0 0 6px #f8b9b7; } .form-actions { padding: 17px 20px 18px; margin-top: 18px; margin-bottom: 18px; background-color: #f5f5f5; border-top: 1px solid #ddd; } .uneditable-input { display: block; background-color: #ffffff; border-color: #eee; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); cursor: not-allowed; } :-moz-placeholder { color: #999999; } ::-webkit-input-placeholder { color: #999999; } .help-block { margin-top: 5px; margin-bottom: 0; color: #999999; } .help-inline { display: inline-block; *display: inline; /* IE7 inline-block hack */ *zoom: 1; margin-bottom: 9px; vertical-align: middle; padding-left: 5px; } .input-prepend, .input-append { margin-bottom: 5px; *zoom: 1; } .input-prepend:before, .input-append:before, .input-prepend:after, .input-append:after { display: table; content: ""; } .input-prepend:after, .input-append:after { clear: both; } .input-prepend input, .input-append input, .input-prepend .uneditable-input, .input-append .uneditable-input { -webkit-border-radius: 0 3px 3px 0; -moz-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; } .input-prepend input:focus, .input-append input:focus, .input-prepend .uneditable-input:focus, .input-append .uneditable-input:focus { position: relative; z-index: 2; } .input-prepend .uneditable-input, .input-append .uneditable-input { border-left-color: #ccc; } .input-prepend .add-on, .input-append .add-on { float: left; display: block; width: auto; min-width: 16px; height: 18px; margin-right: -1px; padding: 4px 5px; font-weight: normal; line-height: 18px; color: #999999; text-align: center; text-shadow: 0 1px 0 #ffffff; background-color: #f5f5f5; border: 1px solid #ccc; -webkit-border-radius: 3px 0 0 3px; -moz-border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px; } .input-prepend .active, .input-append .active { background-color: #a9dba9; border-color: #46a546; } .input-prepend .add-on { *margin-top: 1px; /* IE6-7 */ } .input-append input, .input-append .uneditable-input { float: left; -webkit-border-radius: 3px 0 0 3px; -moz-border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px; } .input-append .uneditable-input { border-right-color: #ccc; } .input-append .add-on { margin-right: 0; margin-left: -1px; -webkit-border-radius: 0 3px 3px 0; -moz-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; } .input-append input:first-child { *margin-left: -160px; } .input-append input:first-child + .add-on { *margin-left: -21px; } .search-query { padding-left: 14px; padding-right: 14px; margin-bottom: 0; -webkit-border-radius: 14px; -moz-border-radius: 14px; border-radius: 14px; } .form-search input, .form-inline input, .form-horizontal input, .form-search textarea, .form-inline textarea, .form-horizontal textarea, .form-search select, .form-inline select, .form-horizontal select, .form-search .help-inline, .form-inline .help-inline, .form-horizontal .help-inline, .form-search .uneditable-input, .form-inline .uneditable-input, .form-horizontal .uneditable-input { display: inline-block; margin-bottom: 0; } .form-search label, .form-inline label, .form-search .input-append, .form-inline .input-append, .form-search .input-prepend, .form-inline .input-prepend { display: inline-block; } .form-search .input-append .add-on, .form-inline .input-prepend .add-on, .form-search .input-append .add-on, .form-inline .input-prepend .add-on { vertical-align: middle; } .control-group { margin-bottom: 9px; } .form-horizontal legend + .control-group { margin-top: 18px; -webkit-margin-top-collapse: separate; } .form-horizontal .control-group { margin-bottom: 18px; *zoom: 1; } .form-horizontal .control-group:before, .form-horizontal .control-group:after { display: table; content: ""; } .form-horizontal .control-group:after { clear: both; } .form-horizontal .control-group > label { float: left; width: 140px; padding-top: 5px; text-align: right; } .form-horizontal .controls { margin-left: 160px; } .form-horizontal .form-actions { padding-left: 160px; } table { max-width: 100%; border-collapse: collapse; border-spacing: 0; } .table { width: 100%; margin-bottom: 18px; } .table th, .table td { padding: 8px; line-height: 18px; text-align: left; border-top: 1px solid #ddd; } .table th { font-weight: bold; vertical-align: bottom; } .table td { vertical-align: top; } .table thead:first-child tr th, .table thead:first-child tr td { border-top: 0; } .table tbody + tbody { border-top: 2px solid #ddd; } .table-condensed th, .table-condensed td { padding: 4px 5px; } .table-bordered { border: 1px solid #ddd; border-collapse: separate; *border-collapse: collapsed; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .table-bordered th + th, .table-bordered td + td, .table-bordered th + td, .table-bordered td + th { border-left: 1px solid #ddd; } .table-bordered thead:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child td { border-top: 0; } .table-bordered thead:first-child tr:first-child th:first-child, .table-bordered tbody:first-child tr:first-child td:first-child { -webkit-border-radius: 4px 0 0 0; -moz-border-radius: 4px 0 0 0; border-radius: 4px 0 0 0; } .table-bordered thead:first-child tr:first-child th:last-child, .table-bordered tbody:first-child tr:first-child td:last-child { -webkit-border-radius: 0 4px 0 0; -moz-border-radius: 0 4px 0 0; border-radius: 0 4px 0 0; } .table-bordered thead:last-child tr:last-child th:first-child, .table-bordered tbody:last-child tr:last-child td:first-child { -webkit-border-radius: 0 0 0 4px; -moz-border-radius: 0 0 0 4px; border-radius: 0 0 0 4px; } .table-bordered thead:last-child tr:last-child th:last-child, .table-bordered tbody:last-child tr:last-child td:last-child { -webkit-border-radius: 0 0 4px 0; -moz-border-radius: 0 0 4px 0; border-radius: 0 0 4px 0; } .table-striped tbody tr:nth-child(odd) td, .table-striped tbody tr:nth-child(odd) th { background-color: #f9f9f9; } table .span1 { float: none; width: 44px; margin-left: 0; } table .span2 { float: none; width: 124px; margin-left: 0; } table .span3 { float: none; width: 204px; margin-left: 0; } table .span4 { float: none; width: 284px; margin-left: 0; } table .span5 { float: none; width: 364px; margin-left: 0; } table .span6 { float: none; width: 444px; margin-left: 0; } table .span7 { float: none; width: 524px; margin-left: 0; } table .span8 { float: none; width: 604px; margin-left: 0; } table .span9 { float: none; width: 684px; margin-left: 0; } table .span10 { float: none; width: 764px; margin-left: 0; } table .span11 { float: none; width: 844px; margin-left: 0; } table .span12 { float: none; width: 924px; margin-left: 0; } [class^="icon-"] { display: inline-block; width: 14px; height: 14px; vertical-align: text-top; background-image: url(../../../../build/api/img/glyphicons-halflings.png); background-position: 14px 14px; background-repeat: no-repeat; *margin-right: .3em; } [class^="icon-"]:last-child { *margin-left: 0; } .icon-white { background-image: url(../../../../build/api/img/glyphicons-halflings-white.png); } .icon-glass { background-position: 0 0; } .icon-music { background-position: -24px 0; } .icon-search { background-position: -48px 0; } .icon-envelope { background-position: -72px 0; } .icon-heart { background-position: -96px 0; } .icon-star { background-position: -120px 0; } .icon-star-empty { background-position: -144px 0; } .icon-user { background-position: -168px 0; } .icon-film { background-position: -192px 0; } .icon-th-large { background-position: -216px 0; } .icon-th { background-position: -240px 0; } .icon-th-list { background-position: -264px 0; } .icon-ok { background-position: -288px 0; } .icon-remove { background-position: -312px 0; } .icon-zoom-in { background-position: -336px 0; } .icon-zoom-out { background-position: -360px 0; } .icon-off { background-position: -384px 0; } .icon-signal { background-position: -408px 0; } .icon-cog { background-position: -432px 0; } .icon-trash { background-position: -456px 0; } .icon-home { background-position: 0 -24px; } .icon-file { background-position: -24px -24px; } .icon-time { background-position: -48px -24px; } .icon-road { background-position: -72px -24px; } .icon-download-alt { background-position: -96px -24px; } .icon-download { background-position: -120px -24px; } .icon-upload { background-position: -144px -24px; } .icon-inbox { background-position: -168px -24px; } .icon-play-circle { background-position: -192px -24px; } .icon-repeat { background-position: -216px -24px; } .icon-refresh { background-position: -240px -24px; } .icon-list-alt { background-position: -264px -24px; } .icon-lock { background-position: -287px -24px; } .icon-flag { background-position: -312px -24px; } .icon-headphones { background-position: -336px -24px; } .icon-volume-off { background-position: -360px -24px; } .icon-volume-down { background-position: -384px -24px; } .icon-volume-up { background-position: -408px -24px; } .icon-qrcode { background-position: -432px -24px; } .icon-barcode { background-position: -456px -24px; } .icon-tag { background-position: 0 -48px; } .icon-tags { background-position: -25px -48px; } .icon-book { background-position: -48px -48px; } .icon-bookmark { background-position: -72px -48px; } .icon-print { background-position: -96px -48px; } .icon-camera { background-position: -120px -48px; } .icon-font { background-position: -144px -48px; } .icon-bold { background-position: -167px -48px; } .icon-italic { background-position: -192px -48px; } .icon-text-height { background-position: -216px -48px; } .icon-text-width { background-position: -240px -48px; } .icon-align-left { background-position: -264px -48px; } .icon-align-center { background-position: -288px -48px; } .icon-align-right { background-position: -312px -48px; } .icon-align-justify { background-position: -336px -48px; } .icon-list { background-position: -360px -48px; } .icon-indent-left { background-position: -384px -48px; } .icon-indent-right { background-position: -408px -48px; } .icon-facetime-video { background-position: -432px -48px; } .icon-picture { background-position: -456px -48px; } .icon-pencil { background-position: 0 -72px; } .icon-map-marker { background-position: -24px -72px; } .icon-adjust { background-position: -48px -72px; } .icon-tint { background-position: -72px -72px; } .icon-edit { background-position: -96px -72px; } .icon-share { background-position: -120px -72px; } .icon-check { background-position: -144px -72px; } .icon-move { background-position: -168px -72px; } .icon-step-backward { background-position: -192px -72px; } .icon-fast-backward { background-position: -216px -72px; } .icon-backward { background-position: -240px -72px; } .icon-play { background-position: -264px -72px; } .icon-pause { background-position: -288px -72px; } .icon-stop { background-position: -312px -72px; } .icon-forward { background-position: -336px -72px; } .icon-fast-forward { background-position: -360px -72px; } .icon-step-forward { background-position: -384px -72px; } .icon-eject { background-position: -408px -72px; } .icon-chevron-left { background-position: -432px -72px; } .icon-chevron-right { background-position: -456px -72px; } .icon-plus-sign { background-position: 0 -96px; } .icon-minus-sign { background-position: -24px -96px; } .icon-remove-sign { background-position: -48px -96px; } .icon-ok-sign { background-position: -72px -96px; } .icon-question-sign { background-position: -96px -96px; } .icon-info-sign { background-position: -120px -96px; } .icon-screenshot { background-position: -144px -96px; } .icon-remove-circle { background-position: -168px -96px; } .icon-ok-circle { background-position: -192px -96px; } .icon-ban-circle { background-position: -216px -96px; } .icon-arrow-left { background-position: -240px -96px; } .icon-arrow-right { background-position: -264px -96px; } .icon-arrow-up { background-position: -289px -96px; } .icon-arrow-down { background-position: -312px -96px; } .icon-share-alt { background-position: -336px -96px; } .icon-resize-full { background-position: -360px -96px; } .icon-resize-small { background-position: -384px -96px; } .icon-plus { background-position: -408px -96px; } .icon-minus { background-position: -433px -96px; } .icon-asterisk { background-position: -456px -96px; } .icon-exclamation-sign { background-position: 0 -120px; } .icon-gift { background-position: -24px -120px; } .icon-leaf { background-position: -48px -120px; } .icon-fire { background-position: -72px -120px; } .icon-eye-open { background-position: -96px -120px; } .icon-eye-close { background-position: -120px -120px; } .icon-warning-sign { background-position: -144px -120px; } .icon-plane { background-position: -168px -120px; } .icon-calendar { background-position: -192px -120px; } .icon-random { background-position: -216px -120px; } .icon-comment { background-position: -240px -120px; } .icon-magnet { background-position: -264px -120px; } .icon-chevron-up { background-position: -288px -120px; } .icon-chevron-down { background-position: -313px -119px; } .icon-retweet { background-position: -336px -120px; } .icon-shopping-cart { background-position: -360px -120px; } .icon-folder-close { background-position: -384px -120px; } .icon-folder-open { background-position: -408px -120px; } .icon-resize-vertical { background-position: -432px -119px; } .icon-resize-horizontal { background-position: -456px -118px; } .dropdown { position: relative; } .dropdown-toggle { *margin-bottom: -3px; } .dropdown-toggle:active, .open .dropdown-toggle { outline: 0; } .caret { display: inline-block; width: 0; height: 0; text-indent: -99999px; *text-indent: 0; vertical-align: top; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 4px solid #000000; opacity: 0.3; filter: alpha(opacity=30); content: "\2193"; } .dropdown .caret { margin-top: 8px; margin-left: 2px; } .dropdown:hover .caret, .open.dropdown .caret { opacity: 1; filter: alpha(opacity=100); } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; float: left; display: none; min-width: 160px; max-width: 220px; _width: 160px; padding: 4px 0; margin: 0; list-style: none; background-color: #ffffff; border-color: #ccc; border-color: rgba(0, 0, 0, 0.2); border-style: solid; border-width: 1px; -webkit-border-radius: 0 0 5px 5px; -moz-border-radius: 0 0 5px 5px; border-radius: 0 0 5px 5px; -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -webkit-background-clip: padding-box; -moz-background-clip: padding; background-clip: padding-box; *border-right-width: 2px; *border-bottom-width: 2px; } .dropdown-menu.bottom-up { top: auto; bottom: 100%; margin-bottom: 2px; } .dropdown-menu .divider { height: 1px; margin: 5px 1px; overflow: hidden; background-color: #e5e5e5; border-bottom: 1px solid #ffffff; *width: 100%; *margin: -5px 0 5px; } .dropdown-menu a { display: block; padding: 3px 15px; clear: both; font-weight: normal; line-height: 18px; color: #555555; white-space: nowrap; } .dropdown-menu li > a:hover, .dropdown-menu .active > a, .dropdown-menu .active > a:hover { color: #ffffff; text-decoration: none; background-color: #0088cc; } .dropdown.open { *z-index: 1000; } .dropdown.open .dropdown-toggle { color: #ffffff; background: #ccc; background: rgba(0, 0, 0, 0.3); } .dropdown.open .dropdown-menu { display: block; } .typeahead { margin-top: 2px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .well { min-height: 20px; padding: 19px; margin-bottom: 20px; background-color: #f5f5f5; border: 1px solid #eee; border: 1px solid rgba(0, 0, 0, 0.05); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); } .well blockquote { border-color: #ddd; border-color: rgba(0, 0, 0, 0.15); } .fade { -webkit-transition: opacity 0.15s linear; -moz-transition: opacity 0.15s linear; -ms-transition: opacity 0.15s linear; -o-transition: opacity 0.15s linear; transition: opacity 0.15s linear; opacity: 0; } .fade.in { opacity: 1; } .collapse { -webkit-transition: height 0.35s ease; -moz-transition: height 0.35s ease; -ms-transition: height 0.35s ease; -o-transition: height 0.35s ease; transition: height 0.35s ease; position: relative; overflow: hidden; height: 0; } .collapse.in { height: auto; } .close { float: right; font-size: 20px; font-weight: bold; line-height: 18px; color: #000000; text-shadow: 0 1px 0 #ffffff; opacity: 0.2; filter: alpha(opacity=20); } .close:hover { color: #000000; text-decoration: none; opacity: 0.4; filter: alpha(opacity=40); cursor: pointer; } .btn { display: inline-block; padding: 4px 10px 4px; font-size: 13px; line-height: 18px; color: #333333; text-align: center; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); background-color: #fafafa; background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-repeat: no-repeat; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); border: 1px solid #ccc; border-bottom-color: #bbb; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); cursor: pointer; *margin-left: .3em; } .btn:first-child { *margin-left: 0; } .btn:hover { color: #333333; text-decoration: none; background-color: #e6e6e6; background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; -ms-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; } .btn:focus { outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .btn.active, .btn:active { background-image: none; -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); background-color: #e6e6e6; background-color: #d9d9d9 \9; color: rgba(0, 0, 0, 0.5); outline: 0; } .btn.disabled, .btn[disabled] { cursor: default; background-image: none; background-color: #e6e6e6; opacity: 0.65; filter: alpha(opacity=65); -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } .btn-large { padding: 9px 14px; font-size: 15px; line-height: normal; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .btn-large .icon { margin-top: 1px; } .btn-small { padding: 5px 9px; font-size: 11px; line-height: 16px; } .btn-small .icon { margin-top: -1px; } .btn-primary, .btn-primary:hover, .btn-warning, .btn-warning:hover, .btn-danger, .btn-danger:hover, .btn-success, .btn-success:hover, .btn-info, .btn-info:hover { text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); color: #ffffff; } .btn-primary.active, .btn-warning.active, .btn-danger.active, .btn-success.active, .btn-info.active { color: rgba(255, 255, 255, 0.75); } .btn-primary { background-color: #006dcc; background-image: -moz-linear-gradient(top, #0088cc, #0044cc); background-image: -ms-linear-gradient(top, #0088cc, #0044cc); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); background-image: -o-linear-gradient(top, #0088cc, #0044cc); background-image: linear-gradient(top, #0088cc, #0044cc); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); border-color: #0044cc #0044cc #002a80; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] { background-color: #0044cc; } .btn-primary:active, .btn-primary.active { background-color: #003399 \9; } .btn-warning { background-color: #faa732; background-image: -moz-linear-gradient(top, #fbb450, #f89406); background-image: -ms-linear-gradient(top, #fbb450, #f89406); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); background-image: -webkit-linear-gradient(top, #fbb450, #f89406); background-image: -o-linear-gradient(top, #fbb450, #f89406); background-image: linear-gradient(top, #fbb450, #f89406); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); border-color: #f89406 #f89406 #ad6704; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .btn-warning:hover, .btn-warning:active, .btn-warning.active, .btn-warning.disabled, .btn-warning[disabled] { background-color: #f89406; } .btn-warning:active, .btn-warning.active { background-color: #c67605 \9; } .btn-danger { background-color: #da4f49; background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); background-image: linear-gradient(top, #ee5f5b, #bd362f); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0); border-color: #bd362f #bd362f #802420; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .btn-danger:hover, .btn-danger:active, .btn-danger.active, .btn-danger.disabled, .btn-danger[disabled] { background-color: #bd362f; } .btn-danger:active, .btn-danger.active { background-color: #942a25 \9; } .btn-success { background-color: #5bb75b; background-image: -moz-linear-gradient(top, #62c462, #51a351); background-image: -ms-linear-gradient(top, #62c462, #51a351); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); background-image: -webkit-linear-gradient(top, #62c462, #51a351); background-image: -o-linear-gradient(top, #62c462, #51a351); background-image: linear-gradient(top, #62c462, #51a351); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0); border-color: #51a351 #51a351 #387038; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .btn-success:hover, .btn-success:active, .btn-success.active, .btn-success.disabled, .btn-success[disabled] { background-color: #51a351; } .btn-success:active, .btn-success.active { background-color: #408140 \9; } .btn-info { background-color: #49afcd; background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); background-image: linear-gradient(top, #5bc0de, #2f96b4); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0); border-color: #2f96b4 #2f96b4 #1f6377; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .btn-info:hover, .btn-info:active, .btn-info.active, .btn-info.disabled, .btn-info[disabled] { background-color: #2f96b4; } .btn-info:active, .btn-info.active { background-color: #24748c \9; } button.btn, input[type="submit"].btn { *padding-top: 2px; *padding-bottom: 2px; } button.btn::-moz-focus-inner, input[type="submit"].btn::-moz-focus-inner { padding: 0; border: 0; } button.btn.large, input[type="submit"].btn.large { *padding-top: 7px; *padding-bottom: 7px; } button.btn.small, input[type="submit"].btn.small { *padding-top: 3px; *padding-bottom: 3px; } .btn-group { position: relative; *zoom: 1; *margin-left: .3em; } .btn-group:before, .btn-group:after { display: table; content: ""; } .btn-group:after { clear: both; } .btn-group:first-child { *margin-left: 0; } .btn-group + .btn-group { margin-left: 5px; } .btn-toolbar { margin-top: 9px; margin-bottom: 9px; } .btn-toolbar .btn-group { display: inline-block; *display: inline; /* IE7 inline-block hack */ *zoom: 1; } .btn-group .btn { position: relative; float: left; margin-left: -1px; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .btn-group .btn:first-child { margin-left: 0; -webkit-border-top-left-radius: 4px; -moz-border-radius-topleft: 4px; border-top-left-radius: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomleft: 4px; border-bottom-left-radius: 4px; } .btn-group .btn:last-child, .btn-group .dropdown-toggle { -webkit-border-top-right-radius: 4px; -moz-border-radius-topright: 4px; border-top-right-radius: 4px; -webkit-border-bottom-right-radius: 4px; -moz-border-radius-bottomright: 4px; border-bottom-right-radius: 4px; } .btn-group .btn.large:first-child { margin-left: 0; -webkit-border-top-left-radius: 6px; -moz-border-radius-topleft: 6px; border-top-left-radius: 6px; -webkit-border-bottom-left-radius: 6px; -moz-border-radius-bottomleft: 6px; border-bottom-left-radius: 6px; } .btn-group .btn.large:last-child, .btn-group .large.dropdown-toggle { -webkit-border-top-right-radius: 6px; -moz-border-radius-topright: 6px; border-top-right-radius: 6px; -webkit-border-bottom-right-radius: 6px; -moz-border-radius-bottomright: 6px; border-bottom-right-radius: 6px; } .btn-group .btn:hover, .btn-group .btn:focus, .btn-group .btn:active, .btn-group .btn.active { z-index: 2; } .btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { outline: 0; } .btn-group .dropdown-toggle { padding-left: 8px; padding-right: 8px; -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); *padding-top: 5px; *padding-bottom: 5px; } .btn-group.open { *z-index: 1000; } .btn-group.open .dropdown-menu { display: block; margin-top: 1px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .btn-group.open .dropdown-toggle { background-image: none; -webkit-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); } .btn .caret { margin-top: 7px; margin-left: 0; } .btn:hover .caret, .open.btn-group .caret { opacity: 1; filter: alpha(opacity=100); } .btn-primary .caret, .btn-danger .caret, .btn-info .caret, .btn-success .caret { border-top-color: #ffffff; opacity: 0.75; filter: alpha(opacity=75); } .btn-small .caret { margin-top: 4px; } .alert { padding: 8px 35px 8px 14px; margin-bottom: 18px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); background-color: #fcf8e3; border: 1px solid #fbeed5; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .alert, .alert-heading { color: #c09853; } .alert .close { position: relative; top: -2px; right: -21px; line-height: 18px; } .alert-success { background-color: #dff0d8; border-color: #d6e9c6; } .alert-success, .alert-success .alert-heading { color: #468847; } .alert-danger, .alert-error { background-color: #f2dede; border-color: #eed3d7; } .alert-danger, .alert-error, .alert-danger .alert-heading, .alert-error .alert-heading { color: #b94a48; } .alert-info { background-color: #d9edf7; border-color: #bce8f1; } .alert-info, .alert-info .alert-heading { color: #3a87ad; } .alert-block { padding-top: 14px; padding-bottom: 14px; } .alert-block > p, .alert-block > ul { margin-bottom: 0; } .alert-block p + p { margin-top: 5px; } .nav { margin-left: 0; margin-bottom: 18px; list-style: none; } .nav > li > a { display: block; } .nav > li > a:hover { text-decoration: none; background-color: #eeeeee; } .nav-list { padding-left: 14px; padding-right: 14px; margin-bottom: 0; } .nav-list > li > a, .nav-list .nav-header { display: block; padding: 3px 15px; margin-left: -15px; margin-right: -15px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); } .nav-list .nav-header { font-size: 11px; font-weight: bold; line-height: 18px; color: #999999; text-transform: uppercase; } .nav-list > li + .nav-header { margin-top: 9px; } .nav-list .active > a, .nav-list .active > a:hover { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); background-color: #0088cc; } .nav-list [class^="icon-"] { margin-right: 2px; } .nav-tabs, .nav-pills { *zoom: 1; } .nav-tabs:before, .nav-pills:before, .nav-tabs:after, .nav-pills:after { display: table; content: ""; } .nav-tabs:after, .nav-pills:after { clear: both; } .nav-tabs > li, .nav-pills > li { float: left; } .nav-tabs > li > a, .nav-pills > li > a { padding-right: 12px; padding-left: 12px; margin-right: 2px; line-height: 14px; } .nav-tabs { border-bottom: 1px solid #ddd; } .nav-tabs > li { margin-bottom: -1px; } .nav-tabs > li > a { padding-top: 9px; padding-bottom: 9px; border: 1px solid transparent; -webkit-border-radius: 4px 4px 0 0; -moz-border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0; } .nav-tabs > li > a:hover { border-color: #eeeeee #eeeeee #dddddd; } .nav-tabs > .active > a, .nav-tabs > .active > a:hover { color: #555555; background-color: #ffffff; border: 1px solid #ddd; border-bottom-color: transparent; cursor: default; } .nav-pills > li > a { padding-top: 8px; padding-bottom: 8px; margin-top: 2px; margin-bottom: 2px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .nav-pills .active > a, .nav-pills .active > a:hover { color: #ffffff; background-color: #0088cc; } .nav-stacked > li { float: none; } .nav-stacked > li > a { margin-right: 0; } .nav-tabs.nav-stacked { border-bottom: 0; } .nav-tabs.nav-stacked > li > a { border: 1px solid #ddd; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .nav-tabs.nav-stacked > li:first-child > a { -webkit-border-radius: 4px 4px 0 0; -moz-border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0; } .nav-tabs.nav-stacked > li:last-child > a { -webkit-border-radius: 0 0 4px 4px; -moz-border-radius: 0 0 4px 4px; border-radius: 0 0 4px 4px; } .nav-tabs.nav-stacked > li > a:hover { border-color: #ddd; z-index: 2; } .nav-pills.nav-stacked > li > a { margin-bottom: 3px; } .nav-pills.nav-stacked > li:last-child > a { margin-bottom: 1px; } .nav-tabs .dropdown-menu, .nav-pills .dropdown-menu { margin-top: 1px; border-width: 1px; } .nav-pills .dropdown-menu { -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .nav-tabs .dropdown-toggle .caret, .nav-pills .dropdown-toggle .caret { border-top-color: #0088cc; margin-top: 6px; } .nav-tabs .dropdown-toggle:hover .caret, .nav-pills .dropdown-toggle:hover .caret { border-top-color: #005580; } .nav-tabs .active .dropdown-toggle .caret, .nav-pills .active .dropdown-toggle .caret { border-top-color: #333333; } .nav > .dropdown.active > a:hover { color: #000000; cursor: pointer; } .nav-tabs .open .dropdown-toggle, .nav-pills .open .dropdown-toggle, .nav > .open.active > a:hover { color: #ffffff; background-color: #999999; border-color: #999999; } .nav .open .caret, .nav .open.active .caret, .nav .open a:hover .caret { border-top-color: #ffffff; opacity: 1; filter: alpha(opacity=100); } .tabs-stacked .open > a:hover { border-color: #999999; } .tabbable { *zoom: 1; } .tabbable:before, .tabbable:after { display: table; content: ""; } .tabbable:after { clear: both; } .tabs-below .nav-tabs, .tabs-right .nav-tabs, .tabs-left .nav-tabs { border-bottom: 0; } .tab-content > .tab-pane, .pill-content > .pill-pane { display: none; } .tab-content > .active, .pill-content > .active { display: block; } .tabs-below .nav-tabs { border-top: 1px solid #ddd; } .tabs-below .nav-tabs > li { margin-top: -1px; margin-bottom: 0; } .tabs-below .nav-tabs > li > a { -webkit-border-radius: 0 0 4px 4px; -moz-border-radius: 0 0 4px 4px; border-radius: 0 0 4px 4px; } .tabs-below .nav-tabs > li > a:hover { border-bottom-color: transparent; border-top-color: #ddd; } .tabs-below .nav-tabs .active > a, .tabs-below .nav-tabs .active > a:hover { border-color: transparent #ddd #ddd #ddd; } .tabs-left .nav-tabs > li, .tabs-right .nav-tabs > li { float: none; } .tabs-left .nav-tabs > li > a, .tabs-right .nav-tabs > li > a { min-width: 74px; margin-right: 0; margin-bottom: 3px; } .tabs-left .nav-tabs { float: left; margin-right: 19px; border-right: 1px solid #ddd; } .tabs-left .nav-tabs > li > a { margin-right: -1px; -webkit-border-radius: 4px 0 0 4px; -moz-border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px; } .tabs-left .nav-tabs > li > a:hover { border-color: #eeeeee #dddddd #eeeeee #eeeeee; } .tabs-left .nav-tabs .active > a, .tabs-left .nav-tabs .active > a:hover { border-color: #ddd transparent #ddd #ddd; *border-right-color: #ffffff; } .tabs-right .nav-tabs { float: right; margin-left: 19px; border-left: 1px solid #ddd; } .tabs-right .nav-tabs > li > a { margin-left: -1px; -webkit-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } .tabs-right .nav-tabs > li > a:hover { border-color: #eeeeee #eeeeee #eeeeee #dddddd; } .tabs-right .nav-tabs .active > a, .tabs-right .nav-tabs .active > a:hover { border-color: #ddd #ddd #ddd transparent; *border-left-color: #ffffff; } .navbar { overflow: visible; margin-bottom: 18px; } .navbar-inner { padding-left: 20px; padding-right: 20px; background-color: #2c2c2c; background-image: -moz-linear-gradient(top, #333333, #222222); background-image: -ms-linear-gradient(top, #333333, #222222); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); background-image: -webkit-linear-gradient(top, #333333, #222222); background-image: -o-linear-gradient(top, #333333, #222222); background-image: linear-gradient(top, #333333, #222222); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); } .btn-navbar { display: none; float: right; padding: 7px 10px; margin-left: 5px; margin-right: 5px; background-color: #2c2c2c; background-image: -moz-linear-gradient(top, #333333, #222222); background-image: -ms-linear-gradient(top, #333333, #222222); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); background-image: -webkit-linear-gradient(top, #333333, #222222); background-image: -o-linear-gradient(top, #333333, #222222); background-image: linear-gradient(top, #333333, #222222); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); border-color: #222222 #222222 #000000; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); } .btn-navbar:hover, .btn-navbar:active, .btn-navbar.active, .btn-navbar.disabled, .btn-navbar[disabled] { background-color: #222222; } .btn-navbar:active, .btn-navbar.active { background-color: #080808 \9; } .btn-navbar .icon-bar { display: block; width: 18px; height: 2px; background-color: #f5f5f5; -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); } .btn-navbar .icon-bar + .icon-bar { margin-top: 3px; } .nav-collapse.collapse { height: auto; } .navbar .brand:hover { text-decoration: none; } .navbar .brand { float: left; display: block; padding: 8px 20px 12px; margin-left: -20px; font-size: 20px; font-weight: 200; line-height: 1; color: #ffffff; } .navbar .navbar-text { margin-bottom: 0; line-height: 40px; color: #999999; } .navbar .navbar-text a:hover { color: #ffffff; background-color: transparent; } .navbar .btn, .navbar .btn-group { margin-top: 5px; } .navbar .btn-group .btn { margin-top: 0; } .navbar-form { margin-bottom: 0; *zoom: 1; } .navbar-form:before, .navbar-form:after { display: table; content: ""; } .navbar-form:after { clear: both; } .navbar-form input, .navbar-form select { display: inline-block; margin-top: 5px; margin-bottom: 0; } .navbar-form .radio, .navbar-form .checkbox { margin-top: 5px; } .navbar-form input[type="image"], .navbar-form input[type="checkbox"], .navbar-form input[type="radio"] { margin-top: 3px; } .navbar-search { position: relative; float: left; margin-top: 6px; margin-bottom: 0; } .navbar-search .search-query { padding: 4px 9px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; line-height: 1; color: #ffffff; color: rgba(255, 255, 255, 0.75); background: #666; background: rgba(255, 255, 255, 0.3); border: 1px solid #111; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none; transition: none; } .navbar-search .search-query :-moz-placeholder { color: #eeeeee; } .navbar-search .search-query::-webkit-input-placeholder { color: #eeeeee; } .navbar-search .search-query:hover { color: #ffffff; background-color: #999999; background-color: rgba(255, 255, 255, 0.5); } .navbar-search .search-query:focus, .navbar-search .search-query.focused { padding: 5px 10px; color: #333333; text-shadow: 0 1px 0 #ffffff; background-color: #ffffff; border: 0; -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); outline: 0; } .navbar-fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030; } .navbar-fixed-top .navbar-inner { padding-left: 0; padding-right: 0; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .navbar .nav { position: relative; left: 0; display: block; float: left; margin: 0 10px 0 0; } .navbar .nav.pull-right { float: right; } .navbar .nav > li { display: block; float: left; } .navbar .nav > li > a { float: none; padding: 10px 10px 11px; line-height: 19px; color: #999999; text-decoration: none; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); } .navbar .nav > li > a:hover { background-color: transparent; color: #ffffff; text-decoration: none; } .navbar .nav .active > a, .navbar .nav .active > a:hover { color: #ffffff; text-decoration: none; background-color: #222222; background-color: rgba(0, 0, 0, 0.5); } .navbar .divider-vertical { height: 40px; width: 1px; margin: 0 9px; overflow: hidden; background-color: #222222; border-right: 1px solid #333333; } .navbar .nav.pull-right { margin-left: 10px; margin-right: 0; } .navbar .dropdown-menu { margin-top: 1px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .navbar .dropdown-menu:before { content: ''; display: inline-block; border-left: 7px solid transparent; border-right: 7px solid transparent; border-bottom: 7px solid #ccc; border-bottom-color: rgba(0, 0, 0, 0.2); position: absolute; top: -7px; left: 9px; } .navbar .dropdown-menu:after { content: ''; display: inline-block; border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 6px solid #ffffff; position: absolute; top: -6px; left: 10px; } .navbar .nav .dropdown-toggle .caret, .navbar .nav .open.dropdown .caret { border-top-color: #ffffff; } .navbar .nav .active .caret { opacity: 1; filter: alpha(opacity=100); } .navbar .nav .open > .dropdown-toggle, .navbar .nav .active > .dropdown-toggle, .navbar .nav .open.active > .dropdown-toggle { background-color: transparent; } .navbar .nav .active > .dropdown-toggle:hover { color: #ffffff; } .navbar .nav.pull-right .dropdown-menu { left: auto; right: 0; } .navbar .nav.pull-right .dropdown-menu:before { left: auto; right: 12px; } .navbar .nav.pull-right .dropdown-menu:after { left: auto; right: 13px; } .breadcrumb { padding: 7px 14px; margin: 0 0 18px; background-color: #fbfbfb; background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); background-image: linear-gradient(top, #ffffff, #f5f5f5); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); border: 1px solid #ddd; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; } .breadcrumb li { display: inline; text-shadow: 0 1px 0 #ffffff; } .breadcrumb .divider { padding: 0 5px; color: #999999; } .breadcrumb .active a { color: #333333; } .pagination { height: 36px; margin: 18px 0; } .pagination ul { display: inline-block; *display: inline; /* IE7 inline-block hack */ *zoom: 1; margin-left: 0; margin-bottom: 0; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } .pagination li { display: inline; } .pagination a { float: left; padding: 0 14px; line-height: 34px; text-decoration: none; border: 1px solid #ddd; border-left-width: 0; } .pagination a:hover, .pagination .active a { background-color: #f5f5f5; } .pagination .active a { color: #999999; cursor: default; } .pagination .disabled a, .pagination .disabled a:hover { color: #999999; background-color: transparent; cursor: default; } .pagination li:first-child a { border-left-width: 1px; -webkit-border-radius: 3px 0 0 3px; -moz-border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px; } .pagination li:last-child a { -webkit-border-radius: 0 3px 3px 0; -moz-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; } .pagination-centered { text-align: center; } .pagination-right { text-align: right; } .pager { margin-left: 0; margin-bottom: 18px; list-style: none; text-align: center; *zoom: 1; } .pager:before, .pager:after { display: table; content: ""; } .pager:after { clear: both; } .pager li { display: inline; } .pager a { display: inline-block; padding: 5px 14px; background-color: #fff; border: 1px solid #ddd; -webkit-border-radius: 15px; -moz-border-radius: 15px; border-radius: 15px; } .pager a:hover { text-decoration: none; background-color: #f5f5f5; } .pager .next a { float: right; } .pager .previous a { float: left; } .modal-open .dropdown-menu { z-index: 2050; } .modal-open .dropdown.open { *z-index: 2050; } .modal-open .popover { z-index: 2060; } .modal-open .tooltip { z-index: 2070; } .modal-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1040; background-color: #000000; } .modal-backdrop.fade { opacity: 0; } .modal-backdrop, .modal-backdrop.fade.in { opacity: 0.8; filter: alpha(opacity=80); } .modal { position: fixed; top: 50%; left: 50%; z-index: 1050; max-height: 500px; overflow: auto; width: 560px; margin: -250px 0 0 -280px; background-color: #ffffff; border: 1px solid #999; border: 1px solid rgba(0, 0, 0, 0.3); *border: 1px solid #999; /* IE6-7 */ -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -webkit-background-clip: padding-box; -moz-background-clip: padding-box; background-clip: padding-box; } .modal.fade { -webkit-transition: opacity .3s linear, top .3s ease-out; -moz-transition: opacity .3s linear, top .3s ease-out; -ms-transition: opacity .3s linear, top .3s ease-out; -o-transition: opacity .3s linear, top .3s ease-out; transition: opacity .3s linear, top .3s ease-out; top: -25%; } .modal.fade.in { top: 50%; } .modal-header { padding: 9px 15px; border-bottom: 1px solid #eee; } .modal-header .close { margin-top: 2px; } .modal-body { padding: 15px; } .modal-footer { padding: 14px 15px 15px; margin-bottom: 0; background-color: #f5f5f5; border-top: 1px solid #ddd; -webkit-border-radius: 0 0 6px 6px; -moz-border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; *zoom: 1; } .modal-footer:before, .modal-footer:after { display: table; content: ""; } .modal-footer:after { clear: both; } .modal-footer .btn { float: right; margin-left: 5px; margin-bottom: 0; } .tooltip { position: absolute; z-index: 1020; display: block; visibility: visible; padding: 5px; font-size: 11px; opacity: 0; filter: alpha(opacity=0); } .tooltip.in { opacity: 0.8; filter: alpha(opacity=80); } .tooltip.top { margin-top: -2px; } .tooltip.right { margin-left: 2px; } .tooltip.bottom { margin-top: 2px; } .tooltip.left { margin-left: -2px; } .tooltip.top .tooltip-arrow { bottom: 0; left: 50%; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 5px solid #000000; } .tooltip.left .tooltip-arrow { top: 50%; right: 0; margin-top: -5px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; border-left: 5px solid #000000; } .tooltip.bottom .tooltip-arrow { top: 0; left: 50%; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 5px solid #000000; } .tooltip.right .tooltip-arrow { top: 50%; left: 0; margin-top: -5px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; border-right: 5px solid #000000; } .tooltip-inner { max-width: 200px; padding: 3px 8px; color: #ffffff; text-align: center; text-decoration: none; background-color: #000000; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .tooltip-arrow { position: absolute; width: 0; height: 0; } .popover { position: absolute; top: 0; left: 0; z-index: 1010; display: none; padding: 5px; } .popover.top { margin-top: -5px; } .popover.right { margin-left: 5px; } .popover.bottom { margin-top: 5px; } .popover.left { margin-left: -5px; } .popover.top .arrow { bottom: 0; left: 50%; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 5px solid #000000; } .popover.right .arrow { top: 50%; left: 0; margin-top: -5px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; border-right: 5px solid #000000; } .popover.bottom .arrow { top: 0; left: 50%; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 5px solid #000000; } .popover.left .arrow { top: 50%; right: 0; margin-top: -5px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; border-left: 5px solid #000000; } .popover .arrow { position: absolute; width: 0; height: 0; } .popover-inner { padding: 3px; width: 280px; overflow: hidden; background: #000000; background: rgba(0, 0, 0, 0.8); -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); } .popover-title { padding: 9px 15px; line-height: 1; background-color: #f5f5f5; border-bottom: 1px solid #eee; -webkit-border-radius: 3px 3px 0 0; -moz-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; } .popover-content { padding: 14px; background-color: #ffffff; -webkit-border-radius: 0 0 3px 3px; -moz-border-radius: 0 0 3px 3px; border-radius: 0 0 3px 3px; -webkit-background-clip: padding-box; -moz-background-clip: padding-box; background-clip: padding-box; } .popover-content p, .popover-content ul, .popover-content ol { margin-bottom: 0; } .thumbnails { margin-left: -20px; list-style: none; *zoom: 1; } .thumbnails:before, .thumbnails:after { display: table; content: ""; } .thumbnails:after { clear: both; } .thumbnails > li { float: left; margin: 0 0 18px 20px; } .thumbnail { display: block; padding: 4px; line-height: 1; border: 1px solid #ddd; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); } a.thumbnail:hover { border-color: #0088cc; -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); } .thumbnail > img { display: block; max-width: 100%; margin-left: auto; margin-right: auto; } .thumbnail .caption { padding: 9px; } .label { padding: 1px 3px 2px; font-size: 9.75px; font-weight: bold; color: #ffffff; text-transform: uppercase; background-color: #999999; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .label-important { background-color: #b94a48; } .label-warning { background-color: #f89406; } .label-success { background-color: #468847; } .label-info { background-color: #3a87ad; } @-webkit-keyframes progress-bar-stripes { from { background-position: 0 0; } to { background-position: 40px 0; } } @-moz-keyframes progress-bar-stripes { from { background-position: 0 0; } to { background-position: 40px 0; } } @keyframes progress-bar-stripes { from { background-position: 0 0; } to { background-position: 40px 0; } } .progress { overflow: hidden; height: 18px; margin-bottom: 18px; background-color: #f7f7f7; background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: linear-gradient(top, #f5f5f5, #f9f9f9); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0); -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .progress .bar { width: 0; height: 18px; color: #ffffff; font-size: 12px; text-align: center; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #0e90d2; background-image: -moz-linear-gradient(top, #149bdf, #0480be); background-image: -ms-linear-gradient(top, #149bdf, #0480be); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); background-image: -webkit-linear-gradient(top, #149bdf, #0480be); background-image: -o-linear-gradient(top, #149bdf, #0480be); background-image: linear-gradient(top, #149bdf, #0480be); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0); -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-transition: width 0.6s ease; -moz-transition: width 0.6s ease; -ms-transition: width 0.6s ease; -o-transition: width 0.6s ease; transition: width 0.6s ease; } .progress-striped .bar { background-color: #62c462; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -webkit-background-size: 40px 40px; -moz-background-size: 40px 40px; -o-background-size: 40px 40px; background-size: 40px 40px; } .progress.active .bar { -webkit-animation: progress-bar-stripes 2s linear infinite; -moz-animation: progress-bar-stripes 2s linear infinite; animation: progress-bar-stripes 2s linear infinite; } .progress-danger .bar { background-color: #dd514c; background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); background-image: linear-gradient(top, #ee5f5b, #c43c35); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); } .progress-danger.progress-striped .bar { background-color: #ee5f5b; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-success .bar { background-color: #5eb95e; background-image: -moz-linear-gradient(top, #62c462, #57a957); background-image: -ms-linear-gradient(top, #62c462, #57a957); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); background-image: -webkit-linear-gradient(top, #62c462, #57a957); background-image: -o-linear-gradient(top, #62c462, #57a957); background-image: linear-gradient(top, #62c462, #57a957); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); } .progress-success.progress-striped .bar { background-color: #62c462; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-info .bar { background-color: #4bb1cf; background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); background-image: -o-linear-gradient(top, #5bc0de, #339bb9); background-image: linear-gradient(top, #5bc0de, #339bb9); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); } .progress-info.progress-striped .bar { background-color: #5bc0de; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .accordion { margin-bottom: 18px; } .accordion-group { margin-bottom: 2px; border: 1px solid #e5e5e5; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .accordion-heading { border-bottom: 0; } .accordion-heading .accordion-toggle { display: block; padding: 8px 15px; } .accordion-inner { padding: 9px 15px; border-top: 1px solid #e5e5e5; } .carousel { position: relative; margin-bottom: 18px; line-height: 1; } .carousel-inner { overflow: hidden; width: 100%; position: relative; } .carousel .item { display: none; position: relative; -webkit-transition: 0.6s ease-in-out left; -moz-transition: 0.6s ease-in-out left; -ms-transition: 0.6s ease-in-out left; -o-transition: 0.6s ease-in-out left; transition: 0.6s ease-in-out left; } .carousel .item > img { display: block; line-height: 1; } .carousel .active, .carousel .next, .carousel .prev { display: block; } .carousel .active { left: 0; } .carousel .next, .carousel .prev { position: absolute; top: 0; width: 100%; } .carousel .next { left: 100%; } .carousel .prev { left: -100%; } .carousel .next.left, .carousel .prev.right { left: 0; } .carousel .active.left { left: -100%; } .carousel .active.right { left: 100%; } .carousel-control { position: absolute; top: 40%; left: 15px; width: 40px; height: 40px; margin-top: -20px; font-size: 60px; font-weight: 100; line-height: 30px; color: #ffffff; text-align: center; background: #222222; border: 3px solid #ffffff; -webkit-border-radius: 23px; -moz-border-radius: 23px; border-radius: 23px; opacity: 0.5; filter: alpha(opacity=50); } .carousel-control.right { left: auto; right: 15px; } .carousel-control:hover { color: #ffffff; text-decoration: none; opacity: 0.9; filter: alpha(opacity=90); } .carousel-caption { position: absolute; left: 0; right: 0; bottom: 0; padding: 10px 15px 5px; background: #333333; background: rgba(0, 0, 0, 0.75); } .carousel-caption h4, .carousel-caption p { color: #ffffff; } .hero-unit { padding: 60px; margin-bottom: 30px; background-color: #f5f5f5; -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; } .hero-unit h1 { margin-bottom: 0; font-size: 60px; line-height: 1; letter-spacing: -1px; } .hero-unit p { font-size: 18px; font-weight: 200; line-height: 27px; } .pull-right { float: right; } .pull-left { float: left; } .hide { display: none; } .show { display: block; } .invisible { visibility: hidden; } /*! * Bootstrap Responsive v2.0.0 * * Copyright 2012 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */ .hidden { display: none; visibility: hidden; } @media (max-width: 480px) { .nav-collapse { -webkit-transform: translate3d(0, 0, 0); } .page-header h1 small { display: block; line-height: 18px; } input[class*="span"], select[class*="span"], textarea[class*="span"], .uneditable-input { display: block; width: 100%; height: 28px; /* Make inputs at least the height of their button counterpart */ /* Makes inputs behave like true block-level elements */ -webkit-box-sizing: border-box; /* Older Webkit */ -moz-box-sizing: border-box; /* Older FF */ -ms-box-sizing: border-box; /* IE8 */ box-sizing: border-box; /* CSS3 spec*/ } .input-prepend input[class*="span"], .input-append input[class*="span"] { width: auto; } input[type="checkbox"], input[type="radio"] { border: 1px solid #ccc; } .form-horizontal .control-group > label { float: none; width: auto; padding-top: 0; text-align: left; } .form-horizontal .controls { margin-left: 0; } .form-horizontal .control-list { padding-top: 0; } .form-horizontal .form-actions { padding-left: 10px; padding-right: 10px; } .modal { position: absolute; top: 10px; left: 10px; right: 10px; width: auto; margin: 0; } .modal.fade.in { top: auto; } .modal-header .close { padding: 10px; margin: -10px; } .carousel-caption { position: static; } } @media (max-width: 768px) { .container { width: auto; padding: 0 20px; } .row-fluid { width: 100%; } .row { margin-left: 0; } .row > [class*="span"], .row-fluid > [class*="span"] { float: none; display: block; width: auto; margin: 0; } } @media (min-width: 768px) and (max-width: 980px) { .row { margin-left: -20px; *zoom: 1; } .row:before, .row:after { display: table; content: ""; } .row:after { clear: both; } [class*="span"] { float: left; margin-left: 20px; } .span1 { width: 42px; } .span2 { width: 104px; } .span3 { width: 166px; } .span4 { width: 228px; } .span5 { width: 290px; } .span6 { width: 352px; } .span7 { width: 414px; } .span8 { width: 476px; } .span9 { width: 538px; } .span10 { width: 600px; } .span11 { width: 662px; } .span12, .container { width: 724px; } .offset1 { margin-left: 82px; } .offset2 { margin-left: 144px; } .offset3 { margin-left: 206px; } .offset4 { margin-left: 268px; } .offset5 { margin-left: 330px; } .offset6 { margin-left: 392px; } .offset7 { margin-left: 454px; } .offset8 { margin-left: 516px; } .offset9 { margin-left: 578px; } .offset10 { margin-left: 640px; } .offset11 { margin-left: 702px; } .row-fluid { width: 100%; *zoom: 1; } .row-fluid:before, .row-fluid:after { display: table; content: ""; } .row-fluid:after { clear: both; } .row-fluid > [class*="span"] { float: left; margin-left: 2.762430939%; } .row-fluid > [class*="span"]:first-child { margin-left: 0; } .row-fluid .span1 { width: 5.801104972%; } .row-fluid .span2 { width: 14.364640883%; } .row-fluid .span3 { width: 22.928176794%; } .row-fluid .span4 { width: 31.491712705%; } .row-fluid .span5 { width: 40.055248616%; } .row-fluid .span6 { width: 48.618784527%; } .row-fluid .span7 { width: 57.182320438000005%; } .row-fluid .span8 { width: 65.74585634900001%; } .row-fluid .span9 { width: 74.30939226%; } .row-fluid .span10 { width: 82.87292817100001%; } .row-fluid .span11 { width: 91.436464082%; } .row-fluid .span12 { width: 99.999999993%; } input.span1, textarea.span1, .uneditable-input.span1 { width: 32px; } input.span2, textarea.span2, .uneditable-input.span2 { width: 94px; } input.span3, textarea.span3, .uneditable-input.span3 { width: 156px; } input.span4, textarea.span4, .uneditable-input.span4 { width: 218px; } input.span5, textarea.span5, .uneditable-input.span5 { width: 280px; } input.span6, textarea.span6, .uneditable-input.span6 { width: 342px; } input.span7, textarea.span7, .uneditable-input.span7 { width: 404px; } input.span8, textarea.span8, .uneditable-input.span8 { width: 466px; } input.span9, textarea.span9, .uneditable-input.span9 { width: 528px; } input.span10, textarea.span10, .uneditable-input.span10 { width: 590px; } input.span11, textarea.span11, .uneditable-input.span11 { width: 652px; } input.span12, textarea.span12, .uneditable-input.span12 { width: 714px; } } @media (max-width: 980px) { body { padding-top: 0; } .navbar-fixed-top { position: static; margin-bottom: 18px; } .navbar-fixed-top .navbar-inner { padding: 5px; } .navbar .container { width: auto; padding: 0; } .navbar .brand { padding-left: 10px; padding-right: 10px; margin: 0 0 0 -5px; } .navbar .nav-collapse { clear: left; } .navbar .nav { float: none; margin: 0 0 9px; } .navbar .nav > li { float: none; } .navbar .nav > li > a { margin-bottom: 2px; } .navbar .nav > .divider-vertical { display: none; } .navbar .nav > li > a, .navbar .dropdown-menu a { padding: 6px 15px; font-weight: bold; color: #999999; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .navbar .dropdown-menu li + li a { margin-bottom: 2px; } .navbar .nav > li > a:hover, .navbar .dropdown-menu a:hover { background-color: #222222; } .navbar .dropdown-menu { position: static; top: auto; left: auto; float: none; display: block; max-width: none; margin: 0 15px; padding: 0; background-color: transparent; border: none; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } .navbar .dropdown-menu:before, .navbar .dropdown-menu:after { display: none; } .navbar .dropdown-menu .divider { display: none; } .navbar-form, .navbar-search { float: none; padding: 9px 15px; margin: 9px 0; border-top: 1px solid #222222; border-bottom: 1px solid #222222; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); } .navbar .nav.pull-right { float: none; margin-left: 0; } .navbar-static .navbar-inner { padding-left: 10px; padding-right: 10px; } .btn-navbar { display: block; } .nav-collapse { overflow: hidden; height: 0; } } @media (min-width: 980px) { .nav-collapse.collapse { height: auto !important; } } @media (min-width: 1200px) { .row { margin-left: -30px; *zoom: 1; } .row:before, .row:after { display: table; content: ""; } .row:after { clear: both; } [class*="span"] { float: left; margin-left: 30px; } .span1 { width: 70px; } .span2 { width: 170px; } .span3 { width: 270px; } .span4 { width: 370px; } .span5 { width: 470px; } .span6 { width: 570px; } .span7 { width: 670px; } .span8 { width: 770px; } .span9 { width: 870px; } .span10 { width: 970px; } .span11 { width: 1070px; } .span12, .container { width: 1170px; } .offset1 { margin-left: 130px; } .offset2 { margin-left: 230px; } .offset3 { margin-left: 330px; } .offset4 { margin-left: 430px; } .offset5 { margin-left: 530px; } .offset6 { margin-left: 630px; } .offset7 { margin-left: 730px; } .offset8 { margin-left: 830px; } .offset9 { margin-left: 930px; } .offset10 { margin-left: 1030px; } .offset11 { margin-left: 1130px; } .row-fluid { width: 100%; *zoom: 1; } .row-fluid:before, .row-fluid:after { display: table; content: ""; } .row-fluid:after { clear: both; } .row-fluid > [class*="span"] { float: left; margin-left: 2.564102564%; } .row-fluid > [class*="span"]:first-child { margin-left: 0; } .row-fluid .span1 { width: 5.982905983%; } .row-fluid .span2 { width: 14.529914530000001%; } .row-fluid .span3 { width: 23.076923077%; } .row-fluid .span4 { width: 31.623931624%; } .row-fluid .span5 { width: 40.170940171000005%; } .row-fluid .span6 { width: 48.717948718%; } .row-fluid .span7 { width: 57.264957265%; } .row-fluid .span8 { width: 65.81196581200001%; } .row-fluid .span9 { width: 74.358974359%; } .row-fluid .span10 { width: 82.905982906%; } .row-fluid .span11 { width: 91.45299145300001%; } .row-fluid .span12 { width: 100%; } input.span1, textarea.span1, .uneditable-input.span1 { width: 60px; } input.span2, textarea.span2, .uneditable-input.span2 { width: 160px; } input.span3, textarea.span3, .uneditable-input.span3 { width: 260px; } input.span4, textarea.span4, .uneditable-input.span4 { width: 360px; } input.span5, textarea.span5, .uneditable-input.span5 { width: 460px; } input.span6, textarea.span6, .uneditable-input.span6 { width: 560px; } input.span7, textarea.span7, .uneditable-input.span7 { width: 660px; } input.span8, textarea.span8, .uneditable-input.span8 { width: 760px; } input.span9, textarea.span9, .uneditable-input.span9 { width: 860px; } input.span10, textarea.span10, .uneditable-input.span10 { width: 960px; } input.span11, textarea.span11, .uneditable-input.span11 { width: 1060px; } input.span12, textarea.span12, .uneditable-input.span12 { width: 1160px; } .thumbnails { margin-left: -30px; } .thumbnails > li { margin-left: 30px; } } @import url(bootstrap.min.css); @import url(bootstrap-responsive.css); @import url(prettify.css); @import url(../../../../build/api/css/jquery.iviewer.css); @import url(http://fonts.googleapis.com/css?family=Crimson+Text|Philosopher|Forum); body { padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */ background: #f9f9f9; color: #444; } a { color: #55A72F; } li.l0, li.l1, li.l2, li.l3, li.l5, li.l6, li.l7, li.l8 { list-style-type: decimal; } a.brand, h2, .hero-unit h1 { font-family: 'Forum', "Helvetica Neue", Helvetica, Arial, sans-serif; } .element .span4 { width: 275px; } .namespace-contents hr, .package-contents hr { border-top: 3px dotted silver; } .namespace-indent, .package-indent { padding-left: 10px; border-left: 1px dashed #f0f0f0; } .element h3 i, .namespace-contents h3 i, .package-contents h3 i { margin-top: 2px; margin-right: 5px; } .element h3, .namespace-contents h3, .package-contents h3 { margin-top: 25px; margin-bottom: 20px; border-bottom: 1px solid silver; } .element h3:first-of-type, .namespace-contents h3:first-of-type, .package-contents h3:first-of-type { margin-top: 30px; } .element h2 { font-family: inherit; font-size: 1.2em; color: black; } .element .type { font-weight: bold; } #search-query { height: auto; } .hero-unit, div.element, .well { border: 1px solid #e0e0e0; background: white; } h2 { border-bottom: 1px dashed #55A72F; margin-bottom: 10px; padding-bottom: 0; padding-left: 5px; color: #e9e9e9; font-weight: normal; margin-top: 40px; } h2:first-of-type { margin-top: 0; } .hero-unit { background: #75a70d; /* Old browsers */ background: -moz-radial-gradient(center, ellipse cover, #bfd255 0%, #8eb92a 72%, #72aa00 96%, #9ecb2d 100%); /* FF3.6+ */ background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,#bfd255), color-stop(72%,#8eb92a), color-stop(96%,#72aa00), color-stop(100%,#9ecb2d)); /* Chrome,Safari4+ */ background: -webkit-radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* Chrome10+,Safari5.1+ */ background: -o-radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* Opera 12+ */ background: -ms-radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* IE10+ */ background: radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#bfd255', endColorstr='#9ecb2d',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */ padding: 40px 0 15px 0; box-shadow: inset 0 0 10px gray; } .hero-unit h1 { text-align: center; font-weight: normal; color: white; text-shadow: black 0 0 15px; } .hero-unit h2 { border: none; color: white; background: rgba(48, 48, 48, 0.5); padding: 0; margin: 0; margin-top: 15px; text-align: center; } .namespace-contents h2, .package-contents h2 { padding-left: 44px; background: transparent url('../../../../build/api/img/icons/icon-th-big.png') no-repeat 3px center; } .package-contents h2 { background-image: url('../../../../build/api/img/icons/icon-folder-open-big.png'); } .namespace-contents .element h2, .package-contents .element h2 { padding-left: 0; background: none; } div.element { border-left: 10px solid #55A72F; border-radius: 5px; padding: 7px 7px 2px 7px; margin-bottom: 15px; margin-left: 0; } div.element.protected { border-left-color: orange; } div.element.private { border-left-color: red; } div.element.class, div.element.interface { border-left-color: #e0e0e0; } div.element.class.abstract h1, div.element.interface.abstract h1 { font-style: italic; } div.element h1 { font-size: 1.2em; line-height: 1.5em; margin-bottom: 10px; padding-left: 22px; background: transparent no-repeat left 2px; word-wrap: break-word; } div.element h1 a { color: transparent; margin-left: 10px; } div.element h1:hover a { color: silver; } div.element h1 a:hover { color: navy; } div.element a.more:hover { background: #f0f0f0; color: #444; text-decoration: none; } div.element a.more { font-weight: bold; text-align: center; color: gray; border-top: 1px dashed silver; display: block; margin-top: 5px; padding: 5px 0; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; } div.element p { font-size: 0.9em; } div.element .table { font-size: 0.9em; } div.element .table th { text-transform: capitalize; } div.detail-description { padding-left: 30px; } body.invert { background: white; } body.invert div.element { background: #f9f9f9; } ul.side-nav { clear: both; } ul.side-nav li { word-wrap: break-word; padding-left: 10px; text-indent: -10px; } ul.side-nav li a { background: transparent no-repeat 5px 3px; padding-bottom: 10px; font-style: italic; } ul.side-nav li pre { font-size: 0.8em; margin: 5px 15px 0 15px; padding: 2px 5px; background-color: #f8f8f8; color: gray; font-style: normal; word-wrap: break-word; text-indent: 0; } ul.side-nav li.view-simple span.description { display: none; } ul.side-nav li.view-simple pre { font-size: inherit; margin: inherit; padding: inherit; background-color: inherit; border: none; color: inherit; font-family: inherit; font-style: inherit; padding-bottom: 0; padding-left: 5px; } ul.side-nav li.view-simple a { padding-bottom: 0; } i.icon-custom { width: 16px; height: 16px; background-position: 0; } .table.markers { background: white; } /* JS only functionality; disable by default */ .btn-group.visibility, .btn-group.view, .btn-group.type-filter { display: none; } .btn-group.view { margin-left: 20px; margin-bottom: 20px; } .visibility button { height: 24px; } div.element.constant h1, i.icon-constant { background-image: url('../../../../build/api/img/icons/constant.png'); } div.element.function h1, i.icon-function { background-image: url('../../../../build/api/img/icons/function.png'); } div.element.method h1, i.icon-method { background-image: url('../../../../build/api/img/icons/method.png'); } div.element.class h1, i.icon-class { background-image: url('../../../../build/api/img/icons/class.png'); } div.element.interface h1, i.icon-interface { background-image: url('../../../../build/api/img/icons/interface.png'); } div.element.property h1, i.icon-property { background-image: url('../../../../build/api/img/icons/property.png'); } i.icon-show-public { background-image: url('../../../../build/api/img/icons/visibility_public.png'); } i.icon-show-protected { background-image: url('../../../../build/api/img/icons/visibility_protected.png'); } i.icon-show-private { background-image: url('../../../../build/api/img/icons/visibility_private.png'); } span.empty-namespace { color: silver; } footer { text-align: right; font-size: 0.8em; opacity: 0.5; } #mapHolder { border: 4px solid #555; padding: 0 !important; overflow: hidden } div.element div.subelement { margin-left: 10px; padding-bottom: 5px; } pre code { border: none; } div.element div.subelement > code { font-size: 0.8em; float: left; margin-right: 10px; padding: 0 5px; line-height: 16px; } div.element div.subelement > p { margin-left: 20px; margin-right: 40px; } div.element div.subelement h4 { color: #666; margin-bottom: 5px; } div.element div.subelement.response { padding-bottom: 15px; } div.labels { text-align: right; } .nav-list .nav-header { font-size: 13px; } .go_to_top { float: right; margin-right: 20px; background: #2C2C2C; color: #999; padding: 3px 10px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); line-height: 19px; } .visibility .btn { text-transform: uppercase; font-size: 0.7em; font-weight: bold; } @media (min-width: 980px) { a[name] { margin-top: -50px; position: absolute; } } @media (min-width: 1200px) { .method .span4 { width: 345px; } } /* redefined because twitter bootstrap assumes that bootstrap-responsive.css */ @media (max-width: 980px) { body { padding-top: 0; } .go_to_top { display: none; } .btn-group.visibility { font-size: 0.80em; margin-bottom: 7px; display: block; float: right; } } @media (max-width: 768px) { .hero-unit h1 { font-size: 30px; } .hero-unit h2 { font-size: 19px; } } @media (min-width: 768px) and (max-width: 980px) { .method .span4 { width: 203px; } } .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}img.center { display: block; margin: 0 auto; } h1, h2, h3 { color: #464; } h1 { font-family: 'Forum', "Helvetica Neue", Helvetica, Arial, sans-serif; } h2 { padding: 0; margin-top: 10px; } h3 { font-weight: normal; } blockquote p { font-size: 13px; } .warning { padding : 8px 35px 8px 14px; margin-bottom: 18px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); background-color: #fcf8e3; border: 1px solid #fbeed5; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; }PNG  IHDR:PLTE333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333gT+tRNS/_?MOo ثKHuÓ'*zǽ̎sIDATx^흉r8h_fMp+̹J`pjt**qo }H)B~uY-o2Jl!aOpŷVcqJHR`f(WQY&)A^蜫/dկqX+bFcOS!paTUJwpIdt;fX^d|M/ LUZk!k [s#v[n'//j3Ǡw_ _/UOT=S^QooR;U|*Ugi[YsTfgXq}ہx?] R5j*IrH;z] Xȕ~(O+AEjSJۿ͈@DZT THUBGHl;??_v8 ށdg( _S@RXcx }Ș{vˎ+N5=ƥM^{sgcq#ϖsw*͖S}Tɒ+6L1ogl~ryenc e`5 u9!C0T 5j\]r.q_9p*߅hSm%a%T-JS>pʿO*)<$TerXK]ՕSgBv!miGzkdͫKJX|7ˑj:q36kqt8GՒ 2NSϹNeȽk[1_yT9NFKqpίňjQ`(TDʤ4D\-/- 6~T=Vy* AJFFҤq!/ b3C}@ط f-5jמ)$'@ހc|*䠯z@Z+ >#)[~OcDq_ux;E5{3)/Ry!"_T=MZ* FGfF8qo3a>8>NvʑF(4zQ}7T[~^i`>^CQF80KO\s%t5TUi:7Mq"@,\Gy幞jã<([omխsk>*"Tg'@q,ƙ#\g ْk̖:[uKWt l)%8UGW[߫JuV6TϻTUTӸuUG̾*귻 28^_uu1U1U.|'KH!ʋ,ozj^TS)I9gG=]k#|Du֩z5pru7(f?<-#e ՚zW߉EYE1m2oӳrgʸҚOv*VlS=YlP$!<.QM@OU>g6KPVlɬԷ>["vm0 ?>=Vhoٱnw!̰heK\@ҧKO<7z\Sgρ8mTR?7 mkޅ5mUۄPz?Sݩ|ϓCWY]]]]]]]]]]]]]]]]]]]m ]n_C{.[ THR#k0]bF>RˇZ~d @=xd~S0 @RvZA4-SO.a*U֠ $910v{Oȥo%9+f.@@AN3<0X~WT.o|p}0v}'~Tac1Zv^Lgu|K ?Gj1',UU_dTalL]~:C=CP4J`°Qݠ2 &nz&CDuJۻTa* ŧPe26T0}Q 'P D[Ne@:|*Ws|q]i rQZ#pcZ.俩H"?:xIpU[ 5ӈjLq SIPig*O{U׿W =[ `O7|Z|9% ):d+'Bl=EZnziՐlʺ^-0O+-\[|^Oi˷-oyoɾD%]dxg.z|f=>*8mq~_e2ɛ25]A5:"#Jyp>X=4+~"4VR?C0<.ޢj@tK/ٶM5zyDs7yKYFkݏAW%#Z$zjqkosEDB:HoiM39_,tt#Ύ޲6b=O;sG9Mu|qXO\ԍ|6yDG>G /"Pn?bO3v~1G{UT'W(|؃X+='Um*e`"N+U%JqDlߌ瓳T!>Syc%qoa/IB~ZxWJydFGj5fKlz+. bUoU͇ 9 Hqx˳Ϛ-}IW6H/J|ڜ ]^+kF]=}N 48E5r2ryVSe]oD/E8T3E &./g믿ַo|>ɭ?l2:cE0?EAkA쬣fsy??'u`D!h?*bƅQ,UmxO)zk{71LY&/7:rJt!PPC|39\YRea7r7ztyj}}sGy*{e]do}fX\3Uj{^`)z/7^V9.$`,LIu0SeM{xFydQ=JnߴJ&z Lot*&Yli%r*;ݢ)K5,U%{Lut)z|d?[QAF8g4vXQA5. {>LK9iDʥuG TngKȴg ") is յ[o&~ZS(DMʀ*i+ʔ`\; s敍eh+k!~ J.lvˎ+N5=ƥM^{sgcq#ϖsw*͖S}Tɒ+6L1ogl~ryenc e`5 u9!C0T 5j\]r.q_9p*߅hSm%a%T-JS>pʿO*)<$TerXK]ՕSgBv!miGzkdͫKJX|7ˑj:q36kqt8GՒ 2NSϹNeȽk[1_yT9NFKqpίňjQ`(TDʤ4D\-/- 6~T=Vy* AJFFҤq!/ b3C}@ط f-5jמ)$'@ހc|*䠯z@Z+ >#)[~OcDq_ux;E5{3)/Ry!"_T=MZ* FGfF8qo3a>8>NvʑF(4zQ}7T[~^i`>^CQF80KO\s%t5TUi:7Mq"@,\Gy幞jã<([omխsk>*"Tg'@q,ƙ#\g ْk̖:[uKWt l)%8UGW[߫JuV6TϻTUTӸuUG̾*귻 28^_uu1U1U.|'KH!ʋ,ozj^TS)I9gG=]k#|Du֩z5pru7(f?<-#e ՚zW߉EYE1m2oӳrgʸҚOv*VlS=YlP$!<.QM@OU>g6KPVlɬԷ>["vm0 ?>=Vhoٱnw!̰heK\@ҧKO<7z\Sgρ8mTR?7 mkޅ5mUۄPz?Sݩ|ϓCWY]]]]]]]]]]]]]]]]]]]m ]n_C{.[ THR#k0]bF>RˇZ~d @=xd~S0 @RvZA4-SO.a*U֠ $910v{Oȥo%9+f.@@AN3<0X~WT.o|p}0v}'~Tac1Zv^Lgu|K ?Gj1',UU_dTalL]~:C=CP4J`°Qݠ2 &nz&CDuJۻTa* ŧPe26T0}Q 'P D[Ne@:|*Ws|q]i rQZ#pcZ.俩H"?:xIpU[ 5ӈjLq SIPig*O{U׿W =[ `O7|Z|9% ):d+'Bl=EZnziՐlʺ^-0O+-\[|^Oi˷-oyoɾD%]dxg.z|f=>*8mq~_e2ɛ25]A5:"#Jyp>X=4+~"4VR?C0<.ޢj@tK/ٶM5zyDs7yKYFkݏAW%#Z$zjqkosEDB:HoiM39_,tt#Ύ޲6b=O;sG9Mu|qXO\ԍ|6yDG>G /"Pn?bO3v~1G{UT'W(|؃X+='Um*e`"N+U%JqDlߌ瓳T!>Syc%qoa/IB~ZxWJydFGj5fKlz+. bUoU͇ 9 Hqx˳Ϛ-}IW6H/J|ڜ ]^+kF]=}N 48E5r2ryVSe]oD/E8T3E &./g믿ַo|>ɭ?l2:cE0?EAkA쬣fsy??'u`D!h?*bƅQ,UmxO)zk{71LY&/7:rJt!PPC|39\YRea7r7ztyj}}sGy*{e]do}fX\3Uj{^`)z/7^V9.$`,LIu0SeM{xFydQ=JnߴJ&z Lot*&Yli%r*;ݢ)K5,U%{Lut)z|d?[QAF8g4vXQA5. {>LK9iDʥuG TngKȴg ") is յ[o&~ZS(DMʀ*i+ʔ`\; s敍eh+k!~ J.lk6S2S7\3U1S1M!9f8g/P.S%>l3MymwPX.M8ZsH[<]7YP^Y\'Ao(>g0U*L0Y7e0N9Vv *`.K$?p!9d)I/P2\2Kx8W7Xr{)7m3R8Q~(?g!2R/Q*?h8Q|0MNZ8S=V(?h&8X3V)Cl5Ox>[!3cUfp8U*Fq+Bi$6X0Cb5Ov=UOiFd1@jC`Ok9Qy*Em+?]1Ea6QuD_=X~iLkMkMkIk`|GbA[>X8Lh(?a>UvEbHaQnztId;V|Li>Uv4IjF[}KdJdNjLgUsRm;a:aQmHiPkLfCZ~JdBUw.D]ToRnLgOmSm[x[xNm\yPlKeNg?Vv/#%*0KcG[IdGaD\PgOgNgG`LeJcF\#&+1GIF89a\\z\yӗߴ! NETSCAPE2.0!"Created with Chimply.com"! ,\\h0I8ͻ`h dih)VCp<3 ԴPfNx&h;piSiK0RjH$|Ϣ:vJS,R( E;G {O. rޭw߿ È+@LJ;Lyd3YsE)se?E.m2Ꜫn 6jܿw[6p‡'xʗM3S;;SÆn|+7|7_Ya7`Z}6lj܁mg g Wjȡa(A! ,\\h0I8ͻ`(8hCIp,s,U|PhO:a#.\6è47VXvz}lLF@is%_zN`y{s~mpjdga[^XR_r|kuve]yLPn;OGVFJNSY-t.17Ák0 \0Zb;YdWō c=ܘ.䭏MA Q% ]I84kޤkH A t M=tիXj ׯ`Êݺ@ٳ_X˶۷n;Vܻxʥ˷ڼKoD5 Ἁ-f<㻑 N|巙n\g&d@ӘS~ڬgzegtP4n 6"j6򓣗7?|et?Wywg*_8K[nk?~uY~ٷ A5P/~_k!VM[ `T݀iY (S ! ,\\h0I8ͻ`(di%lVE,ϴL8=<0UaMId6:#PʴYv>2ꍁѫqS=?te~lm}p|^hAfXwxkmnvDu8{aK~(H$ײW3T_ݴHM>YHp"C],~)Hlɖ^œI͛8ɳϟ@sJH*]tiP*hJ*jʵVQm'-O}'e7PxlX~ `di=%N9eF! ,\\h0I8ͻ`(diYl+l[=sӕ'\"l42ISyFSdl?0歹xpWjsdn9sl:oun=kztv|{r2xC@~-) ºǾ̹̩ҨɧpG` COa=Nb:,8O_@{ZӸc;yeJ&Lh59xY}*t(ϢH*]Z,ӧPJʴԫX6ׯ`J*h>۷p@(K7ִxܺdͻa>;Ç**1J,e3z֜tgƨA^=kӰcn@ۯZs7ۧu}uW7/ut9W|=s-w]q#~~pzw̻u}?]+jfb}_eb&(V*>UՆvᇲ$! ,\\h0I8ͻ`xudhi+p γWpHC:NrijFkB: x꒬B6=5su~@9]5yb|}p{x}ZztWQOlwsejuRn;ƾ ͬ50*ڽSo :0&h0D :)te1= Kkɓ+42̕(IXC9[|ϋE;x/KMA<*b*իXjʵWŠKد̪]`۷pm]m߿N{p޽B̘1v'۷e!<˖3k.˹3ʠGցiʟS מV ҸQK7‡(^Ùvn飩O.f퉹x9^2Ha$K<ʕ:ztR KQ4k*N|JKK24cʥHUL|ȩ%^ R!X#úS8ʝKݻx˷ L +6ǐ#Gfƒ3Kue˘5&٩ϋC\ԩ!i؅Uφ\kܹe,ou']q䁕9t黩lA|Qɏ64—?f/=lv>z|4E`}VAП8~هAQH? ؇ ($h] ! ,\\h0I8ͻ`&di蹀l9B,t-7i0PM:o4\OgqZ[,1*-h`c%8xN/9pzj}1m%L|4Ty}ztwqknhbe_Y\VOSKuHP<Ǎ ʐvͿJCRiGWF.~ ͊"/{ H*\XpÇ#Jċ+FBIR$?\I$J*Yt2F3'ԼgI;!9hPC4z4RASO5RkN G#zeؕeSTZTgXk.ub\i9IdžuLÈ+^̸ǐ#K쀀˘3g\Ag -@Ϩ-Mi S;ؠ%n]6ͺ{~ S_-nϿJh*lX^;p,Y\WmRo-%9ٰ#E`…;Na1ǐ#KL˘3kPϠ=SMҨ-N=auӮMW6ζo-5oܾwnÍ׽ǖ:9s У78vW[w{㹗Wgy_wg<0~푗iWz֠l — ~6ev ( $;!function(a){a(function(){"use strict",a.support.transition=function(){var b=document.body||document.documentElement,c=b.style,d=c.transition!==undefined||c.WebkitTransition!==undefined||c.MozTransition!==undefined||c.MsTransition!==undefined||c.OTransition!==undefined;return d&&{end:function(){var b="TransitionEnd";return a.browser.webkit?b="webkitTransitionEnd":a.browser.mozilla?b="transitionend":a.browser.opera&&(b="oTransitionEnd"),b}()}}()})}(window.jQuery),!function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype={constructor:c,close:function(b){function f(){e.remove(),e.trigger("closed")}var c=a(this),d=c.attr("data-target"),e;d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),e=a(d),e.trigger("close"),b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.on(a.support.transition.end,f):f()}},a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("alert");e||d.data("alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a(function(){a("body").on("click.alert.data-api",b,c.prototype.close)})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype={constructor:b,setState:function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a+="Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},toggle:function(){var a=this.$element.parent('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")}},a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a(function(){a("body").on("click.button.data-api","[data-toggle^=button]",function(b){a(b.target).button("toggle")})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.carousel.defaults,c),this.options.slide&&this.slide(this.options.slide)};b.prototype={cycle:function(){return this.interval=setInterval(a.proxy(this.next,this),this.options.interval),this},to:function(b){var c=this.$element.find(".active"),d=c.parent().children(),e=d.index(c),f=this;if(b>d.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){f.to(b)}):e==b?this.pause().cycle():this.slide(b>e?"next":"prev",a(d[b]))},pause:function(){return clearInterval(this.interval),this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(b,c){var d=this.$element.find(".active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this;return this.sliding=!0,f&&this.pause(),e=e.length?e:this.$element.find(".item")[h](),!a.support.transition&&this.$element.hasClass("slide")?(this.$element.trigger("slide"),d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")):(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),this.$element.trigger("slide"),this.$element.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)})),f&&this.cycle(),this}},a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("carousel"),f=typeof c=="object"&&c;e||d.data("carousel",e=new b(this,f)),typeof c=="number"?e.to(c):typeof c=="string"||(c=f.slide)?e[c]():e.cycle()})},a.fn.carousel.defaults={interval:5e3},a.fn.carousel.Constructor=b,a(function(){a("body").on("click.carousel.data-api","[data-slide]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=!e.data("modal")&&a.extend({},e.data(),c.data());e.carousel(f),b.preventDefault()})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.collapse.defaults,c),this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.prototype={constructor:b,dimension:function(){var a=this.$element.hasClass("width");return a?"width":"height"},show:function(){var b=this.dimension(),c=a.camelCase(["scroll",b].join("-")),d=this.$parent&&this.$parent.find(".in"),e;d&&d.length&&(e=d.data("collapse"),d.collapse("hide"),e||d.data("collapse",null)),this.$element[b](0),this.transition("addClass","show","shown"),this.$element[b](this.$element[0][c])},hide:function(){var a=this.dimension();this.reset(this.$element[a]()),this.transition("removeClass","hide","hidden"),this.$element[a](0)},reset:function(a){var b=this.dimension();this.$element.removeClass("collapse")[b](a||"auto")[0].offsetWidth,this.$element.addClass("collapse")},transition:function(b,c,d){var e=this,f=function(){c=="show"&&e.reset(),e.$element.trigger(d)};this.$element.trigger(c)[b]("in"),a.support.transition&&this.$element.hasClass("collapse")?this.$element.one(a.support.transition.end,f):f()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("collapse"),f=typeof c=="object"&&c;e||d.data("collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.defaults={toggle:!0},a.fn.collapse.Constructor=b,a(function(){a("body").on("click.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e).data("collapse")?"toggle":c.data();a(e).collapse(f)})})}(window.jQuery),!function(a){function d(){a(b).parent().removeClass("open")}"use strict";var b='[data-toggle="dropdown"]',c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),e=c.attr("data-target"),f,g;return e||(e=c.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,"")),f=a(e),f.length||(f=c.parent()),g=f.hasClass("open"),d(),!g&&f.toggleClass("open"),!1}},a.fn.dropdown=function(b){return this.each(function(){var d=a(this),e=d.data("dropdown");e||d.data("dropdown",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.dropdown.Constructor=c,a(function(){a("html").on("click.dropdown.data-api",d),a("body").on("click.dropdown.data-api",b,c.prototype.toggle)})}(window.jQuery),!function(a){function c(){var b=this,c=setTimeout(function(){b.$element.off(a.support.transition.end),d.call(b)},500);this.$element.one(a.support.transition.end,function(){clearTimeout(c),d.call(b)})}function d(a){this.$element.hide().trigger("hidden"),e.call(this)}function e(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); ;/* * jQuery UI Effects Fold 1.8.2 * * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Effects/Fold * * Depends: * jquery.effects.core.js */ (function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100* f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); ;/* * jQuery UI Effects Highlight 1.8.2 * * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Effects/Highlight * * Depends: * jquery.effects.core.js */ (function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); ;/* * jQuery UI Effects Pulsate 1.8.2 * * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Effects/Pulsate * * Depends: * jquery.effects.core.js */ (function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); b.dequeue()})})}})(jQuery); ;/** * Cookie plugin * * Copyright (c) 2006 Klaus Hartl (stilbuero.de) * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * */ /** * Create a cookie with the given name and value and other optional parameters. * * @example $.cookie('the_cookie', 'the_value'); * @desc Set the value of a cookie. * @example $.cookie('the_cookie', 'the_value', {expires: 7, path: '/', domain: 'jquery.com', secure: true}); * @desc Create a cookie with all available options. * @example $.cookie('the_cookie', 'the_value'); * @desc Create a session cookie. * @example $.cookie('the_cookie', null); * @desc Delete a cookie by passing null as value. * * @param String name The name of the cookie. * @param String value The value of the cookie. * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. * If set to null or omitted, the cookie will be a session cookie and will not be retained * when the the browser exits. * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will * require a secure protocol (like HTTPS). * @type undefined * * @name $.cookie * @cat Plugins/Cookie * @author Klaus Hartl/klaus.hartl@stilbuero.de */ /** * Get the value of a cookie with the given name. * * @example $.cookie('the_cookie'); * @desc Get the value of a cookie. * * @param String name The name of the cookie. * @return The value of the cookie. * @type String * * @name $.cookie * @cat Plugins/Cookie * @author Klaus Hartl/klaus.hartl@stilbuero.de */ jQuery.cookie = function(name, value, options) { if (typeof value != 'undefined') { // name and value given, set cookie options = options || {}; if (value === null) { value = ''; options.expires = -1; } var expires = ''; if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { var date; if (typeof options.expires == 'number') { date = new Date(); date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); } else { date = options.expires; } expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE } var path = options.path ? '; path=' + options.path : ''; var domain = options.domain ? '; domain=' + options.domain : ''; var secure = options.secure ? '; secure' : ''; document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); } else { // only name given, get cookie var cookieValue = null; if (document.cookie && document.cookie != '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) == (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } };/*! * jQuery JavaScript Library v1.4.2 * http://jquery.com/ * * Copyright 2010, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2010, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Sat Feb 13 22:33:48 2010 -0500 */ (function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& (d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== "find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
    a"; var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, "_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== "="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

    ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); (function(){var g=s.createElement("div");g.innerHTML="
    ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= {},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== "string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== 1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
    ","
    "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, ""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", ""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, "border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== "string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
    ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? "&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== 1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== "json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== "number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
    "; a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": "pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); PNG  IHDRd<?sRGBbKGD pHYs  tIME5vtpIDATx|y]Uop[ d B@Pldlyؾ[?g?|Si'4 22URTJR|{[$AUsN9gZ5#.XoK'\۱d*p^8swΜpNڡAz/T"# wޗ׀k ~%ݚu "{REt3 400_fd2Iַ~cO'8ӀDQwOt 3>-sQ;2ʮbKIh;u_{;t p?C`T܉ Dt%US_+I~?+(H꿻 ZlpxH@Gg0lcy.G D UDXY<̆+2tޅn}/ЧyqKq$>3L8T8 f*x1 r9|#׊;vu<̳6 `Tpo+ d= *e̸bj(!t"GEe ͞T۾;pTJV pTTƸ w*Ⓨ%ҙĎ 3a+p>?TP f.o]xk_^z1R H!0FGӻUup?6AV3HZAF˒uxČU^v0G3E/+$APE TJRJ XJAJQiY}f3=6=ꍀl6LČʥb(f ?.-PN#IؘI/O„eGCQ1ҔMY1syKUqjl'mʺ҇Rw_3VVC} =FgCшuUQi *ū8ݡm^എD{1AEs"Bq|/ ya4>ՇYёEI^h/#jh@MzT,yb=n*R% < 8gu Б IMtm59GJv|leL:겴tk\"De謝h;`a-EH$paa4̄)I&qLbzw*ʌMd.XK׍3]U뵷ю?+5Ec~r\NX"FTb9x,ʸ 5m"m(1".&WI!Si0)B"EL&H!R*kQY]b\?~2jNF4^īO=ںu)Ն ?#|-z]yYnߴ~- @CqH%TpwL.c(hrx<dY!}d"v#PF#Pb7q#`EcLtwKZpmQ0A0-$|C/ %xӸc};=ϛDD8β .":!BcL'^|a䂋ɧZ.V4>x̘"/V*4J%ah.hrA*괲lz!c3׉@dPH7MkDBDvAȱSyG> زeg иL6gIB c m?{&N0ٶ()08bbNCM"NPEET"Z(T5˴D0 E=!^Qg YU_aocr_D葞~t:Gwj^hV?pd+"[75`nxjɼ*׍([`<{y1Vϯ>G ~vt׶-U[lSK{B̝8[v1̚ߵl[a'‡1;lesHcBfz;}w5#n%9c&p7pO6>*ѐ_Rto mIV袋^| @RU^zd|o׮ǬZjQPx8sY=wgK8yfQ^1cKk֬/ZömL0wXɓ'v/7?M `4_J2{ ~~~s.`fەd,z.{O=uj὿ܾ}ە !>F\}Zys)Ĵm7j/1b_tY a,%0(!C_lWjFv=Cn׆kJJh-<8hZq\b|~L.K137q/-XGyǃgzc 8*++^r%?3/ݻBBy!DMMMn޼5;e.޽{[ B"\ׅeY]vݥ.) !(~/~v掫e͟?U/[~0 ±|O+:zzAI @؍ +1Xnwh "18Lvp^< Æ'k;^ 5b >W1[(VXaYΖeQPB@===3֯_ \."Z\.k׮9.F6Lٹse}}} "&"BbŊo566>?44= B>~7J9#c6!4} a.櫮 Ð Ğ=[Do_/XxGM 4}<' o2RH< gѦ$Y[JIgmM%IR)/_ʂFc:;;gg2D"Ú3WJi\QQA7tӷD; rwΝ8hѢ{n 1@Dŋo>}c |\kh>{k}}s#Ѭ OfMpr`.R`L -K/l8,5!İ\#,q{RPJ1B}}Y0[`*Nڀke@"Y `Р0F}KDI'KyI)qOம.y(`:,y뭿/ʞ0 cq) )1FZZH%!B0w 0Ch#A<AlX(jCh$,B</W#Ȑo9"DBGȺu?9ctHbf)TT܏j$hܱVh45.bRu| N[۷oP(@)5xA +̌H,h*]KDyd)4|?KTyc1e*Ə8x lmv_ǻbı\IL@rQr[C1\||.7< B)ߠk#s b,K'KGX_uh Y_3{{{g#!`)e!umRtXJxSA-g`GrCDU 5cR#Cw~Yvɏ <!s^\(uÃ>3/ `{}' c ۷ol[[Xc k;vkjj}'!$EֿHRJZsEg3fx˲xk6Zy- Le8 c٪v4}d`fa`/v744+Ֆ֬Ys{PjkkWkO(j}8aڿ͛+W^T’< 3f\gӦ{0gΧ8 'g;3?Yu?7iLvDcQ|/0С&m dG*S/|s, z2#k >'[PJK?…}+V=K'|7#SFx58&t*$$FjP#aaؼ.s9̘݈>tEG.OQ?Z9h(e1C^ٺˍΙyM084y^?E+) lC9/zɧW?A!xeAgڦ ke"Tְm3{,ANJM[w8=޴w m?=L<#?E\S@ m4*** pt7;ӿΞ;_wQy:}k!H:(#< bGwo,^T#qVRj)Q6☨> IXIu˞_{XIgCTv_GSjZ q~ [Ĝdri۶ڗ=򁃽oM:#?8$F2(ؿ !${/i@N>ENy_ xޜyawPB.P|xo #8C>qփ_?gɅ{1,i@dNqcU"B~RT) ^1Jӧy ڱWrwOzf0;)BJ -^V@-<˾oAwO/ǂ跈)qo-휥Ti5L+.m\S:kE)@z/yoo<ѓ_GWS9 [)r< `;CE\ /C?.2|BV ʟ.AOhw ߀tq_ _ɉ ~c d- 9P 3,@?;+0>/= >3|ҿ1\\=  d`蒿@# ~c🁑/x _xp H'@Fg?X` n} WW>mh+(:A_hb [Nܾq7 wM%W@A՗GBS%@̓7o:ߺ:AMI?k0]`|>%iBN3o=zӇRIY.e^&v`_@߅j'eB 3?|~L @fg4IENDB`PNG  IHDRasRGBbKGD pHYs  tIME_.IDAT8˥S=`~|$`F?С?PނSKNRGtE$^PP]P @d#oN7೜p2$X1dh3-kÐm)0i1qi.F66X <};x 1h2p ) `_gT hw bATǏ_д@0μ{ Ïo CA6} %7&,b%e`JԒМlf @| OpՇwx `.vk oP@__~>PLX 䔸֩ eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3bKGD pHYs  tIME&PIDAT8}kG3{ssosMjBRTP[Zčv#bݸu!..tU V;7I͇Ixg9]܏. ss0f} ^}5_\>r򞝚XXK۩_>x]߇*;3ڊRiqw޻pqu?=?S6 é|>yb[ zWb8D E^gnNG?|  bDu؊V\cخ=izYs!"FJl! F=et/ifD=5A !L͡=i;;rT#Ah ) w7bZ&.+݂@nkjFkRCiKn66-Iܟ rKsK%QC+{yOTTg75+pACTQ3>D%O2&0SOoXơFVoq=ʮҍƧ7~厙~>usqu_ј5Otu[\t|GۍsM~ԕ$HRk/ I IENDB`PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxb?% (DĂK%1H# ]3:y@M&@) P b ga @}s.,@ ȦƟfx{ ~ u 9g ~!NŪ p?J ?U@tϿO_0:gp V8 FJ@Qbb Mte|IENDB`GIF89ajlbAԽ|9tmp|_,;X%ܬPƤ7i4e'E j dq56p1tJU$;GIF89aZx➭s-҃h$Ç4,7H`KPl\:pL )e9@\"l:+PB;PNG  IHDRa MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3bKGD pHYs  tIME&z;n7IDAT8}Oh\UΛLf$iJ@Oc)PE4)h B.qeE((,?(D M6ЖhH$޻{\$.z79s8<}@p+HNո8Sᩱ[bv{iOqo}776jf;WϜ=! "F"D1b!(PI>s"RWe=Q H\ Q+h_ZX[΋fP=G@ Y3Wz8OMBLr4"Q༫7VfsKso[\#I̼X1ɻ"u+ձ'CuZ:-TA5Uj4⫞ol)齯&95^:3M`prJ2{W-f=F3%8>oAQPs嬴O˛OD޼Au^? 9 rIENDB`PNG  IHDRasRGBbKGD pHYs  tIME\sIDAT8˕˫RQ-# H" AA"Ms05 #  ΤfgR"&MAc}IO#wM6k>ZD4"pn?T*դlCҌ[!Fb$Ih4.L gA4 pX/WշT*<@~p\D"!t:l9%f(w çD"qfJ)TUjzzsx^||r 6 E(c2R`0PӴL1ctlA;^J)L&Ǜk  5UUJ't:Aj$It:p\.ZÎ (`AE8VzodY~'f3v;-~V}nNZxv: 9GȴIENDB`PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8ˍ=OP)C0[!k_@ @ &~@[%C *UAVJ;dB ,@l_رo}nqHP=<>.]D\cn?/ 8FNq$ɷAIP0Hɦi²,0iDQdAJ|mTU&2t]$ILPT@IMIP[5AJ(Je%6O(~0[dāa(*yUtOлM̾_ ^I P%4UUoVNcc_E{v_B|NuXתA"*kfB"_0-K?6љc.oal7.`Z:g|)bbܬ*āG å2Da.a2A$tCʘ?IENDB`PNG  IHDRasRGBbKGD pHYs  tIME&s"|IDAT8˅OlLQΛԤLjCkJYV] $D,!DN$,6AXI"HFjռk˂ι!AWkYӴ! =?pSr7N'Gj.ZVsYoGxL]Yï;9*d6x;<[*Z1`Cp.9VtY~K@BTydkO' ن !HNyhkH574~_*ZPL:O0XUjãˣc6c6c6c6c6c6c6c6c6c6c6c6c6c6i>ėyc6c6c6c6c6c6c6pGc6c6c6c6c6c6tKic6c6c6c6c6c6pGǷZpGc6c6c6c6c6c6c6c6c6c6c6c6pGǷZPNG  IHDRĴl; pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-gAMA|Q cHRMz%u0`:o_FIDATxԕLuE $Q^㥵u 7Lw 9;ޮY 3"KY| ;gڲH/XEm v2^N%(B-sB>w}3Ύ0N;dH3)Am u=8TJR@umЬ'tLuG:_j n/B3S&/#) Rr252C WOeV4ƺs$Dc'7C܎/!) ҖTt2 'uۖN U*Ǭ,byw$D:xlzja&"O`ܿHowAeb2ө"J'蜺;Vfsc$k:q\ik6ug CCH9/8m,g sBP%<N@+clտse h?ܬ jNAOD0D]9hZ8q}r贵9\l2n v^;z>z ;3c2p+vcƨgQyͳNl0U_Yyr2~>IvĺdS's5=3Qp\{IENDB`PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxb?% X@ĄPFd1U 6b] =@|o@,hzF%X Iq0˟]~n/ T pMSPadeOCV@R@㼰̹`ny*,c/? /ÿ_@WGJKVQ)U`h tO&o 00#ß  L|zpb "<3Ue8s )X~ABW 3@WL%^4ÙKOL4| G88a1@L !&ZB >õo4ϯ  `6f7|`O }`0Vegа^m??^zfVW&зafx`͠ӧ7oJ%w- ,$geȫ!aa> ßw|3>|t̵+Ϟ=_Kwٽ[F"| ,Woo޸y9D3<)z^ͻ@LTfb4;-)oypIENDB`PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxb?% X@D}- @ >` lf 4l<- 8X٘|7w>|ܝ{wխi d}u99b`U]MEP[cR.1 `ζ3.Гec/߿?@4 Nc-sIQtWgo v~gbHmfPgq! Cqx\ \Ljr_?5DTBo?3 -,05A]\a²e ߿gc2@ Paaee詨3|y Uax%##Ï!O!?o31|?yOop`=}ԅ _=dHgxs7/_~A@ 8P5UE1 goO 0gd t?`ghb :p~`d##~{ы硩 `.v歩y*o !Ïzk}z69)z^X@LTfb4;B ,f7IENDB`PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxb?% X@jtd1- b V3@|^@,hYh8Hq0}_:~܍խi d "lդYf`̌ \:r|;_:u*b9R_B POAFF2U&Yπ{_0,Y鳗 l NN. _10p pk>yNf//m?,ZP-W`Lmdh25ffa ^h  *lh.fSN+`af@;&P Pe@_A0@@Ͽ @ :/@3ATZ;(4i `͗o@[``c% ޶Hh/ MX ‘/eu d4yW/X`P5?~~T@0]p kH w?|tWϞτ%iBN ]mM1I ^^n6Px|׳/>_tKfxR g7Hiv0dG 32IENDB`PNG  IHDR szz pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-gAMA|Q cHRMz%u0`:o_FIDATx̗mlE{Σ/^/GE[   F(񃆐cŨQD>Q%&Q Fmy +zngٖQqg?B),"Z7 nzܟS`"!Q&hlml >(IJ;MO֚@h潮"Y+0BIRa$ 0]1"M.#( JP*yom29CC-Oh@wa(2؀YeD0> dB[y ͠aáHVr8ㅰbb9԰^Bo5D>7^i>5*&?eؐ*94tӡKK TυxB}fVzv;*)@P=8Gfͪ~ \]KjJ5>r [MLcB8Ƣ۶-\6@BqrlYb\킜|E)p; 7-567";>22a(N̊gtVa;tm" }YsY\/w)԰$>ıG ijϊGVSMy` J~ ̧ŷmԀgwx4iQͿ@B$͑1H%, :?g[NtxyyلC9+;г_)#Jy3e%s'ct*d9.] S3{9W``};: >Ƭy.AvM5lqAzޠE fN߉k "q{seY|>-Iz7gp8$FEOa'c36yID1Q<O&-p!hqh4:b^m*oJl4gRZ/Ú{UKtH&6~jvJl6[=9x<6/8M) VX}9Ao#cLk].Dz,+@(ct:} Ph?P H`_ Tdfc͂Yi 'V{ 2u5'ON #]kIENDB`GIF89a 𵵶ݺ! ,EI8[s/f,^ W\߄xh%@[1 J3@hHW";PNG  IHDRabKGDG pHYs  tIME  . AIDAT8˕NPkqn,I+ u>!#n,1h%,SaVs5d2d ,w[}ֶk :2 A$@"MUGr]dF˱ArgVr4!D|,κIB i&`M ်MHHQlm I&v>,QmON7(IpT0NSOPv~vf;2( =k;DuSCH! =SP[ ]L`YVw6fvjg:qIENDB`PNG  IHDRabKGDG pHYs  tIME  ^ @IDAT8˕JA >Iԏz ?YD>T#$œ~-+{ϙsw X, owσrUKB`Hq

    Welcome!

    This documentation was generated by phpDocumentor .

    Properties

     

     
     
    Yes No 
    Yes No 

    Description

    No description is available

    Methods

    ,

    Properties

    ,

    Constants

      static  final  abstract  (   = , ) : n/a

    Description



    Arguments

    NameTypeDescriptionDefault
    n/a |

    Return value

    Type Description
    n/a n/a

    Tags

    Name Description

      =




    <xsl:value-of select="$title" />
    The following actions are supported in this diagram:
    • Zoom, you can use the scrollwheel to zoom in or out
    • Move, you can move around by dragging the Diagram
    • Go to class, you can view the details of a class by clicking on it
    .treeview, .treeview ul { padding: 0; margin: 0; list-style: none; } .treeview ul { margin-top: 4px; } .treeview .hitarea { background: url(images/treeview-default.gif) -64px -25px no-repeat; height: 16px; width: 16px; margin-left: -16px; float: left; cursor: pointer; } /* fix for IE6 */ * html .hitarea { display: inline; float:none; } .treeview li { margin: 0; padding: 3px 0pt 3px 16px; } .treeview a.selected { background-color: #eee; } #treecontrol { margin: 1em 0; display: none; } .treeview .hover { color: red; cursor: pointer; } .treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; } .treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; } .treeview .expandable-hitarea { background-position: -80px -3px; } .treeview li.last { background-position: 0 -1766px } .treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(images/treeview-default.gif); } .treeview li.lastCollapsable { background-position: 0 -111px } .treeview li.lastExpandable { background-position: -32px -67px } .treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; } .treeview-red li { background-image: url(images/treeview-red-line.gif); } .treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); } .treeview-black li { background-image: url(images/treeview-black-line.gif); } .treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); } .treeview-gray li { background-image: url(images/treeview-gray-line.gif); } .treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); } .treeview-famfamfam li { background-image: url(images/treeview-famfamfam-line.gif); } .treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); } .treeview .placeholder { background: url(images/ajax-loader.gif) 0 0 no-repeat; height: 16px; width: 16px; display: block; } ul.deadtree { padding: 0; margin: 0; list-style: none; } .filetree li, .deadtree li { padding: 3px 0 2px 16px; } .filetree span.folder, .filetree span.file, .deadtree span.folder, .deadtree span.file { padding: 1px 0 1px 16px; display: block; } .filetree span.class, .deadtree span.class, .filetree span.function, .deadtree span.function, .filetree span.interface, .deadtree span.interface { padding: 1px 0 1px 18px; display: block; } .filetree span.folder, .deadtree span.folder { background: url(images/folder.gif) 0 0 no-repeat; } .filetree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; } .filetree span.file { background: url(images/file.gif) 0 0 no-repeat; } .filetree span.class { background: url(../images/icons/class.png) 0 0 no-repeat; } .filetree span.interface { background: url(../images/icons/interface.png) 0 0 no-repeat; } .filetree span.function { background: url(../images/icons/function.png) 0 0 no-repeat; } .treeview ul { background: transparent; } body { margin: 0px; padding: 0px; line-height: 1.5em; font-family: Verdana, Helvetica, sans-serif; font-size: 0.8em; color: black; background: black url('../images/background.png') repeat-x top left; } table { border-collapse: collapse; } thead th { color: gray; font-size: 0.8em; border-bottom: 1px solid silver; } th, td { padding-right: 8px; } #maincontainer { margin: 0 auto; background: white url('../images/top.png') top left no-repeat; width: 980px; overflow: auto; } #header { height: 70px; } #header h1 { display: inline; margin-left: 10px; background: white url('../images/top-background.png') repeat-x top left; padding-top: 36px; } #header img { margin-right: -1px; } #footer { clear:both; } #content_container { float: right; width: 100%; margin-left: -250px; /*Set left margin to -(leftColumnWidth + RightColumnWidth)*/ } #content { margin-left: 250px; /*Set left margin to (leftColumnWidth + RightColumnWidth)*/ } ul#menu { float: left; margin: 0px 10px; -moz-border-radius: 5px; border-radius: 5px; background: #f0f0f0; display: block; width: 960px; height: 32px; line-height: 22px; padding: 0px; } ul#menu li { padding: 0px 10px; margin: 5px 0px; border-right: 1px solid gray; display: block; float: left; } ul#menu li a { color: black; display: block; } div.section { margin: 5px; padding: 5px; padding-top: 0px; margin-bottom: 15px; border: 1px solid silver; -moz-border-radius: 6px; border-radius: 6px; width: 218px; word-wrap: break-word; } div.section h1 { border-bottom: 1px solid #5E8CDF; text-align: center; font-size: 1.1em; padding-bottom: 5px; /*font-variant: small-caps;*/ color: #5E8CDF; } #index { float: left; width: 250px; /*Width of right column in pixels*/ } #index h2 { font-size: 1.1em; margin-bottom: 5px; border-bottom: 1px dashed gray; } .padder { margin: 10px; /*Margins for inner DIV inside each column (to provide padding)*/ margin-top: 0px; } #index .padder { margin-left: 5px; margin-right: 5px; } #menu h1 { text-align: center; margin-top: 15px; margin-bottom: 10px; color: #6495ed; } #menu h4 { margin-bottom: 0px; border-bottom: 1px solid #5E8CDF; } #search_box { display: none; width: 95%; margin: 5px; text-align: center; border: 1px solid #5E8CDF; -moz-border-radius: 5px; border-radius: 5px; } #content .properties { float: right; width: 200px; border: 1px solid gray; -moz-border-radius: 5px; padding: 5px; background: white; word-wrap: break-word; border-radius: 5px; } #content .properties div.property-value { margin-left: 80px; word-wrap: break-word; font-size: 0.8em; width: 120px; } #content .properties label.property-key { float: left; width: 80px; word-wrap: break-word; font-size: 0.8em; font-weight: bold; } #content .properties h1 { font-size: 1.1em; margin-top: 3px; margin-bottom: 0px; border-bottom: 1px solid #5E8CDF; } #content .properties table { font-size: 0.8em; width: 200px; } #content table { font-size: 1.0em; } #content .properties th, #content .properties td, #content th, #content td { text-align: left; vertical-align: top; word-wrap: break-word; overflow: hidden; white-space: pre-wrap; } #content .class, #content .interface { clear: right; } #content h1 { border-bottom: 1px solid #5E8CDF; padding-bottom: 10px; font-size: 1.6em; } #content h2 { color: #5E8CDF; border-bottom: 1px dashed #5E8CDF; padding: 10px 0px; } #content h5 { margin-bottom: 0px; margin-top: 12px; } .file_menu { background-color: #f0f0f0; -moz-border-radius: 5px; border-radius: 5px; text-align: center; margin-top: -5px; padding: 3px; } #content .method, #content .constant, #content .property, #content .class, #content .interface { border: 1px solid silver; background: #f9fdf9; margin: 8px 0px; padding: 5px; } #content .method h4, #content .constant h4, #content .property h4, #content .class h4, #content .interface h4 { margin-top: 10px; margin-bottom: 3px; } #content .method small p, #content .method small ul { margin: 0px; } #content .class { margin: 5px 0px; margin-bottom: 15px; } small.footer { display: block; text-align: right; color: silver; } small.footer a { color: gray; }/* * jQuery UI CSS Framework * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. */ /* Layout helpers ----------------------------------*/ .ui-helper-hidden { display: none; } .ui-helper-hidden-accessible { position: absolute; left: -99999999px; } .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } .ui-helper-clearfix { display: inline-block; } /* required comment for clearfix to work in Opera \*/ * html .ui-helper-clearfix { height:1%; } .ui-helper-clearfix { display:block; } /* end clearfix */ .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } /* Interaction Cues ----------------------------------*/ .ui-state-disabled { cursor: default !important; } /* Icons ----------------------------------*/ /* states and images */ .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } /* Misc visuals ----------------------------------*/ /* Overlays */ .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } /* * jQuery UI CSS Framework * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,%20Arial,%20sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=333333&bgTextureHeader=08_diagonals_thick.png&bgImgOpacityHeader=8&borderColorHeader=a3a3a3&fcHeader=eeeeee&iconColorHeader=bbbbbb&bgColorContent=f9f9f9&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=cccccc&fcContent=222222&iconColorContent=222222&bgColorDefault=111111&bgTextureDefault=02_glass.png&bgImgOpacityDefault=40&borderColorDefault=777777&fcDefault=e3e3e3&iconColorDefault=ededed&bgColorHover=1c1c1c&bgTextureHover=02_glass.png&bgImgOpacityHover=55&borderColorHover=000000&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=ffffff&bgTextureActive=01_flat.png&bgImgOpacityActive=65&borderColorActive=cccccc&fcActive=222222&iconColorActive=222222&bgColorHighlight=ffeb80&bgTextureHighlight=06_inset_hard.png&bgImgOpacityHighlight=55&borderColorHighlight=ffde2e&fcHighlight=363636&iconColorHighlight=4ca300&bgColorError=cd0a0a&bgTextureError=06_inset_hard.png&bgImgOpacityError=45&borderColorError=9e0505&fcError=ffffff&iconColorError=ffcf29&bgColorOverlay=aaaaaa&bgTextureOverlay=04_highlight_hard.png&bgImgOpacityOverlay=40&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=03_highlight_soft.png&bgImgOpacityShadow=50&opacityShadow=20&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px */ /* Component containers ----------------------------------*/ .ui-widget { font-family: Verdana, Arial, sans-serif; font-size: 1.1em; } .ui-widget .ui-widget { font-size: 1em; } .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana, Arial, sans-serif; font-size: 1em; } .ui-widget-content { border: 1px solid #cccccc; background: #f9f9f9 url(images/ui-bg_highlight-hard_100_f9f9f9_1x100.png) 50% top repeat-x; color: #222222; } .ui-widget-content a { color: #222222; } .ui-widget-header { border: 1px solid #a3a3a3; background: #333333 url(images/ui-bg_diagonals-thick_8_333333_40x40.png) 50% 50% repeat; color: #eeeeee; font-weight: bold; } .ui-widget-header a { color: #eeeeee; } /* Interaction states ----------------------------------*/ .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #777777; background: #111111 url(images/ui-bg_glass_40_111111_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #e3e3e3; } .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #e3e3e3; text-decoration: none; } .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #000000; background: #1c1c1c url(images/ui-bg_glass_55_1c1c1c_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; } .ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; } .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #cccccc; background: #ffffff url(images/ui-bg_flat_65_ffffff_40x100.png) 50% 50% repeat-x; font-weight: normal; color: #222222; } .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #222222; text-decoration: none; } .ui-widget :active { outline: none; } /* Interaction Cues ----------------------------------*/ .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #ffde2e; background: #ffeb80 url(images/ui-bg_inset-hard_55_ffeb80_1x100.png) 50% bottom repeat-x; color: #363636; } .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #9e0505; background: #cd0a0a url(images/ui-bg_inset-hard_45_cd0a0a_1x100.png) 50% bottom repeat-x; color: #ffffff; } .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; } .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; } .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } /* Icons ----------------------------------*/ /* states and images */ .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } .ui-widget-header .ui-icon {background-image: url(images/ui-icons_bbbbbb_256x240.png); } .ui-state-default .ui-icon { background-image: url(images/ui-icons_ededed_256x240.png); } .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } .ui-state-active .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_4ca300_256x240.png); } .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffcf29_256x240.png); } /* positioning */ .ui-icon-carat-1-n { background-position: 0 0; } .ui-icon-carat-1-ne { background-position: -16px 0; } .ui-icon-carat-1-e { background-position: -32px 0; } .ui-icon-carat-1-se { background-position: -48px 0; } .ui-icon-carat-1-s { background-position: -64px 0; } .ui-icon-carat-1-sw { background-position: -80px 0; } .ui-icon-carat-1-w { background-position: -96px 0; } .ui-icon-carat-1-nw { background-position: -112px 0; } .ui-icon-carat-2-n-s { background-position: -128px 0; } .ui-icon-carat-2-e-w { background-position: -144px 0; } .ui-icon-triangle-1-n { background-position: 0 -16px; } .ui-icon-triangle-1-ne { background-position: -16px -16px; } .ui-icon-triangle-1-e { background-position: -32px -16px; } .ui-icon-triangle-1-se { background-position: -48px -16px; } .ui-icon-triangle-1-s { background-position: -64px -16px; } .ui-icon-triangle-1-sw { background-position: -80px -16px; } .ui-icon-triangle-1-w { background-position: -96px -16px; } .ui-icon-triangle-1-nw { background-position: -112px -16px; } .ui-icon-triangle-2-n-s { background-position: -128px -16px; } .ui-icon-triangle-2-e-w { background-position: -144px -16px; } .ui-icon-arrow-1-n { background-position: 0 -32px; } .ui-icon-arrow-1-ne { background-position: -16px -32px; } .ui-icon-arrow-1-e { background-position: -32px -32px; } .ui-icon-arrow-1-se { background-position: -48px -32px; } .ui-icon-arrow-1-s { background-position: -64px -32px; } .ui-icon-arrow-1-sw { background-position: -80px -32px; } .ui-icon-arrow-1-w { background-position: -96px -32px; } .ui-icon-arrow-1-nw { background-position: -112px -32px; } .ui-icon-arrow-2-n-s { background-position: -128px -32px; } .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } .ui-icon-arrow-2-e-w { background-position: -160px -32px; } .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } .ui-icon-arrowstop-1-n { background-position: -192px -32px; } .ui-icon-arrowstop-1-e { background-position: -208px -32px; } .ui-icon-arrowstop-1-s { background-position: -224px -32px; } .ui-icon-arrowstop-1-w { background-position: -240px -32px; } .ui-icon-arrowthick-1-n { background-position: 0 -48px; } .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } .ui-icon-arrowthick-1-e { background-position: -32px -48px; } .ui-icon-arrowthick-1-se { background-position: -48px -48px; } .ui-icon-arrowthick-1-s { background-position: -64px -48px; } .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } .ui-icon-arrowthick-1-w { background-position: -96px -48px; } .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } .ui-icon-arrow-4 { background-position: 0 -80px; } .ui-icon-arrow-4-diag { background-position: -16px -80px; } .ui-icon-extlink { background-position: -32px -80px; } .ui-icon-newwin { background-position: -48px -80px; } .ui-icon-refresh { background-position: -64px -80px; } .ui-icon-shuffle { background-position: -80px -80px; } .ui-icon-transfer-e-w { background-position: -96px -80px; } .ui-icon-transferthick-e-w { background-position: -112px -80px; } .ui-icon-folder-collapsed { background-position: 0 -96px; } .ui-icon-folder-open { background-position: -16px -96px; } .ui-icon-document { background-position: -32px -96px; } .ui-icon-document-b { background-position: -48px -96px; } .ui-icon-note { background-position: -64px -96px; } .ui-icon-mail-closed { background-position: -80px -96px; } .ui-icon-mail-open { background-position: -96px -96px; } .ui-icon-suitcase { background-position: -112px -96px; } .ui-icon-comment { background-position: -128px -96px; } .ui-icon-person { background-position: -144px -96px; } .ui-icon-print { background-position: -160px -96px; } .ui-icon-trash { background-position: -176px -96px; } .ui-icon-locked { background-position: -192px -96px; } .ui-icon-unlocked { background-position: -208px -96px; } .ui-icon-bookmark { background-position: -224px -96px; } .ui-icon-tag { background-position: -240px -96px; } .ui-icon-home { background-position: 0 -112px; } .ui-icon-flag { background-position: -16px -112px; } .ui-icon-calendar { background-position: -32px -112px; } .ui-icon-cart { background-position: -48px -112px; } .ui-icon-pencil { background-position: -64px -112px; } .ui-icon-clock { background-position: -80px -112px; } .ui-icon-disk { background-position: -96px -112px; } .ui-icon-calculator { background-position: -112px -112px; } .ui-icon-zoomin { background-position: -128px -112px; } .ui-icon-zoomout { background-position: -144px -112px; } .ui-icon-search { background-position: -160px -112px; } .ui-icon-wrench { background-position: -176px -112px; } .ui-icon-gear { background-position: -192px -112px; } .ui-icon-heart { background-position: -208px -112px; } .ui-icon-star { background-position: -224px -112px; } .ui-icon-link { background-position: -240px -112px; } .ui-icon-cancel { background-position: 0 -128px; } .ui-icon-plus { background-position: -16px -128px; } .ui-icon-plusthick { background-position: -32px -128px; } .ui-icon-minus { background-position: -48px -128px; } .ui-icon-minusthick { background-position: -64px -128px; } .ui-icon-close { background-position: -80px -128px; } .ui-icon-closethick { background-position: -96px -128px; } .ui-icon-key { background-position: -112px -128px; } .ui-icon-lightbulb { background-position: -128px -128px; } .ui-icon-scissors { background-position: -144px -128px; } .ui-icon-clipboard { background-position: -160px -128px; } .ui-icon-copy { background-position: -176px -128px; } .ui-icon-contact { background-position: -192px -128px; } .ui-icon-image { background-position: -208px -128px; } .ui-icon-video { background-position: -224px -128px; } .ui-icon-script { background-position: -240px -128px; } .ui-icon-alert { background-position: 0 -144px; } .ui-icon-info { background-position: -16px -144px; } .ui-icon-notice { background-position: -32px -144px; } .ui-icon-help { background-position: -48px -144px; } .ui-icon-check { background-position: -64px -144px; } .ui-icon-bullet { background-position: -80px -144px; } .ui-icon-radio-off { background-position: -96px -144px; } .ui-icon-radio-on { background-position: -112px -144px; } .ui-icon-pin-w { background-position: -128px -144px; } .ui-icon-pin-s { background-position: -144px -144px; } .ui-icon-play { background-position: 0 -160px; } .ui-icon-pause { background-position: -16px -160px; } .ui-icon-seek-next { background-position: -32px -160px; } .ui-icon-seek-prev { background-position: -48px -160px; } .ui-icon-seek-end { background-position: -64px -160px; } .ui-icon-seek-start { background-position: -80px -160px; } /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ .ui-icon-seek-first { background-position: -80px -160px; } .ui-icon-stop { background-position: -96px -160px; } .ui-icon-eject { background-position: -112px -160px; } .ui-icon-volume-off { background-position: -128px -160px; } .ui-icon-volume-on { background-position: -144px -160px; } .ui-icon-power { background-position: 0 -176px; } .ui-icon-signal-diag { background-position: -16px -176px; } .ui-icon-signal { background-position: -32px -176px; } .ui-icon-battery-0 { background-position: -48px -176px; } .ui-icon-battery-1 { background-position: -64px -176px; } .ui-icon-battery-2 { background-position: -80px -176px; } .ui-icon-battery-3 { background-position: -96px -176px; } .ui-icon-circle-plus { background-position: 0 -192px; } .ui-icon-circle-minus { background-position: -16px -192px; } .ui-icon-circle-close { background-position: -32px -192px; } .ui-icon-circle-triangle-e { background-position: -48px -192px; } .ui-icon-circle-triangle-s { background-position: -64px -192px; } .ui-icon-circle-triangle-w { background-position: -80px -192px; } .ui-icon-circle-triangle-n { background-position: -96px -192px; } .ui-icon-circle-arrow-e { background-position: -112px -192px; } .ui-icon-circle-arrow-s { background-position: -128px -192px; } .ui-icon-circle-arrow-w { background-position: -144px -192px; } .ui-icon-circle-arrow-n { background-position: -160px -192px; } .ui-icon-circle-zoomin { background-position: -176px -192px; } .ui-icon-circle-zoomout { background-position: -192px -192px; } .ui-icon-circle-check { background-position: -208px -192px; } .ui-icon-circlesmall-plus { background-position: 0 -208px; } .ui-icon-circlesmall-minus { background-position: -16px -208px; } .ui-icon-circlesmall-close { background-position: -32px -208px; } .ui-icon-squaresmall-plus { background-position: -48px -208px; } .ui-icon-squaresmall-minus { background-position: -64px -208px; } .ui-icon-squaresmall-close { background-position: -80px -208px; } .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } .ui-icon-grip-solid-vertical { background-position: -32px -224px; } .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } .ui-icon-grip-diagonal-se { background-position: -80px -224px; } /* Misc visuals ----------------------------------*/ /* Corner radius */ .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } .ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } .ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } .ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } .ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } /* Overlays */ .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_highlight-hard_40_aaaaaa_1x100.png) 50% top repeat-x; opacity: .30;filter:Alpha(Opacity=30); } .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_highlight-soft_50_aaaaaa_1x100.png) 50% top repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* Resizable ----------------------------------*/ .ui-resizable { position: relative;} .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Selectable ----------------------------------*/ .ui-selectable-helper { border:1px dotted black } /* Accordion ----------------------------------*/ .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } .ui-accordion .ui-accordion-li-fix { display: inline; } .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } /* IE7-/Win - Fix extra vertical space in lists */ .ui-accordion a { zoom: 1; } .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } .ui-accordion .ui-accordion-content-active { display: block; }/* Autocomplete ----------------------------------*/ .ui-autocomplete { position: absolute; cursor: default; } .ui-autocomplete-loading { background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; } /* workarounds */ * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ /* Menu ----------------------------------*/ .ui-menu { list-style:none; padding: 2px; margin: 0; display:block; } .ui-menu .ui-menu { margin-top: -3px; } .ui-menu .ui-menu-item { margin:0; padding: 0; zoom: 1; float: left; clear: left; width: 100%; } .ui-menu .ui-menu-item a { text-decoration:none; display:block; padding:.2em .4em; line-height:1.5; zoom:1; } .ui-menu .ui-menu-item a.ui-state-hover, .ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; } /* Button ----------------------------------*/ .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ .ui-button-icons-only { width: 3.4em; } button.ui-button-icons-only { width: 3.7em; } /*button text element */ .ui-button .ui-button-text { display: block; line-height: 1.4; } .ui-button-text-only .ui-button-text { padding: .4em 1em; } .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } .ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } /* no icon support for input elements, provide padding by default */ input.ui-button { padding: .4em 1em; } /*button icon element(s) */ .ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } .ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } /*button sets*/ .ui-buttonset { margin-right: 7px; } .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } /* workarounds */ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ /* Dialog ----------------------------------*/ .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } .ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; } .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } .ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } .ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } .ui-draggable .ui-dialog-titlebar { cursor: move; } /* Slider ----------------------------------*/ .ui-slider { position: relative; text-align: left; } .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } .ui-slider-horizontal { height: .8em; } .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } .ui-slider-horizontal .ui-slider-range-min { left: 0; } .ui-slider-horizontal .ui-slider-range-max { right: 0; } .ui-slider-vertical { width: .8em; height: 100px; } .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } .ui-slider-vertical .ui-slider-range-min { bottom: 0; } .ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs ----------------------------------*/ .ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } .ui-tabs .ui-tabs-hide { display: none !important; } /* Datepicker ----------------------------------*/ .ui-datepicker { width: 17em; padding: .2em .2em 0; } .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } .ui-datepicker .ui-datepicker-prev { left:2px; } .ui-datepicker .ui-datepicker-next { right:2px; } .ui-datepicker .ui-datepicker-prev-hover { left:1px; } .ui-datepicker .ui-datepicker-next-hover { right:1px; } .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } .ui-datepicker select.ui-datepicker-month-year {width: 100%;} .ui-datepicker select.ui-datepicker-month, .ui-datepicker select.ui-datepicker-year { width: 49%;} .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } .ui-datepicker td { border: 0; padding: 1px; } .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } /* with multiple calendars */ .ui-datepicker.ui-datepicker-multi { width:auto; } .ui-datepicker-multi .ui-datepicker-group { float:left; } .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } .ui-datepicker-row-break { clear:both; width:100%; } /* RTL support */ .ui-datepicker-rtl { direction: rtl; } .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } .ui-datepicker-rtl .ui-datepicker-group { float:right; } .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ .ui-datepicker-cover { display: none; /*sorry for IE5*/ display/**/: block; /*sorry for IE5*/ position: absolute; /*must have*/ z-index: -1; /*must have*/ filter: mask(); /*must have*/ top: -4px; /*must have*/ left: -4px; /*must have*/ width: 200px; /*must have*/ height: 200px; /*must have*/ }/* Progressbar ----------------------------------*/ .ui-progressbar { height:2em; text-align: left; } .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }PNG  IHDRoX CIDAT8ϱ 0Dуzaƅd( +f'yU<fl >SIENDB`PNG  IHDR(ddrzyIDATh1 R 7(ȚV`%X V`%X V`%X V`%X V`%X V`%X V`%X V`%X V`%X V`%X V`%X V`%X Vj)2NIENDB`PNG  IHDRNzoPLTE,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,E |NtRNS2P."Tp@f` <BHJZ&0R,4j8D|($ blߝF>n~hhH_IDATx] c۶JZgv,ٲ&{?:-[3Ү3qJOptB }6x9s SmCXȸR<QήF ?SHf+&ytSE-G8>Am٪d ~Z#sկ6'аfN( 0%#r(DXXKQL^J*KʱzTA~yd-TLieSS(Kň< bۜE%NS~._c$QUb=+C5>W-Z8BHؗ+$~ǫ+e9*9J*VDoq@.i ovR~SH6w_v cU˂5y@~Rת#J9"!ꎾJ:d$. 3@nVew%w>#vSv ᤵ #,e]T q/|cթbfppߋbH1FS s L(?"#YP)C6C\$V-A$b ߏ3R4m`G\~ c:C.UasuC]7<e7,4 ʯUW-Cv7uT{%*9"VzOFU8ь)Y~+%X4STaWDSWeju^ѓIMg/_Moe"&~m ' sOW7-;3xf7yr#C+9ckM].8qYd#R`kaU^k#/P?*u$~HY52֟^|b{|a,?kE/vkL?o=;dxlE{A:?aM2$GqB+hC>te_O8d0wPlE` AAɂ[.zdaVĀ#O4&k?V `]ْP#NJ7Ybe7,H[F24eYSۉ|B&]KR˥Ŷ ATS6?h{9 "\vr9U{qvk/0W+?q"GW˨`wͤWAF-`ae]n"bMB]p+5޿ 3G]SÎ.1Yax)Ã[<+> smT؆*sɴ,K۶\ij`erY9yaЩ L|Ϟ)L[ T7GRPP$/0*vStWFCE/2:htL?8;>l fYd6ɩ}{ZiukDJӟS\^z L,uFtKyh}jdrf$3:Cd.Uٽ{AojRN 簐џQ S/]VTq _G9sE$Zwa͏FUH# e G1ZwV7>naO[+ʀ4HF^ ׆ONfTpza ƀV@O//S]SύwxTnځZG#N"a]s՜X7 `G{v´?VW_FYͩi+U'4 V 7%yT`뇪rXfOo@Ao>W n2K*fǦMh:75M+ЏyN<ÊP Lon> h:ǙvI~9畺K 5f dķc=8983K4jvyi|@v0cNv+̩1WrJ<=Qm[=(A3LJLX H˦6:խziJc'f&Ltv}15 |%۶%2oCm _x\c)VaF3p[oǽ$\FFO"v p30Fz8L&2pG>0V~XQO~!E  0t${  F0{F「{bZ),\(<`0o%JVA=#J֟߆ L 4lO /ܫbĪ (X&ܮ`XZw222>*Dg) 0ݱ*ouJ(=M^ 8IV },f>+!>? @ejBD8pOagd|PTqg$Ǐ8i)s0,C~\ :UV6U \`77`V1c@fN/ɪǿfPʃV]*h w.藢{7iHu}Jn3@ vebd?wPyW˂ErٵyI*RV2~ET~=N8e! *{,F- :.Yg (^!.j4^6Ե5o B}|~[ ];CU [R)aT>7/{Ky&Ϥ{QOy)#ârύ~a!&Wz Z졽TץRҥ_s]4"oEDAwUT8Hvo%sn\Hy$ȴhz4qR;yu5:??@V'.vlcl77^W QgZ-&5_D?1EBT NN ٞqJ/ {^b!#{ ~M{x/-Jn)Qljk=%46}t yX3KȊ7D:m{μ0-2TULPĆX@ ׎|M#D/vzXp< %#_%=/9(@C@ YMkf#-r@Cʭd8aG@ƌ<@޻@Fƃǃ~?lldž/wlTLdžRnFWbA%Igש½'39R^MRV֡UuC +0i=YS}!uۖ,V/B5, .C|r Z^;0p&h"?ȏo7~olap,lr_UaFH\zh+G_mB[޶CշjSz322`t裇:{GC@{E :\^ ?*;ۢ9/BAo_ @[@ ] Ql uf;sIENDB`PNG  IHDRIJPLTE NtRNS2P."Tp@f` <BHJZ&0R,4j8D|($ blߝF>n~hhHIDATx]b۶H儒-{iZK:glkn-tIqq? E$dK>$>;PZsVh!Sy0E0}H)-t koܪKp\RϠ .E7 ) *V;~Pe Bx*,=$zDؾ JҸٻ9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;" i] dddddddd4y5  Rb@(8CdŪݡ,@T@ibrq0alX!pe, =4bW { 5Ƭhu~(Q^@3="b5XC@JCT76q_5 @,r šɩD)T|O@ ON-ՙ [n@RXIm݋(F @?=0puL;g$@6η K`>п @h գKVn"a" %l@.v$/U^ G:#`` uTtK~ŋZ5T%kxk]\*Q ,҇B44 OXK|yg+_M(lоEO V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V rh(]tI^}oצo S3 ";ʙb}"߰ ){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.}Q3.Nس})>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa 3 {oB &<L[ Nc.öi=`Q@d ͆I.Il`\t[< Cit484-r +f쑱BCB MH iy }>rxp|z;BǏ;burcK4tz1G~`ؚK| ̔>ۡO$~ Ao)0pzz }i`;ADm8n:cfA@s7L Z/..h8or? N93B~o_'`opO- :TG L;7]`B%˛>*wTpM0H}&t ^1'Oqr'2P͡+z,tIW''|en=dzgRm[NStK{҉mؓVt6ҲR`ζN&}B U(rۗ&1%Q''?l׸+&r{jN಻4) `N狌. ߭ ǣ)q 2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~Mz +4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6GFZ)O !lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5av]m1+3y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c- 賟Lδ>]5.sYs1f0;'̨Yg銛{@9 `aC(=%bo2=n1 jBoS$n#m=i0ci9}oI qT]W%.(؅]z\x f"]o'u䫵tk{v;AC3ֆwwR_#X (xҋ/q%W hpk_IX'b/fXKi"#####QCLi2t 5L0 QiH2;yTOok;ע ٶ`RNg{zy!Kxm?A(vU~mL(`o/!nmX-{v[ dw=n「sdwzn(}Oy~ m ?XU;,V'+ V&JRZ]᧭:zC'-߆@y 4u `Vۓwъ#zP@Q N>2/{\o)W~a3xLw :_Q;=pּdt\'8~3SRP6y+XQ*޺r ̗ѭ*޺r gl/\U^u$|mbVnw \V|D͊NVNy7k<;/E}?E*dzgO ~g/96f cD}% g$QG7o)U Jo,O@0߾Q(;bw:5 NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 3 u Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?sn~hhHIDATx]b۶H儒-{iZK:glkn-tIqq? E$dK>$>;PZsVh!Sy0E0}H)-t koܪKp\RϠ .E7 ) *V;~Pe Bx*,=$zDؾ JҸٻ9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;" i] dddddddd4y5  Rb@(8CdŪݡ,@T@ibrq0alX!pe, =4bW { 5Ƭhu~(Q^@3="b5XC@JCT76q_5 @,r šɩD)T|O@ ON-ՙ [n@RXIm݋(F @?=0puL;g$@6η K`>п @h գKVn"a" %l@.v$/U^ G:#`` uTtK~ŋZ5T%kxk]\*Q ,҇B44 OXK|yg+_M(lоEO V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V rh(]tI^}oצo S3 ";ʙb}"߰ ){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.}Q3.Nس})>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa 3 {oB &<L[ Nc.öi=`Q@d ͆I.Il`\t[< Cit484-r +f쑱BCB MH iy }>rxp|z;BǏ;burcK4tz1G~`ؚK| ̔>ۡO$~ Ao)0pzz }i`;ADm8n:cfA@s7L Z/..h8or? N93B~o_'`opO- :TG L;7]`B%˛>*wTpM0H}&t ^1'Oqr'2P͡+z,tIW''|en=dzgRm[NStK{҉mؓVt6ҲR`ζN&}B U(rۗ&1%Q''?l׸+&r{jN಻4) `N狌. ߭ ǣ)q 2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~Mz +4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6GFZ)O !lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5av]m1+3y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c- 賟Lδ>]5.sYs1f0;'̨Yg銛{@9 `aC(=%bo2=n1 jBoS$n#m=i0ci9}oI qT]W%.(؅]z\x f"]o'u䫵tk{v;AC3ֆwwR_#X (xҋ/q%W hpk_IX'b/fXKi"#####QCLi2t 5L0 QiH2;yTOok;ע ٶ`RNg{zy!Kxm?A(vU~mL(`o/!nmX-{v[ dw=n「sdwzn(}Oy~ m ?XU;,V'+ V&JRZ]᧭:zC'-߆@y 4u `Vۓwъ#zP@Q N>2/{\o)W~a3xLw :_Q;=pּdt\'8~3SRP6y+XQ*޺r ̗ѭ*޺r gl/\U^u$|mbVnw \V|D͊NVNy7k<;/E}?E*dzgO ~g/96f cD}% g$QG7o)U Jo,O@0߾Q(;bw:5 NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 3 u Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?sn~hhHIDATx]b۶H儒-{iZK:glkn-tIqq? E$dK>$>;PZsVh!Sy0E0}H)-t koܪKp\RϠ .E7 ) *V;~Pe Bx*,=$zDؾ JҸٻ9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;" i] dddddddd4y5  Rb@(8CdŪݡ,@T@ibrq0alX!pe, =4bW { 5Ƭhu~(Q^@3="b5XC@JCT76q_5 @,r šɩD)T|O@ ON-ՙ [n@RXIm݋(F @?=0puL;g$@6η K`>п @h գKVn"a" %l@.v$/U^ G:#`` uTtK~ŋZ5T%kxk]\*Q ,҇B44 OXK|yg+_M(lоEO V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V rh(]tI^}oצo S3 ";ʙb}"߰ ){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.}Q3.Nس})>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa 3 {oB &<L[ Nc.öi=`Q@d ͆I.Il`\t[< Cit484-r +f쑱BCB MH iy }>rxp|z;BǏ;burcK4tz1G~`ؚK| ̔>ۡO$~ Ao)0pzz }i`;ADm8n:cfA@s7L Z/..h8or? N93B~o_'`opO- :TG L;7]`B%˛>*wTpM0H}&t ^1'Oqr'2P͡+z,tIW''|en=dzgRm[NStK{҉mؓVt6ҲR`ζN&}B U(rۗ&1%Q''?l׸+&r{jN಻4) `N狌. ߭ ǣ)q 2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~Mz +4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6GFZ)O !lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5av]m1+3y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c- 賟Lδ>]5.sYs1f0;'̨Yg銛{@9 `aC(=%bo2=n1 jBoS$n#m=i0ci9}oI qT]W%.(؅]z\x f"]o'u䫵tk{v;AC3ֆwwR_#X (xҋ/q%W hpk_IX'b/fXKi"#####QCLi2t 5L0 QiH2;yTOok;ע ٶ`RNg{zy!Kxm?A(vU~mL(`o/!nmX-{v[ dw=n「sdwzn(}Oy~ m ?XU;,V'+ V&JRZ]᧭:zC'-߆@y 4u `Vۓwъ#zP@Q N>2/{\o)W~a3xLw :_Q;=pּdt\'8~3SRP6y+XQ*޺r ̗ѭ*޺r gl/\U^u$|mbVnw \V|D͊NVNy7k<;/E}?E*dzgO ~g/96f cD}% g$QG7o)U Jo,O@0߾Q(;bw:5 NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 3 u Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s R!!,c $PxB +*-[dඁ+i@ )`L ?'I`JGb Ph XB)0׸XQ# } No "tI+ZI!!,\ $P`8* 1h0rx8BQaV  !MDl!4%BBe PDY00!!,] $$I>Q] d"28 GqH9 A2ȀB", DH('4C \0`UL"r(!! ,d $dI`ìkBB m A72, (PX鲪 8@R%a K*D2E {$ft5C%!;PNG  IHDRdG,Z`BIDATݏ @2;{peMDycՍN0 ZX3X ̣wM0UXU_/ g6>>IENDB`PNG  IHDRNzoPLTE&haNtRNS2P."Tp@f` <BHJZ&0R,4j8D|($ blߝF>n~hhH_IDATx] c۶JZgv,ٲ&{?:-[3Ү3qJOptB }6x9s SmCXȸR<QήF ?SHf+&ytSE-G8>Am٪d ~Z#sկ6'аfN( 0%#r(DXXKQL^J*KʱzTA~yd-TLieSS(Kň< bۜE%NS~._c$QUb=+C5>W-Z8BHؗ+$~ǫ+e9*9J*VDoq@.i ovR~SH6w_v cU˂5y@~Rת#J9"!ꎾJ:d$. 3@nVew%w>#vSv ᤵ #,e]T q/|cթbfppߋbH1FS s L(?"#YP)C6C\$V-A$b ߏ3R4m`G\~ c:C.UasuC]7<e7,4 ʯUW-Cv7uT{%*9"VzOFU8ь)Y~+%X4STaWDSWeju^ѓIMg/_Moe"&~m ' sOW7-;3xf7yr#C+9ckM].8qYd#R`kaU^k#/P?*u$~HY52֟^|b{|a,?kE/vkL?o=;dxlE{A:?aM2$GqB+hC>te_O8d0wPlE` AAɂ[.zdaVĀ#O4&k?V `]ْP#NJ7Ybe7,H[F24eYSۉ|B&]KR˥Ŷ ATS6?h{9 "\vr9U{qvk/0W+?q"GW˨`wͤWAF-`ae]n"bMB]p+5޿ 3G]SÎ.1Yax)Ã[<+> smT؆*sɴ,K۶\ij`erY9yaЩ L|Ϟ)L[ T7GRPP$/0*vStWFCE/2:htL?8;>l fYd6ɩ}{ZiukDJӟS\^z L,uFtKyh}jdrf$3:Cd.Uٽ{AojRN 簐џQ S/]VTq _G9sE$Zwa͏FUH# e G1ZwV7>naO[+ʀ4HF^ ׆ONfTpza ƀV@O//S]SύwxTnځZG#N"a]s՜X7 `G{v´?VW_FYͩi+U'4 V 7%yT`뇪rXfOo@Ao>W n2K*fǦMh:75M+ЏyN<ÊP Lon> h:ǙvI~9畺K 5f dķc=8983K4jvyi|@v0cNv+̩1WrJ<=Qm[=(A3LJLX H˦6:խziJc'f&Ltv}15 |%۶%2oCm _x\c)VaF3p[oǽ$\FFO"v p30Fz8L&2pG>0V~XQO~!E  0t${  F0{F「{bZ),\(<`0o%JVA=#J֟߆ L 4lO /ܫbĪ (X&ܮ`XZw222>*Dg) 0ݱ*ouJ(=M^ 8IV },f>+!>? @ejBD8pOagd|PTqg$Ǐ8i)s0,C~\ :UV6U \`77`V1c@fN/ɪǿfPʃV]*h w.藢{7iHu}Jn3@ vebd?wPyW˂ErٵyI*RV2~ET~=N8e! *{,F- :.Yg (^!.j4^6Ե5o B}|~[ ];CU [R)aT>7/{Ky&Ϥ{QOy)#ârύ~a!&Wz Z졽TץRҥ_s]4"oEDAwUT8Hvo%sn\Hy$ȴhz4qR;yu5:??@V'.vlcl77^W QgZ-&5_D?1EBT NN ٞqJ/ {^b!#{ ~M{x/-Jn)Qljk=%46}t yX3KȊ7D:m{μ0-2TULPĆX@ ׎|M#D/vzXp< %#_%=/9(@C@ YMkf#-r@Cʭd8aG@ƌ<@޻@Fƃǃ~?lldž/wlTLdžRnFWbA%Igש½'39R^MRV֡UuC +0i=YS}!uۖ,V/B5, .C|r Z^;0p&h"?ȏo7~olap,lr_UaFH\zh+G_mB[޶CշjSz322`t裇:{GC@{E :\^ ?*;ۢ9/BAo_ @[@ ] Ql uf;sIENDB`PNG  IHDRIJPLTEiNtRNS2P."Tp@f` <BHJZ&0R,4j8D|($ blߝF>n~hhHIDATx]b۶H儒-{iZK:glkn-tIqq? E$dK>$>;PZsVh!Sy0E0}H)-t koܪKp\RϠ .E7 ) *V;~Pe Bx*,=$zDؾ JҸٻ9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;" i] dddddddd4y5  Rb@(8CdŪݡ,@T@ibrq0alX!pe, =4bW { 5Ƭhu~(Q^@3="b5XC@JCT76q_5 @,r šɩD)T|O@ ON-ՙ [n@RXIm݋(F @?=0puL;g$@6η K`>п @h գKVn"a" %l@.v$/U^ G:#`` uTtK~ŋZ5T%kxk]\*Q ,҇B44 OXK|yg+_M(lоEO V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V rh(]tI^}oצo S3 ";ʙb}"߰ ){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.}Q3.Nس})>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa 3 {oB &<L[ Nc.öi=`Q@d ͆I.Il`\t[< Cit484-r +f쑱BCB MH iy }>rxp|z;BǏ;burcK4tz1G~`ؚK| ̔>ۡO$~ Ao)0pzz }i`;ADm8n:cfA@s7L Z/..h8or? N93B~o_'`opO- :TG L;7]`B%˛>*wTpM0H}&t ^1'Oqr'2P͡+z,tIW''|en=dzgRm[NStK{҉mؓVt6ҲR`ζN&}B U(rۗ&1%Q''?l׸+&r{jN಻4) `N狌. ߭ ǣ)q 2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~Mz +4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6GFZ)O !lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5av]m1+3y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c- 賟Lδ>]5.sYs1f0;'̨Yg銛{@9 `aC(=%bo2=n1 jBoS$n#m=i0ci9}oI qT]W%.(؅]z\x f"]o'u䫵tk{v;AC3ֆwwR_#X (xҋ/q%W hpk_IX'b/fXKi"#####QCLi2t 5L0 QiH2;yTOok;ע ٶ`RNg{zy!Kxm?A(vU~mL(`o/!nmX-{v[ dw=n「sdwzn(}Oy~ m ?XU;,V'+ V&JRZ]᧭:zC'-߆@y 4u `Vۓwъ#zP@Q N>2/{\o)W~a3xLw :_Q;=pּdt\'8~3SRP6y+XQ*޺r ̗ѭ*޺r gl/\U^u$|mbVnw \V|D͊NVNy7k<;/E}?E*dzgO ~g/96f cD}% g$QG7o)U Jo,O@0߾Q(;bw:5 NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 3 u Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s*IENDB`GIF89a`1k9s!Bs!R1scBJZZ!k!s{cc{Bs֔ƭҤޥ筌絔ﵔҵ!,` H*\BlHŋ#bȱEC rɓ(S\ɲ˗0cʜ)B&ܙB x(A(tp@ѧH;HthjQ PJ+O  `۷pʝK.͒v[[qć|7 r0È+^̸ $c8DP2 0`!8Hi "0X1$e!K ȓ+~FֳkνU8ur ,wJ:ujXr]XѪe뽿8vDM1A(^NݑP%TW)wmb}aa~iU0xX|)h >(D$d]fmhݦ]j]l&ev[!YdR=!`ұip)県IvJjٕVwTJefw]%wv裐F*;GIF89a`!,` H*\BlHŋ#bȱEC rɓ(S< Õ0I,ǁ iܹ0'N@FteУ ԉϥMB5TNFZ)׮A)vͲfcMZ8QKs/E7o߼ `r#x1211希/c~r῝99z$ҢQs̈0#A;GIF89a!,;GIF89a!, HA*\x0!Ç BHP"E 3xaNj?2 )R!ɒOrdˈ/M8ʗ7[\eϒ?E8cQ5m&eaSOb|ԉW!f}eT`mإeeM&ٰol.Zl;R}4Ề ƹXgc}F:Yhej̹3H34dӒQSVm5fFAOp^ڳmōUvoZ}W݁EXZ棡~zj뫱{ln{-FpW\r?tx!~ᝧ yFރIXaq8yx8x ¸6V昡١"#Y'2+B٢/R3"Y#7ȥ^y?CYK٤OSYW♥I~ mq":u2zyBgeRzib顟&ꢣ6Z꣧Fꤜ j*j⪪**lZlllFkR>,Nm^nn;n+k.+o;okoVڪܬ"\2\B/Kc\s ܰ[\1gܱ#\'2+1=5#}93=CAK=t/[]5Es}IMQ=* Tt]vj_}owց]݇8߃w׏ؓ]ٗڋw >#3^:{C^Sc޻s^x3<œͣӳ^ϋ~ٛ=^㞾޾o<<H=Zπ=s$> ςà4?σ` ?3P@Ѕe@. qANЇA"nЈDBp pfJyN* C2R%4c јB5損-tcxC9>*aE>vQ?d9DBѐGDdDF6яtFI~m5YFNqAYGQ{4QHVҕ!eHZ.)H@;GIF89a888&&&֨vvvfff䘘HHHVVV!Created with ajaxload.info! ! NETSCAPE2.0,P di0l!*`Ƒ5و[<iP),IZ$bH85&x5k <yB! ,h GҌh*ਨ@$E}eh @ LcQGBP5 <5UdQ+"g0Ak#A nI0$K7 H,-t*E-``1@C7h/1f\)&!;GIF89a !, "H"q3g?;>X4Ҧ)N}u_הaw\ ;0m׶SMMUI#\wjJ(TzsZ4w뾙'ӫ7}{Ӗy-|}_}=ym7Pu}W vi'18x)߄VhNq6qgaX B"R)"ȹ8t h<uX7RXqK$lO߁8>XWfIGu_za>ih;GIF89a!, / "\XB B(p"E1:0ǏR8r G%<0ʒ,$L6s SgO#oVEnTڑ)ʟP=:5iեWf}*5*UVb,ׯ]Ӣ]Vm[cƅ[Vn]gꝻn߼| xˆ[nUl2:;oe—gLqş=w~thҧ)skͯ9=Zumַ]熽[PڳEGtƇVn缡~Iܥسkν{W|s^y*:?_zrW ~ *8 B I^ZHx"f8%&c.(cˆc;bx@($A9$=vE"dOeSx$WJ%[ZiNvi#X\ejeyiҹfxΙg{ީ|gj}"*2zhbBڦv:j)br(U^ jNZj꣩zjnk~*ʚ+ڪd[+L[,˺z mRbkr묶Ւ{٢{»KJo;/[0 +< C0J_[L"g <%'s.,sÌs;c|@,4A=4=wE#tOuS|4WK5[[mNwm3X\uje}iӽvxϝw{|wn}#.3~xbC޶v;n9cs8U_zO^z型髣~zo{:˞;ۮt_꿓;L_<˻~}Sc{sՓ٣ÿOK?_#@Ѐ = 2pA r !' pCT?τ%L` +ʰ!#C P@2iD"=`OXD$61O\a[8WbE+N i;GIF89a`!,` H*\BlHŋ#bȱEC rɓ(S<K+c p̛m:φ:AI!MZhPM|*T5j]Rת_Â*YgUfImeDIރs L8-WGZ3BxҮ/>q3g?;>X4Ҧ)N}u_הaw\ ;0m׶SMMUI#\wjJ(TzsZ4w뾙'ӫ7}{Ӗy-|}_}=ym7Pu}W vi'18x)߄VhNq6qgaX B"R)"ȹ8t h<uX7RXqK$lO߁8>XWfIGu_za>ih;
    Documentation was generated by
    phpDocumentor .

    Properties

     

    Description




    Includes

     ()

    Functions

    Constants

    Classes

    Interfaces

    Interfaces

    Path Description
    :
    :

    Namespaces

    Packages

    Files

  • Default
  • Default
  • Compilation Errors

    No errors have been found in this project.

    TypeLineDescription
    /* * Treeview 1.5pre - jQuery plugin to hide and show branches of a tree * * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/ * http://docs.jquery.com/Plugins/Treeview * * Copyright (c) 2007 Jörn Zaefferer * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * Revision: $Id: jquery.treeview.js 5759 2008-07-01 07:50:28Z joern.zaefferer $ * */ ;(function($) { // TODO rewrite as a widget, removing all the extra plugins $.extend($.fn, { swapClass: function(c1, c2) { var c1Elements = this.filter('.' + c1); this.filter('.' + c2).removeClass(c2).addClass(c1); c1Elements.removeClass(c1).addClass(c2); return this; }, replaceClass: function(c1, c2) { return this.filter('.' + c1).removeClass(c1).addClass(c2).end(); }, hoverClass: function(className) { className = className || "hover"; return this.hover(function() { $(this).addClass(className); }, function() { $(this).removeClass(className); }); }, heightToggle: function(animated, callback) { animated ? this.animate({ height: "toggle" }, animated, callback) : this.each(function(){ jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ](); if(callback) callback.apply(this, arguments); }); }, heightHide: function(animated, callback) { if (animated) { this.animate({ height: "hide" }, animated, callback); } else { this.hide(); if (callback) this.each(callback); } }, prepareBranches: function(settings) { if (!settings.prerendered) { // mark last tree items this.filter(":last-child:not(ul)").addClass(CLASSES.last); // collapse whole tree, or only those marked as closed, anyway except those marked as open this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide(); } // return all items with sublists return this.filter(":has(>ul)"); }, applyClasses: function(settings, toggler) { // TODO use event delegation this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) { // don't handle click events on children, eg. checkboxes if ( this == event.target ) toggler.apply($(this).next()); }).add( $("a", this) ).hoverClass(); if (!settings.prerendered) { // handle closed ones first this.filter(":has(>ul:hidden)") .addClass(CLASSES.expandable) .replaceClass(CLASSES.last, CLASSES.lastExpandable); // handle open ones this.not(":has(>ul:hidden)") .addClass(CLASSES.collapsable) .replaceClass(CLASSES.last, CLASSES.lastCollapsable); // create hitarea if not present var hitarea = this.find("div." + CLASSES.hitarea); if (!hitarea.length) hitarea = this.prepend("
    ").find("div." + CLASSES.hitarea); hitarea.removeClass().addClass(CLASSES.hitarea).each(function() { var classes = ""; $.each($(this).parent().attr("class").split(" "), function() { classes += this + "-hitarea "; }); $(this).addClass( classes ); }) } // apply event to hitarea this.find("div." + CLASSES.hitarea).click( toggler ); }, treeview: function(settings) { settings = $.extend({ cookieId: "treeview" }, settings); if ( settings.toggle ) { var callback = settings.toggle; settings.toggle = function() { return callback.apply($(this).parent()[0], arguments); }; } // factory for treecontroller function treeController(tree, control) { // factory for click handlers function handler(filter) { return function() { // reuse toggle event handler, applying the elements to toggle // start searching for all hitareas toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() { // for plain toggle, no filter is provided, otherwise we need to check the parent element return filter ? $(this).parent("." + filter).length : true; }) ); return false; }; } // click on first element to collapse tree $("a:eq(0)", control).click( handler(CLASSES.collapsable) ); // click on second to expand tree $("a:eq(1)", control).click( handler(CLASSES.expandable) ); // click on third to toggle tree $("a:eq(2)", control).click( handler() ); } // handle toggle event function toggler() { $(this) .parent() // swap classes for hitarea .find(">.hitarea") .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea ) .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea ) .end() // swap classes for parent li .swapClass( CLASSES.collapsable, CLASSES.expandable ) .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable ) // find child lists .find( ">ul" ) // toggle them .heightToggle( settings.animated, settings.toggle ); if ( settings.unique ) { $(this).parent() .siblings() // swap classes for hitarea .find(">.hitarea") .replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea ) .replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea ) .end() .replaceClass( CLASSES.collapsable, CLASSES.expandable ) .replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable ) .find( ">ul" ) .heightHide( settings.animated, settings.toggle ); } } this.data("toggler", toggler); function serialize() { function binary(arg) { return arg ? 1 : 0; } var data = []; branches.each(function(i, e) { data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0; }); $.cookie(settings.cookieId, data.join(""), settings.cookieOptions ); } function deserialize() { var stored = $.cookie(settings.cookieId); if ( stored ) { var data = stored.split(""); branches.each(function(i, e) { $(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ](); }); } } // add treeview class to activate styles this.addClass("treeview"); // prepare branches and find all tree items with child lists var branches = this.find("li").prepareBranches(settings); switch(settings.persist) { case "cookie": var toggleCallback = settings.toggle; settings.toggle = function() { serialize(); if (toggleCallback) { toggleCallback.apply(this, arguments); } }; deserialize(); break; case "location": var current = this.find("a").filter(function() { return this.href.toLowerCase() == location.href.toLowerCase(); }); if ( current.length ) { // TODO update the open/closed classes var items = current.addClass("selected").parents("ul, li").add( current.next() ).show(); if (settings.prerendered) { // if prerendered is on, replicate the basic class swapping items.filter("li") .swapClass( CLASSES.collapsable, CLASSES.expandable ) .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable ) .find(">.hitarea") .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea ) .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea ); } } break; } branches.applyClasses(settings, toggler); // if control option is set, create the treecontroller and show it if ( settings.control ) { treeController(this, settings.control); $(settings.control).show(); } return this; } }); // classes used by the plugin // need to be styled via external stylesheet, see first example $.treeview = {}; var CLASSES = ($.treeview.classes = { open: "open", closed: "closed", expandable: "expandable", expandableHitarea: "expandable-hitarea", lastExpandableHitarea: "lastExpandable-hitarea", collapsable: "collapsable", collapsableHitarea: "collapsable-hitarea", lastCollapsableHitarea: "lastCollapsable-hitarea", lastCollapsable: "lastCollapsable", lastExpandable: "lastExpandable", last: "last", hitarea: "hitarea" }); })(jQuery);/* * Downloaded from http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js, 2012-02-04 23:26 */ /*! * jQuery JavaScript Library v1.7.1 * http://jquery.com/ * * Copyright 2011, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Mon Nov 21 21:11:03 2011 -0500 */ (function( window, undefined ) { // Use the correct document accordingly with window argument (sandbox) var document = window.document, navigator = window.navigator, location = window.location; var jQuery = (function() { // Define a local copy of jQuery var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); }, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, // A central reference to the root jQuery(document) rootjQuery, // A simple way to check for HTML strings or ID strings // Prioritize #id over to avoid XSS via location.hash (#9521) quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, // Check if a string has a non-whitespace character in it rnotwhite = /\S/, // Used for trimming whitespace trimLeft = /^\s+/, trimRight = /\s+$/, // Match a standalone tag rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, // JSON RegExp rvalidchars = /^[\],:{}\s]*$/, rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, // Useragent RegExp rwebkit = /(webkit)[ \/]([\w.]+)/, ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, rmsie = /(msie) ([\w.]+)/, rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, // Matches dashed string for camelizing rdashAlpha = /-([a-z]|[0-9])/ig, rmsPrefix = /^-ms-/, // Used by jQuery.camelCase as callback to replace() fcamelCase = function( all, letter ) { return ( letter + "" ).toUpperCase(); }, // Keep a UserAgent string for use with jQuery.browser userAgent = navigator.userAgent, // For matching the engine and version of the browser browserMatch, // The deferred used on DOM ready readyList, // The ready event handler DOMContentLoaded, // Save a reference to some core methods toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty, push = Array.prototype.push, slice = Array.prototype.slice, trim = String.prototype.trim, indexOf = Array.prototype.indexOf, // [[Class]] -> type pairs class2type = {}; jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined) if ( !selector ) { return this; } // Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it if ( selector === "body" && !context && document.body ) { this.context = document; this[0] = document.body; this.selector = selector; this.length = 1; return this; } // Handle HTML strings if ( typeof selector === "string" ) { // Are we dealing with HTML string or an ID? if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = quickExpr.exec( selector ); } // Verify a match, and that no context was specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; doc = ( context ? context.ownerDocument || context : document ); // If a single string is passed in and it's a single tag // just do a createElement and skip the rest ret = rsingleTag.exec( selector ); if ( ret ) { if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } else { ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; } return jQuery.merge( this, selector ); // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); }, // Start with an empty selector selector: "", // The current version of jQuery being used jquery: "1.7.1", // The default length of a jQuery object is 0 length: 0, // The number of elements contained in the matched element set size: function() { return this.length; }, toArray: function() { return slice.call( this, 0 ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { return num == null ? // Return a 'clean' array this.toArray() : // Return just the object ( num < 0 ? this[ this.length + num ] : this[ num ] ); }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems, name, selector ) { // Build a new jQuery matched element set var ret = this.constructor(); if ( jQuery.isArray( elems ) ) { push.apply( ret, elems ); } else { jQuery.merge( ret, elems ); } // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; if ( name === "find" ) { ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; } else if ( name ) { ret.selector = this.selector + "." + name + "(" + selector + ")"; } // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) each: function( callback, args ) { return jQuery.each( this, callback, args ); }, ready: function( fn ) { // Attach the listeners jQuery.bindReady(); // Add the callback readyList.add( fn ); return this; }, eq: function( i ) { i = +i; return i === -1 ? this.slice( i ) : this.slice( i, i + 1 ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ), "slice", slice.call(arguments).join(",") ); }, map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, end: function() { return this.prevObject || this.constructor(null); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: [].sort, splice: [].splice }; // Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend({ noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; }, // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Hold (or release) the ready event holdReady: function( hold ) { if ( hold ) { jQuery.readyWait++; } else { jQuery.ready( true ); } }, // Handle when the DOM is ready ready: function( wait ) { // Either a released hold or an DOMready/load event and not yet ready if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( !document.body ) { return setTimeout( jQuery.ready, 1 ); } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.fireWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { jQuery( document ).trigger( "ready" ).off( "ready" ); } } }, bindReady: function() { if ( readyList ) { return; } readyList = jQuery.Callbacks( "once memory" ); // Catch cases where $(document).ready() is called after the // browser event has already occurred. if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready return setTimeout( jQuery.ready, 1 ); } // Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); // If IE event model is used } else if ( document.attachEvent ) { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent( "onreadystatechange", DOMContentLoaded ); // A fallback to window.onload, that will always work window.attachEvent( "onload", jQuery.ready ); // If IE and not a frame // continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } }, // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, isArray: Array.isArray || function( obj ) { return jQuery.type(obj) === "array"; }, // A crude way of determining if an object is a window isWindow: function( obj ) { return obj && typeof obj === "object" && "setInterval" in obj; }, isNumeric: function( obj ) { return !isNaN( parseFloat(obj) ) && isFinite( obj ); }, type: function( obj ) { return obj == null ? String( obj ) : class2type[ toString.call(obj) ] || "object"; }, isPlainObject: function( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } try { // Not own constructor property must be Object if ( obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } } catch ( e ) { // IE8,9 Will throw exceptions on certain host objects #9897 return false; } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || hasOwn.call( obj, key ); }, isEmptyObject: function( obj ) { for ( var name in obj ) { return false; } return true; }, error: function( msg ) { throw new Error( msg ); }, parseJSON: function( data ) { if ( typeof data !== "string" || !data ) { return null; } // Make sure leading/trailing whitespace is removed (IE can't handle it) data = jQuery.trim( data ); // Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); } // Make sure the incoming data is actual JSON // Logic borrowed from http://json.org/json2.js if ( rvalidchars.test( data.replace( rvalidescape, "@" ) .replace( rvalidtokens, "]" ) .replace( rvalidbraces, "")) ) { return ( new Function( "return " + data ) )(); } jQuery.error( "Invalid JSON: " + data ); }, // Cross-browser xml parsing parseXML: function( data ) { var xml, tmp; try { if ( window.DOMParser ) { // Standard tmp = new DOMParser(); xml = tmp.parseFromString( data , "text/xml" ); } else { // IE xml = new ActiveXObject( "Microsoft.XMLDOM" ); xml.async = "false"; xml.loadXML( data ); } } catch( e ) { xml = undefined; } if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { jQuery.error( "Invalid XML: " + data ); } return xml; }, noop: function() {}, // Evaluates a script in a global context // Workarounds based on findings by Jim Driscoll // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context globalEval: function( data ) { if ( data && rnotwhite.test( data ) ) { // We use execScript on Internet Explorer // We use an anonymous function so that context is window // rather than jQuery in Firefox ( window.execScript || function( data ) { window[ "eval" ].call( window, data ); } )( data ); } }, // Convert dashed to camelCase; used by the css and data modules // Microsoft forgot to hump their vendor prefix (#9572) camelCase: function( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); }, nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); }, // args is for internal usage only each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction( object ); if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { break; } } } } return object; }, // Use native String.trim function wherever possible trim: trim ? function( text ) { return text == null ? "" : trim.call( text ); } : // Otherwise use our own trimming functionality function( text ) { return text == null ? "" : text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); }, // results is for internal usage only makeArray: function( array, results ) { var ret = results || []; if ( array != null ) { // The window, strings (and functions) also have 'length' // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 var type = jQuery.type( array ); if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { push.call( ret, array ); } else { jQuery.merge( ret, array ); } } return ret; }, inArray: function( elem, array, i ) { var len; if ( array ) { if ( indexOf ) { return indexOf.call( array, elem, i ); } len = array.length; i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; for ( ; i < len; i++ ) { // Skip accessing in sparse arrays if ( i in array && array[ i ] === elem ) { return i; } } } return -1; }, merge: function( first, second ) { var i = first.length, j = 0; if ( typeof second.length === "number" ) { for ( var l = second.length; j < l; j++ ) { first[ i++ ] = second[ j ]; } } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first; }, grep: function( elems, callback, inv ) { var ret = [], retVal; inv = !!inv; // Go through the array, only saving the items // that pass the validator function for ( var i = 0, length = elems.length; i < length; i++ ) { retVal = !!callback( elems[ i ], i ); if ( inv !== retVal ) { ret.push( elems[ i ] ); } } return ret; }, // arg is for internal usage only map: function( elems, callback, arg ) { var value, key, ret = [], i = 0, length = elems.length, // jquery objects are treated as arrays isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; // Go through the array, translating each of the items to their if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } } // Go through every key on the object, } else { for ( key in elems ) { value = callback( elems[ key ], key, arg ); if ( value != null ) { ret[ ret.length ] = value; } } } // Flatten any nested arrays return ret.concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // Bind a function to a context, optionally partially applying any // arguments. proxy: function( fn, context ) { if ( typeof context === "string" ) { var tmp = fn[ context ]; context = fn; fn = tmp; } // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. if ( !jQuery.isFunction( fn ) ) { return undefined; } // Simulated bind var args = slice.call( arguments, 2 ), proxy = function() { return fn.apply( context, args.concat( slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; return proxy; }, // Mutifunctional method to get and set values to a collection // The value/s can optionally be executed if it's a function access: function( elems, key, value, exec, fn, pass ) { var length = elems.length; // Setting many attributes if ( typeof key === "object" ) { for ( var k in key ) { jQuery.access( elems, k, key[k], exec, fn, value ); } return elems; } // Setting one attribute if ( value !== undefined ) { // Optionally, function values get executed if exec is true exec = !pass && exec && jQuery.isFunction(value); for ( var i = 0; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } return elems; } // Getting an attribute return length ? fn( elems[0], key ) : undefined; }, now: function() { return ( new Date() ).getTime(); }, // Use of jQuery.browser is frowned upon. // More details: http://docs.jquery.com/Utilities/jQuery.browser uaMatch: function( ua ) { ua = ua.toLowerCase(); var match = rwebkit.exec( ua ) || ropera.exec( ua ) || rmsie.exec( ua ) || ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || []; return { browser: match[1] || "", version: match[2] || "0" }; }, sub: function() { function jQuerySub( selector, context ) { return new jQuerySub.fn.init( selector, context ); } jQuery.extend( true, jQuerySub, this ); jQuerySub.superclass = this; jQuerySub.fn = jQuerySub.prototype = this(); jQuerySub.fn.constructor = jQuerySub; jQuerySub.sub = this.sub; jQuerySub.fn.init = function init( selector, context ) { if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { context = jQuerySub( context ); } return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); }; jQuerySub.fn.init.prototype = jQuerySub.fn; var rootjQuerySub = jQuerySub(document); return jQuerySub; }, browser: {} }); // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); }); browserMatch = jQuery.uaMatch( userAgent ); if ( browserMatch.browser ) { jQuery.browser[ browserMatch.browser ] = true; jQuery.browser.version = browserMatch.version; } // Deprecated, use jQuery.browser.webkit instead if ( jQuery.browser.webkit ) { jQuery.browser.safari = true; } // IE doesn't match non-breaking spaces with \s if ( rnotwhite.test( "\xA0" ) ) { trimLeft = /^[\s\xA0]+/; trimRight = /[\s\xA0]+$/; } // All jQuery objects should point back to these rootjQuery = jQuery(document); // Cleanup functions for the document ready method if ( document.addEventListener ) { DOMContentLoaded = function() { document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); jQuery.ready(); }; } else if ( document.attachEvent ) { DOMContentLoaded = function() { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( document.readyState === "complete" ) { document.detachEvent( "onreadystatechange", DOMContentLoaded ); jQuery.ready(); } }; } // The DOM ready check for Internet Explorer function doScrollCheck() { if ( jQuery.isReady ) { return; } try { // If IE is used, use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); } catch(e) { setTimeout( doScrollCheck, 1 ); return; } // and execute any waiting functions jQuery.ready(); } return jQuery; })(); // String to Object flags format cache var flagsCache = {}; // Convert String-formatted flags into Object-formatted ones and store in cache function createFlags( flags ) { var object = flagsCache[ flags ] = {}, i, length; flags = flags.split( /\s+/ ); for ( i = 0, length = flags.length; i < length; i++ ) { object[ flags[i] ] = true; } return object; } /* * Create a callback list using the following parameters: * * flags: an optional list of space-separated flags that will change how * the callback list behaves * * By default a callback list will act like an event callback list and can be * "fired" multiple times. * * Possible flags: * * once: will ensure the callback list can only be fired once (like a Deferred) * * memory: will keep track of previous values and will call any callback added * after the list has been fired right away with the latest "memorized" * values (like a Deferred) * * unique: will ensure a callback can only be added once (no duplicate in the list) * * stopOnFalse: interrupt callings when a callback returns false * */ jQuery.Callbacks = function( flags ) { // Convert flags from String-formatted to Object-formatted // (we check in cache first) flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; var // Actual callback list list = [], // Stack of fire calls for repeatable lists stack = [], // Last fire value (for non-forgettable lists) memory, // Flag to know if list is currently firing firing, // First callback to fire (used internally by add and fireWith) firingStart, // End of the loop when firing firingLength, // Index of currently firing callback (modified by remove if needed) firingIndex, // Add one or several callbacks to the list add = function( args ) { var i, length, elem, type, actual; for ( i = 0, length = args.length; i < length; i++ ) { elem = args[ i ]; type = jQuery.type( elem ); if ( type === "array" ) { // Inspect recursively add( elem ); } else if ( type === "function" ) { // Add if not in unique mode and callback is not in if ( !flags.unique || !self.has( elem ) ) { list.push( elem ); } } } }, // Fire callbacks fire = function( context, args ) { args = args || []; memory = !flags.memory || [ context, args ]; firing = true; firingIndex = firingStart || 0; firingStart = 0; firingLength = list.length; for ( ; list && firingIndex < firingLength; firingIndex++ ) { if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { memory = true; // Mark as halted break; } } firing = false; if ( list ) { if ( !flags.once ) { if ( stack && stack.length ) { memory = stack.shift(); self.fireWith( memory[ 0 ], memory[ 1 ] ); } } else if ( memory === true ) { self.disable(); } else { list = []; } } }, // Actual Callbacks object self = { // Add a callback or a collection of callbacks to the list add: function() { if ( list ) { var length = list.length; add( arguments ); // Do we need to add the callbacks to the // current firing batch? if ( firing ) { firingLength = list.length; // With memory, if we're not firing then // we should call right away, unless previous // firing was halted (stopOnFalse) } else if ( memory && memory !== true ) { firingStart = length; fire( memory[ 0 ], memory[ 1 ] ); } } return this; }, // Remove a callback from the list remove: function() { if ( list ) { var args = arguments, argIndex = 0, argLength = args.length; for ( ; argIndex < argLength ; argIndex++ ) { for ( var i = 0; i < list.length; i++ ) { if ( args[ argIndex ] === list[ i ] ) { // Handle firingIndex and firingLength if ( firing ) { if ( i <= firingLength ) { firingLength--; if ( i <= firingIndex ) { firingIndex--; } } } // Remove the element list.splice( i--, 1 ); // If we have some unicity property then // we only need to do this once if ( flags.unique ) { break; } } } } } return this; }, // Control if a given callback is in the list has: function( fn ) { if ( list ) { var i = 0, length = list.length; for ( ; i < length; i++ ) { if ( fn === list[ i ] ) { return true; } } } return false; }, // Remove all callbacks from the list empty: function() { list = []; return this; }, // Have the list do nothing anymore disable: function() { list = stack = memory = undefined; return this; }, // Is it disabled? disabled: function() { return !list; }, // Lock the list in its current state lock: function() { stack = undefined; if ( !memory || memory === true ) { self.disable(); } return this; }, // Is it locked? locked: function() { return !stack; }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { if ( stack ) { if ( firing ) { if ( !flags.once ) { stack.push( [ context, args ] ); } } else if ( !( flags.once && memory ) ) { fire( context, args ); } } return this; }, // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!memory; } }; return self; }; var // Static reference to slice sliceDeferred = [].slice; jQuery.extend({ Deferred: function( func ) { var doneList = jQuery.Callbacks( "once memory" ), failList = jQuery.Callbacks( "once memory" ), progressList = jQuery.Callbacks( "memory" ), state = "pending", lists = { resolve: doneList, reject: failList, notify: progressList }, promise = { done: doneList.add, fail: failList.add, progress: progressList.add, state: function() { return state; }, // Deprecated isResolved: doneList.fired, isRejected: failList.fired, then: function( doneCallbacks, failCallbacks, progressCallbacks ) { deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); return this; }, always: function() { deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); return this; }, pipe: function( fnDone, fnFail, fnProgress ) { return jQuery.Deferred(function( newDefer ) { jQuery.each( { done: [ fnDone, "resolve" ], fail: [ fnFail, "reject" ], progress: [ fnProgress, "notify" ] }, function( handler, data ) { var fn = data[ 0 ], action = data[ 1 ], returned; if ( jQuery.isFunction( fn ) ) { deferred[ handler ](function() { returned = fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); } else { newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); } }); } else { deferred[ handler ]( newDefer[ action ] ); } }); }).promise(); }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { if ( obj == null ) { obj = promise; } else { for ( var key in promise ) { obj[ key ] = promise[ key ]; } } return obj; } }, deferred = promise.promise({}), key; for ( key in lists ) { deferred[ key ] = lists[ key ].fire; deferred[ key + "With" ] = lists[ key ].fireWith; } // Handle state deferred.done( function() { state = "resolved"; }, failList.disable, progressList.lock ).fail( function() { state = "rejected"; }, doneList.disable, progressList.lock ); // Call given func if any if ( func ) { func.call( deferred, deferred ); } // All done! return deferred; }, // Deferred helper when: function( firstParam ) { var args = sliceDeferred.call( arguments, 0 ), i = 0, length = args.length, pValues = new Array( length ), count = length, pCount = length, deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? firstParam : jQuery.Deferred(), promise = deferred.promise(); function resolveFunc( i ) { return function( value ) { args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; if ( !( --count ) ) { deferred.resolveWith( deferred, args ); } }; } function progressFunc( i ) { return function( value ) { pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; deferred.notifyWith( promise, pValues ); }; } if ( length > 1 ) { for ( ; i < length; i++ ) { if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); } else { --count; } } if ( !count ) { deferred.resolveWith( deferred, args ); } } else if ( deferred !== firstParam ) { deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); } return promise; } }); jQuery.support = (function() { var support, all, a, select, opt, input, marginDiv, fragment, tds, events, eventName, i, isSupported, div = document.createElement( "div" ), documentElement = document.documentElement; // Preliminary tests div.setAttribute("className", "t"); div.innerHTML = "
    a"; all = div.getElementsByTagName( "*" ); a = div.getElementsByTagName( "a" )[ 0 ]; // Can't get basic test support if ( !all || !all.length || !a ) { return {}; } // First batch of supports tests select = document.createElement( "select" ); opt = select.appendChild( document.createElement("option") ); input = div.getElementsByTagName( "input" )[ 0 ]; support = { // IE strips leading whitespace when .innerHTML is used leadingWhitespace: ( div.firstChild.nodeType === 3 ), // Make sure that tbody elements aren't automatically inserted // IE will insert them into empty tables tbody: !div.getElementsByTagName("tbody").length, // Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE htmlSerialize: !!div.getElementsByTagName("link").length, // Get the style information from getAttribute // (IE uses .cssText instead) style: /top/.test( a.getAttribute("style") ), // Make sure that URLs aren't manipulated // (IE normalizes it by default) hrefNormalized: ( a.getAttribute("href") === "/a" ), // Make sure that element opacity exists // (IE uses filter instead) // Use a regex to work around a WebKit issue. See #5145 opacity: /^0.55/.test( a.style.opacity ), // Verify style float existence // (IE uses styleFloat instead of cssFloat) cssFloat: !!a.style.cssFloat, // Make sure that if no value is specified for a checkbox // that it defaults to "on". // (WebKit defaults to "" instead) checkOn: ( input.value === "on" ), // Make sure that a selected-by-default option has a working selected property. // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) optSelected: opt.selected, // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) getSetAttribute: div.className !== "t", // Tests for enctype support on a form(#6743) enctype: !!document.createElement("form").enctype, // Makes sure cloning an html5 element does not cause problems // Where outerHTML is undefined, this still works html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", // Will be defined later submitBubbles: true, changeBubbles: true, focusinBubbles: false, deleteExpando: true, noCloneEvent: true, inlineBlockNeedsLayout: false, shrinkWrapBlocks: false, reliableMarginRight: true }; // Make sure checked status is properly cloned input.checked = true; support.noCloneChecked = input.cloneNode( true ).checked; // Make sure that the options inside disabled selects aren't marked as disabled // (WebKit marks them as disabled) select.disabled = true; support.optDisabled = !opt.disabled; // Test to see if it's possible to delete an expando from an element // Fails in Internet Explorer try { delete div.test; } catch( e ) { support.deleteExpando = false; } if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { div.attachEvent( "onclick", function() { // Cloning a node shouldn't copy over any // bound event handlers (IE does this) support.noCloneEvent = false; }); div.cloneNode( true ).fireEvent( "onclick" ); } // Check if a radio maintains its value // after being appended to the DOM input = document.createElement("input"); input.value = "t"; input.setAttribute("type", "radio"); support.radioValue = input.value === "t"; input.setAttribute("checked", "checked"); div.appendChild( input ); fragment = document.createDocumentFragment(); fragment.appendChild( div.lastChild ); // WebKit doesn't clone checked state correctly in fragments support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; // Check if a disconnected checkbox will retain its checked // value of true after appended to the DOM (IE6/7) support.appendChecked = input.checked; fragment.removeChild( input ); fragment.appendChild( div ); div.innerHTML = ""; // Check if div with explicit width and no margin-right incorrectly // gets computed margin-right based on width of container. For more // info see bug #3333 // Fails in WebKit before Feb 2011 nightlies // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right if ( window.getComputedStyle ) { marginDiv = document.createElement( "div" ); marginDiv.style.width = "0"; marginDiv.style.marginRight = "0"; div.style.width = "2px"; div.appendChild( marginDiv ); support.reliableMarginRight = ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; } // Technique from Juriy Zaytsev // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ // We only care about the case where non-standard event systems // are used, namely in IE. Short-circuiting here helps us to // avoid an eval call (in setAttribute) which can cause CSP // to go haywire. See: https://developer.mozilla.org/en/Security/CSP if ( div.attachEvent ) { for( i in { submit: 1, change: 1, focusin: 1 }) { eventName = "on" + i; isSupported = ( eventName in div ); if ( !isSupported ) { div.setAttribute( eventName, "return;" ); isSupported = ( typeof div[ eventName ] === "function" ); } support[ i + "Bubbles" ] = isSupported; } } fragment.removeChild( div ); // Null elements to avoid leaks in IE fragment = select = opt = marginDiv = div = input = null; // Run tests that need a body at doc ready jQuery(function() { var container, outer, inner, table, td, offsetSupport, conMarginTop, ptlm, vb, style, html, body = document.getElementsByTagName("body")[0]; if ( !body ) { // Return for frameset docs that don't have a body return; } conMarginTop = 1; ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; vb = "visibility:hidden;border:0;"; style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; html = "
    " + "" + "
    "; container = document.createElement("div"); container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; body.insertBefore( container, body.firstChild ); // Construct the test element div = document.createElement("div"); container.appendChild( div ); // Check if table cells still have offsetWidth/Height when they are set // to display:none and there are still other visible table cells in a // table row; if so, offsetWidth/Height are not reliable for use when // determining if an element has been hidden directly using // display:none (it is still safe to use offsets if a parent element is // hidden; don safety goggles and see bug #4512 for more information). // (only IE 8 fails this test) div.innerHTML = "
    t
    "; tds = div.getElementsByTagName( "td" ); isSupported = ( tds[ 0 ].offsetHeight === 0 ); tds[ 0 ].style.display = ""; tds[ 1 ].style.display = "none"; // Check if empty table cells still have offsetWidth/Height // (IE <= 8 fail this test) support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); // Figure out if the W3C box model works as expected div.innerHTML = ""; div.style.width = div.style.paddingLeft = "1px"; jQuery.boxModel = support.boxModel = div.offsetWidth === 2; if ( typeof div.style.zoom !== "undefined" ) { // Check if natively block-level elements act like inline-block // elements when setting their display to 'inline' and giving // them layout // (IE < 8 does this) div.style.display = "inline"; div.style.zoom = 1; support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); // Check if elements with layout shrink-wrap their children // (IE 6 does this) div.style.display = ""; div.innerHTML = "
    "; support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); } div.style.cssText = ptlm + vb; div.innerHTML = html; outer = div.firstChild; inner = outer.firstChild; td = outer.nextSibling.firstChild.firstChild; offsetSupport = { doesNotAddBorder: ( inner.offsetTop !== 5 ), doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) }; inner.style.position = "fixed"; inner.style.top = "20px"; // safari subtracts parent border width here which is 5px offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); inner.style.position = inner.style.top = ""; outer.style.overflow = "hidden"; outer.style.position = "relative"; offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); body.removeChild( container ); div = container = null; jQuery.extend( support, offsetSupport ); }); return support; })(); var rbrace = /^(?:\{.*\}|\[.*\])$/, rmultiDash = /([A-Z])/g; jQuery.extend({ cache: {}, // Please use with caution uuid: 0, // Unique for each copy of jQuery on the page // Non-digits removed to match rinlinejQuery expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), // The following elements throw uncatchable exceptions if you // attempt to add expando properties to them. noData: { "embed": true, // Ban all objects except for Flash (which handle expandos) "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", "applet": true }, hasData: function( elem ) { elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; return !!elem && !isEmptyDataObject( elem ); }, data: function( elem, name, data, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var privateCache, thisCache, ret, internalKey = jQuery.expando, getByName = typeof name === "string", // We have to handle DOM nodes and JS objects differently because IE6-7 // can't GC object references properly across the DOM-JS boundary isNode = elem.nodeType, // Only DOM nodes need the global jQuery cache; JS object data is // attached directly to the object so GC can occur automatically cache = isNode ? jQuery.cache : elem, // Only defining an ID for JS objects if its cache already exists allows // the code to shortcut on the same path as a DOM node with no cache id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, isEvents = name === "events"; // Avoid doing any more work than we need to when trying to get data on an // object that has no data at all if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { return; } if ( !id ) { // Only DOM nodes need a new unique ID for each element since their data // ends up in the global cache if ( isNode ) { elem[ internalKey ] = id = ++jQuery.uuid; } else { id = internalKey; } } if ( !cache[ id ] ) { cache[ id ] = {}; // Avoids exposing jQuery metadata on plain JS objects when the object // is serialized using JSON.stringify if ( !isNode ) { cache[ id ].toJSON = jQuery.noop; } } // An object can be passed to jQuery.data instead of a key/value pair; this gets // shallow copied over onto the existing cache if ( typeof name === "object" || typeof name === "function" ) { if ( pvt ) { cache[ id ] = jQuery.extend( cache[ id ], name ); } else { cache[ id ].data = jQuery.extend( cache[ id ].data, name ); } } privateCache = thisCache = cache[ id ]; // jQuery data() is stored in a separate object inside the object's internal data // cache in order to avoid key collisions between internal data and user-defined // data. if ( !pvt ) { if ( !thisCache.data ) { thisCache.data = {}; } thisCache = thisCache.data; } if ( data !== undefined ) { thisCache[ jQuery.camelCase( name ) ] = data; } // Users should not attempt to inspect the internal events object using jQuery.data, // it is undocumented and subject to change. But does anyone listen? No. if ( isEvents && !thisCache[ name ] ) { return privateCache.events; } // Check for both converted-to-camel and non-converted data property names // If a data property was specified if ( getByName ) { // First Try to find as-is property data ret = thisCache[ name ]; // Test for null|undefined property data if ( ret == null ) { // Try to find the camelCased property ret = thisCache[ jQuery.camelCase( name ) ]; } } else { ret = thisCache; } return ret; }, removeData: function( elem, name, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var thisCache, i, l, // Reference to internal data cache key internalKey = jQuery.expando, isNode = elem.nodeType, // See jQuery.data for more information cache = isNode ? jQuery.cache : elem, // See jQuery.data for more information id = isNode ? elem[ internalKey ] : internalKey; // If there is already no cache entry for this object, there is no // purpose in continuing if ( !cache[ id ] ) { return; } if ( name ) { thisCache = pvt ? cache[ id ] : cache[ id ].data; if ( thisCache ) { // Support array or space separated string names for data keys if ( !jQuery.isArray( name ) ) { // try the string as a key before any manipulation if ( name in thisCache ) { name = [ name ]; } else { // split the camel cased version by spaces unless a key with the spaces exists name = jQuery.camelCase( name ); if ( name in thisCache ) { name = [ name ]; } else { name = name.split( " " ); } } } for ( i = 0, l = name.length; i < l; i++ ) { delete thisCache[ name[i] ]; } // If there is no data left in the cache, we want to continue // and let the cache object itself get destroyed if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { return; } } } // See jQuery.data for more information if ( !pvt ) { delete cache[ id ].data; // Don't destroy the parent cache unless the internal data object // had been the only thing left in it if ( !isEmptyDataObject(cache[ id ]) ) { return; } } // Browsers that fail expando deletion also refuse to delete expandos on // the window, but it will allow it on all other JS objects; other browsers // don't care // Ensure that `cache` is not a window object #10080 if ( jQuery.support.deleteExpando || !cache.setInterval ) { delete cache[ id ]; } else { cache[ id ] = null; } // We destroyed the cache and need to eliminate the expando on the node to avoid // false lookups in the cache for entries that no longer exist if ( isNode ) { // IE does not allow us to delete expando properties from nodes, // nor does it have a removeAttribute function on Document nodes; // we must handle all of these cases if ( jQuery.support.deleteExpando ) { delete elem[ internalKey ]; } else if ( elem.removeAttribute ) { elem.removeAttribute( internalKey ); } else { elem[ internalKey ] = null; } } }, // For internal use only. _data: function( elem, name, data ) { return jQuery.data( elem, name, data, true ); }, // A method for determining if a DOM node can handle the data expando acceptData: function( elem ) { if ( elem.nodeName ) { var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; if ( match ) { return !(match === true || elem.getAttribute("classid") !== match); } } return true; } }); jQuery.fn.extend({ data: function( key, value ) { var parts, attr, name, data = null; if ( typeof key === "undefined" ) { if ( this.length ) { data = jQuery.data( this[0] ); if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { attr = this[0].attributes; for ( var i = 0, l = attr.length; i < l; i++ ) { name = attr[i].name; if ( name.indexOf( "data-" ) === 0 ) { name = jQuery.camelCase( name.substring(5) ); dataAttr( this[0], name, data[ name ] ); } } jQuery._data( this[0], "parsedAttrs", true ); } } return data; } else if ( typeof key === "object" ) { return this.each(function() { jQuery.data( this, key ); }); } parts = key.split("."); parts[1] = parts[1] ? "." + parts[1] : ""; if ( value === undefined ) { data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); // Try to fetch any internally stored data first if ( data === undefined && this.length ) { data = jQuery.data( this[0], key ); data = dataAttr( this[0], key, data ); } return data === undefined && parts[1] ? this.data( parts[0] ) : data; } else { return this.each(function() { var self = jQuery( this ), args = [ parts[0], value ]; self.triggerHandler( "setData" + parts[1] + "!", args ); jQuery.data( this, key, value ); self.triggerHandler( "changeData" + parts[1] + "!", args ); }); } }, removeData: function( key ) { return this.each(function() { jQuery.removeData( this, key ); }); } }); function dataAttr( elem, key, data ) { // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if ( data === undefined && elem.nodeType === 1 ) { var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); data = elem.getAttribute( name ); if ( typeof data === "string" ) { try { data = data === "true" ? true : data === "false" ? false : data === "null" ? null : jQuery.isNumeric( data ) ? parseFloat( data ) : rbrace.test( data ) ? jQuery.parseJSON( data ) : data; } catch( e ) {} // Make sure we set the data so it isn't changed later jQuery.data( elem, key, data ); } else { data = undefined; } } return data; } // checks a cache object for emptiness function isEmptyDataObject( obj ) { for ( var name in obj ) { // if the public data object is empty, the private is still empty if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { continue; } if ( name !== "toJSON" ) { return false; } } return true; } function handleQueueMarkDefer( elem, type, src ) { var deferDataKey = type + "defer", queueDataKey = type + "queue", markDataKey = type + "mark", defer = jQuery._data( elem, deferDataKey ); if ( defer && ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { // Give room for hard-coded callbacks to fire first // and eventually mark/queue something else on the element setTimeout( function() { if ( !jQuery._data( elem, queueDataKey ) && !jQuery._data( elem, markDataKey ) ) { jQuery.removeData( elem, deferDataKey, true ); defer.fire(); } }, 0 ); } } jQuery.extend({ _mark: function( elem, type ) { if ( elem ) { type = ( type || "fx" ) + "mark"; jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); } }, _unmark: function( force, elem, type ) { if ( force !== true ) { type = elem; elem = force; force = false; } if ( elem ) { type = type || "fx"; var key = type + "mark", count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); if ( count ) { jQuery._data( elem, key, count ); } else { jQuery.removeData( elem, key, true ); handleQueueMarkDefer( elem, type, "mark" ); } } }, queue: function( elem, type, data ) { var q; if ( elem ) { type = ( type || "fx" ) + "queue"; q = jQuery._data( elem, type ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { if ( !q || jQuery.isArray(data) ) { q = jQuery._data( elem, type, jQuery.makeArray(data) ); } else { q.push( data ); } } return q || []; } }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), fn = queue.shift(), hooks = {}; // If the fx queue is dequeued, always remove the progress sentinel if ( fn === "inprogress" ) { fn = queue.shift(); } if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if ( type === "fx" ) { queue.unshift( "inprogress" ); } jQuery._data( elem, type + ".run", hooks ); fn.call( elem, function() { jQuery.dequeue( elem, type ); }, hooks ); } if ( !queue.length ) { jQuery.removeData( elem, type + "queue " + type + ".run", true ); handleQueueMarkDefer( elem, type, "queue" ); } } }); jQuery.fn.extend({ queue: function( type, data ) { if ( typeof type !== "string" ) { data = type; type = "fx"; } if ( data === undefined ) { return jQuery.queue( this[0], type ); } return this.each(function() { var queue = jQuery.queue( this, type, data ); if ( type === "fx" && queue[0] !== "inprogress" ) { jQuery.dequeue( this, type ); } }); }, dequeue: function( type ) { return this.each(function() { jQuery.dequeue( this, type ); }); }, // Based off of the plugin by Clint Helfers, with permission. // http://blindsignals.com/index.php/2009/07/jquery-delay/ delay: function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; type = type || "fx"; return this.queue( type, function( next, hooks ) { var timeout = setTimeout( next, time ); hooks.stop = function() { clearTimeout( timeout ); }; }); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); }, // Get a promise resolved when queues of a certain type // are emptied (fx is the type by default) promise: function( type, object ) { if ( typeof type !== "string" ) { object = type; type = undefined; } type = type || "fx"; var defer = jQuery.Deferred(), elements = this, i = elements.length, count = 1, deferDataKey = type + "defer", queueDataKey = type + "queue", markDataKey = type + "mark", tmp; function resolve() { if ( !( --count ) ) { defer.resolveWith( elements, [ elements ] ); } } while( i-- ) { if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { count++; tmp.add( resolve ); } } resolve(); return defer.promise(); } }); var rclass = /[\n\t\r]/g, rspace = /\s+/, rreturn = /\r/g, rtype = /^(?:button|input)$/i, rfocusable = /^(?:button|input|object|select|textarea)$/i, rclickable = /^a(?:rea)?$/i, rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, getSetAttribute = jQuery.support.getSetAttribute, nodeHook, boolHook, fixSpecified; jQuery.fn.extend({ attr: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.attr ); }, removeAttr: function( name ) { return this.each(function() { jQuery.removeAttr( this, name ); }); }, prop: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.prop ); }, removeProp: function( name ) { name = jQuery.propFix[ name ] || name; return this.each(function() { // try/catch handles cases where IE balks (such as removing a property on window) try { this[ name ] = undefined; delete this[ name ]; } catch( e ) {} }); }, addClass: function( value ) { var classNames, i, l, elem, setClass, c, cl; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).addClass( value.call(this, j, this.className) ); }); } if ( value && typeof value === "string" ) { classNames = value.split( rspace ); for ( i = 0, l = this.length; i < l; i++ ) { elem = this[ i ]; if ( elem.nodeType === 1 ) { if ( !elem.className && classNames.length === 1 ) { elem.className = value; } else { setClass = " " + elem.className + " "; for ( c = 0, cl = classNames.length; c < cl; c++ ) { if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { setClass += classNames[ c ] + " "; } } elem.className = jQuery.trim( setClass ); } } } } return this; }, removeClass: function( value ) { var classNames, i, l, elem, className, c, cl; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).removeClass( value.call(this, j, this.className) ); }); } if ( (value && typeof value === "string") || value === undefined ) { classNames = ( value || "" ).split( rspace ); for ( i = 0, l = this.length; i < l; i++ ) { elem = this[ i ]; if ( elem.nodeType === 1 && elem.className ) { if ( value ) { className = (" " + elem.className + " ").replace( rclass, " " ); for ( c = 0, cl = classNames.length; c < cl; c++ ) { className = className.replace(" " + classNames[ c ] + " ", " "); } elem.className = jQuery.trim( className ); } else { elem.className = ""; } } } } return this; }, toggleClass: function( value, stateVal ) { var type = typeof value, isBool = typeof stateVal === "boolean"; if ( jQuery.isFunction( value ) ) { return this.each(function( i ) { jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); }); } return this.each(function() { if ( type === "string" ) { // toggle individual class names var className, i = 0, self = jQuery( this ), state = stateVal, classNames = value.split( rspace ); while ( (className = classNames[ i++ ]) ) { // check each className given, space seperated list state = isBool ? state : !self.hasClass( className ); self[ state ? "addClass" : "removeClass" ]( className ); } } else if ( type === "undefined" || type === "boolean" ) { if ( this.className ) { // store className if set jQuery._data( this, "__className__", this.className ); } // toggle whole className this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; } }); }, hasClass: function( selector ) { var className = " " + selector + " ", i = 0, l = this.length; for ( ; i < l; i++ ) { if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { return true; } } return false; }, val: function( value ) { var hooks, ret, isFunction, elem = this[0]; if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { return ret; } ret = elem.value; return typeof ret === "string" ? // handle most common string cases ret.replace(rreturn, "") : // handle cases where value is null/undef or number ret == null ? "" : ret; } return; } isFunction = jQuery.isFunction( value ); return this.each(function( i ) { var self = jQuery(this), val; if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { val = value.call( this, i, self.val() ); } else { val = value; } // Treat null/undefined as ""; convert numbers to string if ( val == null ) { val = ""; } else if ( typeof val === "number" ) { val += ""; } else if ( jQuery.isArray( val ) ) { val = jQuery.map(val, function ( value ) { return value == null ? "" : value + ""; }); } hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; // If set returns undefined, fall back to normal setting if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } }); } }); jQuery.extend({ valHooks: { option: { get: function( elem ) { // attributes.value is undefined in Blackberry 4.7 but // uses .value. See #6932 var val = elem.attributes.value; return !val || val.specified ? elem.value : elem.text; } }, select: { get: function( elem ) { var value, i, max, option, index = elem.selectedIndex, values = [], options = elem.options, one = elem.type === "select-one"; // Nothing was selected if ( index < 0 ) { return null; } // Loop through all the selected options i = one ? index : 0; max = one ? index + 1 : options.length; for ( ; i < max; i++ ) { option = options[ i ]; // Don't return options that are disabled or in a disabled optgroup if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { // Get the specific value for the option value = jQuery( option ).val(); // We don't need an array for one selects if ( one ) { return value; } // Multi-Selects return an array values.push( value ); } } // Fixes Bug #2551 -- select.val() broken in IE after form.reset() if ( one && !values.length && options.length ) { return jQuery( options[ index ] ).val(); } return values; }, set: function( elem, value ) { var values = jQuery.makeArray( value ); jQuery(elem).find("option").each(function() { this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; }); if ( !values.length ) { elem.selectedIndex = -1; } return values; } } }, attrFn: { val: true, css: true, html: true, text: true, data: true, width: true, height: true, offset: true }, attr: function( elem, name, value, pass ) { var ret, hooks, notxml, nType = elem.nodeType; // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } if ( pass && name in jQuery.attrFn ) { return jQuery( elem )[ name ]( value ); } // Fallback to prop when attributes are not supported if ( typeof elem.getAttribute === "undefined" ) { return jQuery.prop( elem, name, value ); } notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); // All attributes are lowercase // Grab necessary hook if one is defined if ( notxml ) { name = name.toLowerCase(); hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); } if ( value !== undefined ) { if ( value === null ) { jQuery.removeAttr( elem, name ); return; } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { elem.setAttribute( name, "" + value ); return value; } } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { ret = elem.getAttribute( name ); // Non-existent attributes return null, we normalize to undefined return ret === null ? undefined : ret; } }, removeAttr: function( elem, value ) { var propName, attrNames, name, l, i = 0; if ( value && elem.nodeType === 1 ) { attrNames = value.toLowerCase().split( rspace ); l = attrNames.length; for ( ; i < l; i++ ) { name = attrNames[ i ]; if ( name ) { propName = jQuery.propFix[ name ] || name; // See #9699 for explanation of this approach (setting first, then removal) jQuery.attr( elem, name, "" ); elem.removeAttribute( getSetAttribute ? name : propName ); // Set corresponding property to false for boolean attributes if ( rboolean.test( name ) && propName in elem ) { elem[ propName ] = false; } } } } }, attrHooks: { type: { set: function( elem, value ) { // We can't allow the type property to be changed (since it causes problems in IE) if ( rtype.test( elem.nodeName ) && elem.parentNode ) { jQuery.error( "type property can't be changed" ); } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { // Setting the type on a radio button after the value resets the value in IE6-9 // Reset value to it's default in case type is set after value // This is for element creation var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; } return value; } } }, // Use the value property for back compat // Use the nodeHook for button elements in IE6/7 (#1954) value: { get: function( elem, name ) { if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { return nodeHook.get( elem, name ); } return name in elem ? elem.value : null; }, set: function( elem, value, name ) { if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { return nodeHook.set( elem, value, name ); } // Does not return so that setAttribute is also used elem.value = value; } } }, propFix: { tabindex: "tabIndex", readonly: "readOnly", "for": "htmlFor", "class": "className", maxlength: "maxLength", cellspacing: "cellSpacing", cellpadding: "cellPadding", rowspan: "rowSpan", colspan: "colSpan", usemap: "useMap", frameborder: "frameBorder", contenteditable: "contentEditable" }, prop: function( elem, name, value ) { var ret, hooks, notxml, nType = elem.nodeType; // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); if ( notxml ) { // Fix name and attach hooks name = jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; } if ( value !== undefined ) { if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { return ( elem[ name ] = value ); } } else { if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { return elem[ name ]; } } }, propHooks: { tabIndex: { get: function( elem ) { // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ var attributeNode = elem.getAttributeNode("tabindex"); return attributeNode && attributeNode.specified ? parseInt( attributeNode.value, 10 ) : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : undefined; } } } }); // Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; // Hook for boolean attributes boolHook = { get: function( elem, name ) { // Align boolean attributes with corresponding properties // Fall back to attribute presence where some booleans are not supported var attrNode, property = jQuery.prop( elem, name ); return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? name.toLowerCase() : undefined; }, set: function( elem, value, name ) { var propName; if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); } else { // value is true since we know at this point it's type boolean and not false // Set boolean attributes to the same name and set the DOM property propName = jQuery.propFix[ name ] || name; if ( propName in elem ) { // Only set the IDL specifically if it already exists on the element elem[ propName ] = true; } elem.setAttribute( name, name.toLowerCase() ); } return name; } }; // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !getSetAttribute ) { fixSpecified = { name: true, id: true }; // Use this for any attribute in IE6/7 // This fixes almost every IE6/7 issue nodeHook = jQuery.valHooks.button = { get: function( elem, name ) { var ret; ret = elem.getAttributeNode( name ); return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? ret.nodeValue : undefined; }, set: function( elem, value, name ) { // Set the existing or create a new attribute node var ret = elem.getAttributeNode( name ); if ( !ret ) { ret = document.createAttribute( name ); elem.setAttributeNode( ret ); } return ( ret.nodeValue = value + "" ); } }; // Apply the nodeHook to tabindex jQuery.attrHooks.tabindex.set = nodeHook.set; // Set width and height to auto instead of 0 on empty string( Bug #8150 ) // This is for removals jQuery.each([ "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { set: function( elem, value ) { if ( value === "" ) { elem.setAttribute( name, "auto" ); return value; } } }); }); // Set contenteditable to false on removals(#10429) // Setting to empty string throws an error as an invalid value jQuery.attrHooks.contenteditable = { get: nodeHook.get, set: function( elem, value, name ) { if ( value === "" ) { value = "false"; } nodeHook.set( elem, value, name ); } }; } // Some attributes require a special call on IE if ( !jQuery.support.hrefNormalized ) { jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { get: function( elem ) { var ret = elem.getAttribute( name, 2 ); return ret === null ? undefined : ret; } }); }); } if ( !jQuery.support.style ) { jQuery.attrHooks.style = { get: function( elem ) { // Return undefined in the case of empty string // Normalize to lowercase since IE uppercases css property names return elem.style.cssText.toLowerCase() || undefined; }, set: function( elem, value ) { return ( elem.style.cssText = "" + value ); } }; } // Safari mis-reports the default selected property of an option // Accessing the parent's selectedIndex property fixes it if ( !jQuery.support.optSelected ) { jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { get: function( elem ) { var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; // Make sure that it also works with optgroups, see #5701 if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } return null; } }); } // IE6/7 call enctype encoding if ( !jQuery.support.enctype ) { jQuery.propFix.enctype = "encoding"; } // Radios and checkboxes getter/setter if ( !jQuery.support.checkOn ) { jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = { get: function( elem ) { // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified return elem.getAttribute("value") === null ? "on" : elem.value; } }; }); } jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { set: function( elem, value ) { if ( jQuery.isArray( value ) ) { return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); } } }); }); var rformElems = /^(?:textarea|input|select)$/i, rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, rhoverHack = /\bhover(\.\S+)?\b/, rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|contextmenu)|click/, rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, quickParse = function( selector ) { var quick = rquickIs.exec( selector ); if ( quick ) { // 0 1 2 3 // [ _, tag, id, class ] quick[1] = ( quick[1] || "" ).toLowerCase(); quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); } return quick; }, quickIs = function( elem, m ) { var attrs = elem.attributes || {}; return ( (!m[1] || elem.nodeName.toLowerCase() === m[1]) && (!m[2] || (attrs.id || {}).value === m[2]) && (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) ); }, hoverHack = function( events ) { return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); }; /* * Helper functions for managing events -- not part of the public interface. * Props to Dean Edwards' addEvent library for many of the ideas. */ jQuery.event = { add: function( elem, types, handler, data, selector ) { var elemData, eventHandle, events, t, tns, type, namespaces, handleObj, handleObjIn, quick, handlers, special; // Don't attach events to noData or text/comment nodes (allow plain objects tho) if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { return; } // Caller can pass in an object of custom data in lieu of the handler if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; } // Make sure that the handler has a unique ID, used to find/remove it later if ( !handler.guid ) { handler.guid = jQuery.guid++; } // Init the element's event structure and main handler, if this is the first events = elemData.events; if ( !events ) { elemData.events = events = {}; } eventHandle = elemData.handle; if ( !eventHandle ) { elemData.handle = eventHandle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : undefined; }; // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events eventHandle.elem = elem; } // Handle multiple events separated by a space // jQuery(...).bind("mouseover mouseout", fn); types = jQuery.trim( hoverHack(types) ).split( " " ); for ( t = 0; t < types.length; t++ ) { tns = rtypenamespace.exec( types[t] ) || []; type = tns[1]; namespaces = ( tns[2] || "" ).split( "." ).sort(); // If event changes its type, use the special event handlers for the changed type special = jQuery.event.special[ type ] || {}; // If selector defined, determine special event api type, otherwise given type type = ( selector ? special.delegateType : special.bindType ) || type; // Update special based on newly reset type special = jQuery.event.special[ type ] || {}; // handleObj is passed to all event handlers handleObj = jQuery.extend({ type: type, origType: tns[1], data: data, handler: handler, guid: handler.guid, selector: selector, quick: quickParse( selector ), namespace: namespaces.join(".") }, handleObjIn ); // Init the event handler queue if we're the first handlers = events[ type ]; if ( !handlers ) { handlers = events[ type ] = []; handlers.delegateCount = 0; // Only use addEventListener/attachEvent if the special events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { // Bind the global event handler to the element if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, eventHandle ); } } } if ( special.add ) { special.add.call( elem, handleObj ); if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // Add to the element's handler list, delegates in front if ( selector ) { handlers.splice( handlers.delegateCount++, 0, handleObj ); } else { handlers.push( handleObj ); } // Keep track of which events have ever been used, for event optimization jQuery.event.global[ type ] = true; } // Nullify elem to prevent memory leaks in IE elem = null; }, global: {}, // Detach an event or set of events from an element remove: function( elem, types, handler, selector, mappedTypes ) { var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), t, tns, type, origType, namespaces, origCount, j, events, special, handle, eventType, handleObj; if ( !elemData || !(events = elemData.events) ) { return; } // Once for each type.namespace in types; type may be omitted types = jQuery.trim( hoverHack( types || "" ) ).split(" "); for ( t = 0; t < types.length; t++ ) { tns = rtypenamespace.exec( types[t] ) || []; type = origType = tns[1]; namespaces = tns[2]; // Unbind all events (on this namespace, if provided) for the element if ( !type ) { for ( type in events ) { jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); } continue; } special = jQuery.event.special[ type ] || {}; type = ( selector? special.delegateType : special.bindType ) || type; eventType = events[ type ] || []; origCount = eventType.length; namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; // Remove matching events for ( j = 0; j < eventType.length; j++ ) { handleObj = eventType[ j ]; if ( ( mappedTypes || origType === handleObj.origType ) && ( !handler || handler.guid === handleObj.guid ) && ( !namespaces || namespaces.test( handleObj.namespace ) ) && ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { eventType.splice( j--, 1 ); if ( handleObj.selector ) { eventType.delegateCount--; } if ( special.remove ) { special.remove.call( elem, handleObj ); } } } // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) if ( eventType.length === 0 && origCount !== eventType.length ) { if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); } delete events[ type ]; } } // Remove the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { handle = elemData.handle; if ( handle ) { handle.elem = null; } // removeData also checks for emptiness and clears the expando if empty // so use it instead of delete jQuery.removeData( elem, [ "events", "handle" ], true ); } }, // Events that are safe to short-circuit if no handlers are attached. // Native DOM events should not be added, they may have inline handlers. customEvent: { "getData": true, "setData": true, "changeData": true }, trigger: function( event, data, elem, onlyHandlers ) { // Don't do events on text and comment nodes if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { return; } // Event object or event type var type = event.type || event, namespaces = [], cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; // focus/blur morphs to focusin/out; ensure we're not firing them right now if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { return; } if ( type.indexOf( "!" ) >= 0 ) { // Exclusive events trigger only for the exact event (no namespaces) type = type.slice(0, -1); exclusive = true; } if ( type.indexOf( "." ) >= 0 ) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split("."); type = namespaces.shift(); namespaces.sort(); } if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { // No jQuery handlers for this event type, and it can't have inline handlers return; } // Caller can pass in an Event, Object, or just an event type string event = typeof event === "object" ? // jQuery.Event object event[ jQuery.expando ] ? event : // Object literal new jQuery.Event( type, event ) : // Just the event type (string) new jQuery.Event( type ); event.type = type; event.isTrigger = true; event.exclusive = exclusive; event.namespace = namespaces.join( "." ); event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; // Handle a global trigger if ( !elem ) { // TODO: Stop taunting the data cache; remove global events and always attach to document cache = jQuery.cache; for ( i in cache ) { if ( cache[ i ].events && cache[ i ].events[ type ] ) { jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); } } return; } // Clean up the event in case it is being reused event.result = undefined; if ( !event.target ) { event.target = elem; } // Clone any incoming data and prepend the event, creating the handler arg list data = data != null ? jQuery.makeArray( data ) : []; data.unshift( event ); // Allow special events to draw outside the lines special = jQuery.event.special[ type ] || {}; if ( special.trigger && special.trigger.apply( elem, data ) === false ) { return; } // Determine event propagation path in advance, per W3C events spec (#9951) // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) eventPath = [[ elem, special.bindType || type ]]; if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { bubbleType = special.delegateType || type; cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; old = null; for ( ; cur; cur = cur.parentNode ) { eventPath.push([ cur, bubbleType ]); old = cur; } // Only add window if we got to document (e.g., not plain obj or detached DOM) if ( old && old === elem.ownerDocument ) { eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); } } // Fire handlers on the event path for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { cur = eventPath[i][0]; event.type = eventPath[i][1]; handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); } // Note that this is a bare JS function and not a jQuery handler handle = ontype && cur[ ontype ]; if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { event.preventDefault(); } } event.type = type; // If nobody prevented the default action, do it now if ( !onlyHandlers && !event.isDefaultPrevented() ) { if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { // Call a native DOM method on the target with the same name name as the event. // Can't use an .isFunction() check here because IE6/7 fails that test. // Don't do default actions on window, that's where global variables be (#6170) // IE<9 dies on focus/blur to hidden element (#1486) if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method old = elem[ ontype ]; if ( old ) { elem[ ontype ] = null; } // Prevent re-triggering of the same event, since we already bubbled it above jQuery.event.triggered = type; elem[ type ](); jQuery.event.triggered = undefined; if ( old ) { elem[ ontype ] = old; } } } } return event.result; }, dispatch: function( event ) { // Make a writable jQuery.Event from the native event object event = jQuery.event.fix( event || window.event ); var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), delegateCount = handlers.delegateCount, args = [].slice.call( arguments, 0 ), run_all = !event.exclusive && !event.namespace, handlerQueue = [], i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; // Use the fix-ed jQuery.Event rather than the (read-only) native event args[0] = event; event.delegateTarget = this; // Determine handlers that should run if there are delegated events // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { // Pregenerate a single jQuery object for reuse with .is() jqcur = jQuery(this); jqcur.context = this.ownerDocument || this; for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { selMatch = {}; matches = []; jqcur[0] = cur; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; sel = handleObj.selector; if ( selMatch[ sel ] === undefined ) { selMatch[ sel ] = ( handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) ); } if ( selMatch[ sel ] ) { matches.push( handleObj ); } } if ( matches.length ) { handlerQueue.push({ elem: cur, matches: matches }); } } } // Add the remaining (directly-bound) handlers if ( handlers.length > delegateCount ) { handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); } // Run delegates first; they may want to stop propagation beneath us for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { matched = handlerQueue[ i ]; event.currentTarget = matched.elem; for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { handleObj = matched.matches[ j ]; // Triggered event must either 1) be non-exclusive and have no namespace, or // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { event.data = handleObj.data; event.handleObj = handleObj; ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) .apply( matched.elem, args ); if ( ret !== undefined ) { event.result = ret; if ( ret === false ) { event.preventDefault(); event.stopPropagation(); } } } } } return event.result; }, // Includes some event props shared by KeyEvent and MouseEvent // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), fixHooks: {}, keyHooks: { props: "char charCode key keyCode".split(" "), filter: function( event, original ) { // Add which for key events if ( event.which == null ) { event.which = original.charCode != null ? original.charCode : original.keyCode; } return event; } }, mouseHooks: { props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), filter: function( event, original ) { var eventDoc, doc, body, button = original.button, fromElement = original.fromElement; // Calculate pageX/Y if missing and clientX/Y available if ( event.pageX == null && original.clientX != null ) { eventDoc = event.target.ownerDocument || document; doc = eventDoc.documentElement; body = eventDoc.body; event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); } // Add relatedTarget, if necessary if ( !event.relatedTarget && fromElement ) { event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; } // Add which for click: 1 === left; 2 === middle; 3 === right // Note: button is not normalized, so don't use it if ( !event.which && button !== undefined ) { event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); } return event; } }, fix: function( event ) { if ( event[ jQuery.expando ] ) { return event; } // Create a writable copy of the event object and normalize some properties var i, prop, originalEvent = event, fixHook = jQuery.event.fixHooks[ event.type ] || {}, copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; event = jQuery.Event( originalEvent ); for ( i = copy.length; i; ) { prop = copy[ --i ]; event[ prop ] = originalEvent[ prop ]; } // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) if ( !event.target ) { event.target = originalEvent.srcElement || document; } // Target should not be a text node (#504, Safari) if ( event.target.nodeType === 3 ) { event.target = event.target.parentNode; } // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) if ( event.metaKey === undefined ) { event.metaKey = event.ctrlKey; } return fixHook.filter? fixHook.filter( event, originalEvent ) : event; }, special: { ready: { // Make sure the ready event is setup setup: jQuery.bindReady }, load: { // Prevent triggered image.load events from bubbling to window.load noBubble: true }, focus: { delegateType: "focusin" }, blur: { delegateType: "focusout" }, beforeunload: { setup: function( data, namespaces, eventHandle ) { // We only want to do this special case on windows if ( jQuery.isWindow( this ) ) { this.onbeforeunload = eventHandle; } }, teardown: function( namespaces, eventHandle ) { if ( this.onbeforeunload === eventHandle ) { this.onbeforeunload = null; } } } }, simulate: function( type, elem, event, bubble ) { // Piggyback on a donor event to simulate a different one. // Fake originalEvent to avoid donor's stopPropagation, but if the // simulated event prevents default then we do the same on the donor. var e = jQuery.extend( new jQuery.Event(), event, { type: type, isSimulated: true, originalEvent: {} } ); if ( bubble ) { jQuery.event.trigger( e, null, elem ); } else { jQuery.event.dispatch.call( elem, e ); } if ( e.isDefaultPrevented() ) { event.preventDefault(); } } }; // Some plugins are using, but it's undocumented/deprecated and will be removed. // The 1.7 special event interface should provide all the hooks needed now. jQuery.event.handle = jQuery.event.dispatch; jQuery.removeEvent = document.removeEventListener ? function( elem, type, handle ) { if ( elem.removeEventListener ) { elem.removeEventListener( type, handle, false ); } } : function( elem, type, handle ) { if ( elem.detachEvent ) { elem.detachEvent( "on" + type, handle ); } }; jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !(this instanceof jQuery.Event) ) { return new jQuery.Event( src, props ); } // Event object if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; // Event type } else { this.type = src; } // Put explicitly provided properties onto the event object if ( props ) { jQuery.extend( this, props ); } // Create a timestamp if incoming event doesn't have one this.timeStamp = src && src.timeStamp || jQuery.now(); // Mark it as fixed this[ jQuery.expando ] = true; }; function returnFalse() { return false; } function returnTrue() { return true; } // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { preventDefault: function() { this.isDefaultPrevented = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if preventDefault exists run it on the original event if ( e.preventDefault ) { e.preventDefault(); // otherwise set the returnValue property of the original event to false (IE) } else { e.returnValue = false; } }, stopPropagation: function() { this.isPropagationStopped = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if stopPropagation exists run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // otherwise set the cancelBubble property of the original event to true (IE) e.cancelBubble = true; }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); }, isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse }; // Create mouseenter/leave events using mouseover/out and event-time checks jQuery.each({ mouseenter: "mouseover", mouseleave: "mouseout" }, function( orig, fix ) { jQuery.event.special[ orig ] = { delegateType: fix, bindType: fix, handle: function( event ) { var target = this, related = event.relatedTarget, handleObj = event.handleObj, selector = handleObj.selector, ret; // For mousenter/leave call the handler if related is outside the target. // NB: No relatedTarget if the mouse left/entered the browser window if ( !related || (related !== target && !jQuery.contains( target, related )) ) { event.type = handleObj.origType; ret = handleObj.handler.apply( this, arguments ); event.type = fix; } return ret; } }; }); // IE submit delegation if ( !jQuery.support.submitBubbles ) { jQuery.event.special.submit = { setup: function() { // Only need this for delegated form submit events if ( jQuery.nodeName( this, "form" ) ) { return false; } // Lazy-add a submit handler when a descendant form may potentially be submitted jQuery.event.add( this, "click._submit keypress._submit", function( e ) { // Node name check avoids a VML-related crash in IE (#9807) var elem = e.target, form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; if ( form && !form._submit_attached ) { jQuery.event.add( form, "submit._submit", function( event ) { // If form was submitted by the user, bubble the event up the tree if ( this.parentNode && !event.isTrigger ) { jQuery.event.simulate( "submit", this.parentNode, event, true ); } }); form._submit_attached = true; } }); // return undefined since we don't need an event listener }, teardown: function() { // Only need this for delegated form submit events if ( jQuery.nodeName( this, "form" ) ) { return false; } // Remove delegated handlers; cleanData eventually reaps submit handlers attached above jQuery.event.remove( this, "._submit" ); } }; } // IE change delegation and checkbox/radio fix if ( !jQuery.support.changeBubbles ) { jQuery.event.special.change = { setup: function() { if ( rformElems.test( this.nodeName ) ) { // IE doesn't fire change on a check/radio until blur; trigger it on click // after a propertychange. Eat the blur-change in special.change.handle. // This still fires onchange a second time for check/radio after blur. if ( this.type === "checkbox" || this.type === "radio" ) { jQuery.event.add( this, "propertychange._change", function( event ) { if ( event.originalEvent.propertyName === "checked" ) { this._just_changed = true; } }); jQuery.event.add( this, "click._change", function( event ) { if ( this._just_changed && !event.isTrigger ) { this._just_changed = false; jQuery.event.simulate( "change", this, event, true ); } }); } return false; } // Delegated event; lazy-add a change handler on descendant inputs jQuery.event.add( this, "beforeactivate._change", function( e ) { var elem = e.target; if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { jQuery.event.add( elem, "change._change", function( event ) { if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { jQuery.event.simulate( "change", this.parentNode, event, true ); } }); elem._change_attached = true; } }); }, handle: function( event ) { var elem = event.target; // Swallow native change events from checkbox/radio, we already triggered them above if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { return event.handleObj.handler.apply( this, arguments ); } }, teardown: function() { jQuery.event.remove( this, "._change" ); return rformElems.test( this.nodeName ); } }; } // Create "bubbling" focus and blur events if ( !jQuery.support.focusinBubbles ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { // Attach a single capturing handler while someone wants focusin/focusout var attaches = 0, handler = function( event ) { jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); }; jQuery.event.special[ fix ] = { setup: function() { if ( attaches++ === 0 ) { document.addEventListener( orig, handler, true ); } }, teardown: function() { if ( --attaches === 0 ) { document.removeEventListener( orig, handler, true ); } } }; }); } jQuery.fn.extend({ on: function( types, selector, data, fn, /*INTERNAL*/ one ) { var origFn, type; // Types can be a map of types/handlers if ( typeof types === "object" ) { // ( types-Object, selector, data ) if ( typeof selector !== "string" ) { // ( types-Object, data ) data = selector; selector = undefined; } for ( type in types ) { this.on( type, selector, data, types[ type ], one ); } return this; } if ( data == null && fn == null ) { // ( types, fn ) fn = selector; data = selector = undefined; } else if ( fn == null ) { if ( typeof selector === "string" ) { // ( types, selector, fn ) fn = data; data = undefined; } else { // ( types, data, fn ) fn = data; data = selector; selector = undefined; } } if ( fn === false ) { fn = returnFalse; } else if ( !fn ) { return this; } if ( one === 1 ) { origFn = fn; fn = function( event ) { // Can use an empty set, since event contains the info jQuery().off( event ); return origFn.apply( this, arguments ); }; // Use same guid so caller can remove using origFn fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); } return this.each( function() { jQuery.event.add( this, types, fn, data, selector ); }); }, one: function( types, selector, data, fn ) { return this.on.call( this, types, selector, data, fn, 1 ); }, off: function( types, selector, fn ) { if ( types && types.preventDefault && types.handleObj ) { // ( event ) dispatched jQuery.Event var handleObj = types.handleObj; jQuery( types.delegateTarget ).off( handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, handleObj.selector, handleObj.handler ); return this; } if ( typeof types === "object" ) { // ( types-object [, selector] ) for ( var type in types ) { this.off( type, selector, types[ type ] ); } return this; } if ( selector === false || typeof selector === "function" ) { // ( types [, fn] ) fn = selector; selector = undefined; } if ( fn === false ) { fn = returnFalse; } return this.each(function() { jQuery.event.remove( this, types, fn, selector ); }); }, bind: function( types, data, fn ) { return this.on( types, null, data, fn ); }, unbind: function( types, fn ) { return this.off( types, null, fn ); }, live: function( types, data, fn ) { jQuery( this.context ).on( types, this.selector, data, fn ); return this; }, die: function( types, fn ) { jQuery( this.context ).off( types, this.selector || "**", fn ); return this; }, delegate: function( selector, types, data, fn ) { return this.on( types, selector, data, fn ); }, undelegate: function( selector, types, fn ) { // ( namespace ) or ( selector, types [, fn] ) return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); }, trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); }); }, triggerHandler: function( type, data ) { if ( this[0] ) { return jQuery.event.trigger( type, data, this[0], true ); } }, toggle: function( fn ) { // Save reference to arguments for access in closure var args = arguments, guid = fn.guid || jQuery.guid++, i = 0, toggler = function( event ) { // Figure out which function to execute var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); // Make sure that clicks stop event.preventDefault(); // and execute the function return args[ lastToggle ].apply( this, arguments ) || false; }; // link all the functions, so any of them can unbind this click handler toggler.guid = guid; while ( i < args.length ) { args[ i++ ].guid = guid; } return this.click( toggler ); }, hover: function( fnOver, fnOut ) { return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); } }); jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { // Handle event binding jQuery.fn[ name ] = function( data, fn ) { if ( fn == null ) { fn = data; data = null; } return arguments.length > 0 ? this.on( name, null, data, fn ) : this.trigger( name ); }; if ( jQuery.attrFn ) { jQuery.attrFn[ name ] = true; } if ( rkeyEvent.test( name ) ) { jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; } if ( rmouseEvent.test( name ) ) { jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; } }); /*! * Sizzle CSS Selector Engine * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ (function(){ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, expando = "sizcache" + (Math.random() + '').replace('.', ''), done = 0, toString = Object.prototype.toString, hasDuplicate = false, baseHasDuplicate = true, rBackslash = /\\/g, rReturn = /\r\n/g, rNonWord = /\W/; // Here we check if the JavaScript engine is using some sort of // optimization where it does not always call our comparision // function. If that is the case, discard the hasDuplicate value. // Thus far that includes Google Chrome. [0, 0].sort(function() { baseHasDuplicate = false; return 0; }); var Sizzle = function( selector, context, results, seed ) { results = results || []; context = context || document; var origContext = context; if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } if ( !selector || typeof selector !== "string" ) { return results; } var m, set, checkSet, extra, ret, cur, pop, i, prune = true, contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); m = chunker.exec( soFar ); if ( m ) { soFar = m[3]; parts.push( m[1] ); if ( m[2] ) { extra = m[3]; break; } } } while ( m ); if ( parts.length > 1 && origPOS.exec( selector ) ) { if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { set = posProcess( parts[0] + parts[1], context, seed ); } else { set = Expr.relative[ parts[0] ] ? [ context ] : Sizzle( parts.shift(), context ); while ( parts.length ) { selector = parts.shift(); if ( Expr.relative[ selector ] ) { selector += parts.shift(); } set = posProcess( selector, set, seed ); } } } else { // Take a shortcut and set the context if the root selector is an ID // (but not if it'll be faster if the inner selector is an ID) if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { ret = Sizzle.find( parts.shift(), context, contextXML ); context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; } if ( context ) { ret = seed ? { expr: parts.pop(), set: makeArray(seed) } : Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; if ( parts.length > 0 ) { checkSet = makeArray( set ); } else { prune = false; } while ( parts.length ) { cur = parts.pop(); pop = cur; if ( !Expr.relative[ cur ] ) { cur = ""; } else { pop = parts.pop(); } if ( pop == null ) { pop = context; } Expr.relative[ cur ]( checkSet, pop, contextXML ); } } else { checkSet = parts = []; } } if ( !checkSet ) { checkSet = set; } if ( !checkSet ) { Sizzle.error( cur || selector ); } if ( toString.call(checkSet) === "[object Array]" ) { if ( !prune ) { results.push.apply( results, checkSet ); } else if ( context && context.nodeType === 1 ) { for ( i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { results.push( set[i] ); } } } else { for ( i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && checkSet[i].nodeType === 1 ) { results.push( set[i] ); } } } } else { makeArray( checkSet, results ); } if ( extra ) { Sizzle( extra, origContext, results, seed ); Sizzle.uniqueSort( results ); } return results; }; Sizzle.uniqueSort = function( results ) { if ( sortOrder ) { hasDuplicate = baseHasDuplicate; results.sort( sortOrder ); if ( hasDuplicate ) { for ( var i = 1; i < results.length; i++ ) { if ( results[i] === results[ i - 1 ] ) { results.splice( i--, 1 ); } } } } return results; }; Sizzle.matches = function( expr, set ) { return Sizzle( expr, null, null, set ); }; Sizzle.matchesSelector = function( node, expr ) { return Sizzle( expr, null, null, [node] ).length > 0; }; Sizzle.find = function( expr, context, isXML ) { var set, i, len, match, type, left; if ( !expr ) { return []; } for ( i = 0, len = Expr.order.length; i < len; i++ ) { type = Expr.order[i]; if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { left = match[1]; match.splice( 1, 1 ); if ( left.substr( left.length - 1 ) !== "\\" ) { match[1] = (match[1] || "").replace( rBackslash, "" ); set = Expr.find[ type ]( match, context, isXML ); if ( set != null ) { expr = expr.replace( Expr.match[ type ], "" ); break; } } } } if ( !set ) { set = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName( "*" ) : []; } return { set: set, expr: expr }; }; Sizzle.filter = function( expr, set, inplace, not ) { var match, anyFound, type, found, item, filter, left, i, pass, old = expr, result = [], curLoop = set, isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); while ( expr && set.length ) { for ( type in Expr.filter ) { if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { filter = Expr.filter[ type ]; left = match[1]; anyFound = false; match.splice(1,1); if ( left.substr( left.length - 1 ) === "\\" ) { continue; } if ( curLoop === result ) { result = []; } if ( Expr.preFilter[ type ] ) { match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); if ( !match ) { anyFound = found = true; } else if ( match === true ) { continue; } } if ( match ) { for ( i = 0; (item = curLoop[i]) != null; i++ ) { if ( item ) { found = filter( item, match, i, curLoop ); pass = not ^ found; if ( inplace && found != null ) { if ( pass ) { anyFound = true; } else { curLoop[i] = false; } } else if ( pass ) { result.push( item ); anyFound = true; } } } } if ( found !== undefined ) { if ( !inplace ) { curLoop = result; } expr = expr.replace( Expr.match[ type ], "" ); if ( !anyFound ) { return []; } break; } } } // Improper expression if ( expr === old ) { if ( anyFound == null ) { Sizzle.error( expr ); } else { break; } } old = expr; } return curLoop; }; Sizzle.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); }; /** * Utility function for retreiving the text value of an array of DOM nodes * @param {Array|Element} elem */ var getText = Sizzle.getText = function( elem ) { var i, node, nodeType = elem.nodeType, ret = ""; if ( nodeType ) { if ( nodeType === 1 || nodeType === 9 ) { // Use textContent || innerText for elements if ( typeof elem.textContent === 'string' ) { return elem.textContent; } else if ( typeof elem.innerText === 'string' ) { // Replace IE's carriage returns return elem.innerText.replace( rReturn, '' ); } else { // Traverse it's children for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { ret += getText( elem ); } } } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } } else { // If no nodeType, this is expected to be an array for ( i = 0; (node = elem[i]); i++ ) { // Do not traverse comment nodes if ( node.nodeType !== 8 ) { ret += getText( node ); } } } return ret; }; var Expr = Sizzle.selectors = { order: [ "ID", "NAME", "TAG" ], match: { ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ }, leftMatch: {}, attrMap: { "class": "className", "for": "htmlFor" }, attrHandle: { href: function( elem ) { return elem.getAttribute( "href" ); }, type: function( elem ) { return elem.getAttribute( "type" ); } }, relative: { "+": function(checkSet, part){ var isPartStr = typeof part === "string", isTag = isPartStr && !rNonWord.test( part ), isPartStrNotTag = isPartStr && !isTag; if ( isTag ) { part = part.toLowerCase(); } for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { if ( (elem = checkSet[i]) ) { while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? elem || false : elem === part; } } if ( isPartStrNotTag ) { Sizzle.filter( part, checkSet, true ); } }, ">": function( checkSet, part ) { var elem, isPartStr = typeof part === "string", i = 0, l = checkSet.length; if ( isPartStr && !rNonWord.test( part ) ) { part = part.toLowerCase(); for ( ; i < l; i++ ) { elem = checkSet[i]; if ( elem ) { var parent = elem.parentNode; checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; } } } else { for ( ; i < l; i++ ) { elem = checkSet[i]; if ( elem ) { checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part; } } if ( isPartStr ) { Sizzle.filter( part, checkSet, true ); } } }, "": function(checkSet, part, isXML){ var nodeCheck, doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) { part = part.toLowerCase(); nodeCheck = part; checkFn = dirNodeCheck; } checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); }, "~": function( checkSet, part, isXML ) { var nodeCheck, doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) { part = part.toLowerCase(); nodeCheck = part; checkFn = dirNodeCheck; } checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); } }, find: { ID: function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 return m && m.parentNode ? [m] : []; } }, NAME: function( match, context ) { if ( typeof context.getElementsByName !== "undefined" ) { var ret = [], results = context.getElementsByName( match[1] ); for ( var i = 0, l = results.length; i < l; i++ ) { if ( results[i].getAttribute("name") === match[1] ) { ret.push( results[i] ); } } return ret.length === 0 ? null : ret; } }, TAG: function( match, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( match[1] ); } } }, preFilter: { CLASS: function( match, curLoop, inplace, result, not, isXML ) { match = " " + match[1].replace( rBackslash, "" ) + " "; if ( isXML ) { return match; } for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { if ( elem ) { if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { if ( !inplace ) { result.push( elem ); } } else if ( inplace ) { curLoop[i] = false; } } } return false; }, ID: function( match ) { return match[1].replace( rBackslash, "" ); }, TAG: function( match, curLoop ) { return match[1].replace( rBackslash, "" ).toLowerCase(); }, CHILD: function( match ) { if ( match[1] === "nth" ) { if ( !match[2] ) { Sizzle.error( match[0] ); } match[2] = match[2].replace(/^\+|\s*/g, ''); // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); // calculate the numbers (first)n+(last) including if they are negative match[2] = (test[1] + (test[2] || 1)) - 0; match[3] = test[3] - 0; } else if ( match[2] ) { Sizzle.error( match[0] ); } // TODO: Move to normal caching system match[0] = done++; return match; }, ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } // Handle if an un-quoted value was used match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); if ( match[2] === "~=" ) { match[4] = " " + match[4] + " "; } return match; }, PSEUDO: function( match, curLoop, inplace, result, not ) { if ( match[1] === "not" ) { // If we're dealing with a complex expression, or a simple one if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { match[3] = Sizzle(match[3], null, null, curLoop); } else { var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); if ( !inplace ) { result.push.apply( result, ret ); } return false; } } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } return match; }, POS: function( match ) { match.unshift( true ); return match; } }, filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; }, disabled: function( elem ) { return elem.disabled === true; }, checked: function( elem ) { return elem.checked === true; }, selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } return elem.selected === true; }, parent: function( elem ) { return !!elem.firstChild; }, empty: function( elem ) { return !elem.firstChild; }, has: function( elem, i, match ) { return !!Sizzle( match[3], elem ).length; }, header: function( elem ) { return (/h\d/i).test( elem.nodeName ); }, text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, radio: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; }, checkbox: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; }, file: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; }, password: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; }, submit: function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && "submit" === elem.type; }, image: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; }, reset: function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && "reset" === elem.type; }, button: function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && "button" === elem.type || name === "button"; }, input: function( elem ) { return (/input|select|textarea|button/i).test( elem.nodeName ); }, focus: function( elem ) { return elem === elem.ownerDocument.activeElement; } }, setFilters: { first: function( elem, i ) { return i === 0; }, last: function( elem, i, match, array ) { return i === array.length - 1; }, even: function( elem, i ) { return i % 2 === 0; }, odd: function( elem, i ) { return i % 2 === 1; }, lt: function( elem, i, match ) { return i < match[3] - 0; }, gt: function( elem, i, match ) { return i > match[3] - 0; }, nth: function( elem, i, match ) { return match[3] - 0 === i; }, eq: function( elem, i, match ) { return match[3] - 0 === i; } }, filter: { PSEUDO: function( elem, match, i, array ) { var name = match[1], filter = Expr.filters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } else if ( name === "contains" ) { return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; } else if ( name === "not" ) { var not = match[3]; for ( var j = 0, l = not.length; j < l; j++ ) { if ( not[j] === elem ) { return false; } } return true; } else { Sizzle.error( name ); } }, CHILD: function( elem, match ) { var first, last, doneName, parent, cache, count, diff, type = match[1], node = elem; switch ( type ) { case "only": case "first": while ( (node = node.previousSibling) ) { if ( node.nodeType === 1 ) { return false; } } if ( type === "first" ) { return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { if ( node.nodeType === 1 ) { return false; } } return true; case "nth": first = match[2]; last = match[3]; if ( first === 1 && last === 0 ) { return true; } doneName = match[0]; parent = elem.parentNode; if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { count = 0; for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } } parent[ expando ] = doneName; } diff = elem.nodeIndex - last; if ( first === 0 ) { return diff === 0; } else { return ( diff % first === 0 && diff / first >= 0 ); } } }, ID: function( elem, match ) { return elem.nodeType === 1 && elem.getAttribute("id") === match; }, TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; }, CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; }, ATTR: function( elem, match ) { var name = match[1], result = Sizzle.attr ? Sizzle.attr( elem, name ) : Expr.attrHandle[ name ] ? Expr.attrHandle[ name ]( elem ) : elem[ name ] != null ? elem[ name ] : elem.getAttribute( name ), value = result + "", type = match[2], check = match[4]; return result == null ? type === "!=" : !type && Sizzle.attr ? result != null : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value !== check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false; }, POS: function( elem, match, i, array ) { var name = match[2], filter = Expr.setFilters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } } } }; var origPOS = Expr.match.POS, fescape = function(all, num){ return "\\" + (num - 0 + 1); }; for ( var type in Expr.match ) { Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); } var makeArray = function( array, results ) { array = Array.prototype.slice.call( array, 0 ); if ( results ) { results.push.apply( results, array ); return results; } return array; }; // Perform a simple check to determine if the browser is capable of // converting a NodeList to an array using builtin methods. // Also verifies that the returned array holds DOM nodes // (which is not the case in the Blackberry browser) try { Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; // Provide a fallback method if it does not work } catch( e ) { makeArray = function( array, results ) { var i = 0, ret = results || []; if ( toString.call(array) === "[object Array]" ) { Array.prototype.push.apply( ret, array ); } else { if ( typeof array.length === "number" ) { for ( var l = array.length; i < l; i++ ) { ret.push( array[i] ); } } else { for ( ; array[i]; i++ ) { ret.push( array[i] ); } } } return ret; }; } var sortOrder, siblingCheck; if ( document.documentElement.compareDocumentPosition ) { sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; return 0; } if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { return a.compareDocumentPosition ? -1 : 1; } return a.compareDocumentPosition(b) & 4 ? -1 : 1; }; } else { sortOrder = function( a, b ) { // The nodes are identical, we can exit early if ( a === b ) { hasDuplicate = true; return 0; // Fallback to using sourceIndex (in IE) if it's available on both nodes } else if ( a.sourceIndex && b.sourceIndex ) { return a.sourceIndex - b.sourceIndex; } var al, bl, ap = [], bp = [], aup = a.parentNode, bup = b.parentNode, cur = aup; // If the nodes are siblings (or identical) we can do a quick check if ( aup === bup ) { return siblingCheck( a, b ); // If no parents were found then the nodes are disconnected } else if ( !aup ) { return -1; } else if ( !bup ) { return 1; } // Otherwise they're somewhere else in the tree so we need // to build up a full list of the parentNodes for comparison while ( cur ) { ap.unshift( cur ); cur = cur.parentNode; } cur = bup; while ( cur ) { bp.unshift( cur ); cur = cur.parentNode; } al = ap.length; bl = bp.length; // Start walking down the tree looking for a discrepancy for ( var i = 0; i < al && i < bl; i++ ) { if ( ap[i] !== bp[i] ) { return siblingCheck( ap[i], bp[i] ); } } // We ended someplace up the tree so do a sibling check return i === al ? siblingCheck( a, bp[i], -1 ) : siblingCheck( ap[i], b, 1 ); }; siblingCheck = function( a, b, ret ) { if ( a === b ) { return ret; } var cur = a.nextSibling; while ( cur ) { if ( cur === b ) { return -1; } cur = cur.nextSibling; } return 1; }; } // Check to see if the browser returns elements by name when // querying by getElementById (and provide a workaround) (function(){ // We're going to inject a fake input element with a specified name var form = document.createElement("div"), id = "script" + (new Date()).getTime(), root = document.documentElement; form.innerHTML = ""; // Inject it into the root element, check its status, and remove it quickly root.insertBefore( form, root.firstChild ); // The workaround has to do additional checks after a getElementById // Which slows things down for other browsers (hence the branching) if ( document.getElementById( id ) ) { Expr.find.ID = function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; } }; Expr.filter.ID = function( elem, match ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return elem.nodeType === 1 && node && node.nodeValue === match; }; } root.removeChild( form ); // release memory in IE root = form = null; })(); (function(){ // Check to see if the browser returns only elements // when doing getElementsByTagName("*") // Create a fake element var div = document.createElement("div"); div.appendChild( document.createComment("") ); // Make sure no comments are found if ( div.getElementsByTagName("*").length > 0 ) { Expr.find.TAG = function( match, context ) { var results = context.getElementsByTagName( match[1] ); // Filter out possible comments if ( match[1] === "*" ) { var tmp = []; for ( var i = 0; results[i]; i++ ) { if ( results[i].nodeType === 1 ) { tmp.push( results[i] ); } } results = tmp; } return results; }; } // Check to see if an attribute returns normalized href attributes div.innerHTML = ""; if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#" ) { Expr.attrHandle.href = function( elem ) { return elem.getAttribute( "href", 2 ); }; } // release memory in IE div = null; })(); if ( document.querySelectorAll ) { (function(){ var oldSizzle = Sizzle, div = document.createElement("div"), id = "__sizzle__"; div.innerHTML = "

    "; // Safari can't handle uppercase or unicode characters when // in quirks mode. if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } Sizzle = function( query, context, extra, seed ) { context = context || document; // Only use querySelectorAll on non-XML documents // (ID selectors don't work in non-HTML documents) if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } } else { return makeArray( [], extra ); } } try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root // and working up from there (Thanks to Andrew Dupont for the technique) // IE 8 doesn't work on object elements } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { var oldContext = context, old = context.getAttribute( "id" ), nid = old || id, hasParent = context.parentNode, relativeHierarchySelector = /^\s*[+~]/.test( query ); if ( !old ) { context.setAttribute( "id", nid ); } else { nid = nid.replace( /'/g, "\\$&" ); } if ( relativeHierarchySelector && hasParent ) { context = context.parentNode; } try { if ( !relativeHierarchySelector || hasParent ) { return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); } } catch(pseudoError) { } finally { if ( !old ) { oldContext.removeAttribute( "id" ); } } } } return oldSizzle(query, context, extra, seed); }; for ( var prop in oldSizzle ) { Sizzle[ prop ] = oldSizzle[ prop ]; } // release memory in IE div = null; })(); } (function(){ var html = document.documentElement, matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; if ( matches ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9 fails this) var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), pseudoWorks = false; try { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); } catch( pseudoError ) { pseudoWorks = true; } Sizzle.matchesSelector = function( node, expr ) { // Make sure that attribute selectors are quoted expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || !disconnectedMatch || // As well, disconnected nodes are said to be in a document // fragment in IE 9, so check for that node.document && node.document.nodeType !== 11 ) { return ret; } } } catch(e) {} } return Sizzle(expr, null, null, [node]).length > 0; }; } })(); (function(){ var div = document.createElement("div"); div.innerHTML = "
    "; // Opera can't find a second classname (in 9.6) // Also, make sure that getElementsByClassName actually exists if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { return; } // Safari caches class attributes, doesn't catch changes (in 3.2) div.lastChild.className = "e"; if ( div.getElementsByClassName("e").length === 1 ) { return; } Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { return context.getElementsByClassName(match[1]); } }; // release memory in IE div = null; })(); function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var match = false; elem = elem[dir]; while ( elem ) { if ( elem[ expando ] === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 && !isXML ){ elem[ expando ] = doneName; elem.sizset = i; } if ( elem.nodeName.toLowerCase() === cur ) { match = elem; break; } elem = elem[dir]; } checkSet[i] = match; } } } function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var match = false; elem = elem[dir]; while ( elem ) { if ( elem[ expando ] === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 ) { if ( !isXML ) { elem[ expando ] = doneName; elem.sizset = i; } if ( typeof cur !== "string" ) { if ( elem === cur ) { match = true; break; } } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { match = elem; break; } } elem = elem[dir]; } checkSet[i] = match; } } } if ( document.documentElement.contains ) { Sizzle.contains = function( a, b ) { return a !== b && (a.contains ? a.contains(b) : true); }; } else if ( document.documentElement.compareDocumentPosition ) { Sizzle.contains = function( a, b ) { return !!(a.compareDocumentPosition(b) & 16); }; } else { Sizzle.contains = function() { return false; }; } Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; var posProcess = function( selector, context, seed ) { var match, tmpSet = [], later = "", root = context.nodeType ? [context] : context; // Position selectors must be done after the filter // And so must :not(positional) so we move all PSEUDOs to the end while ( (match = Expr.match.PSEUDO.exec( selector )) ) { later += match[0]; selector = selector.replace( Expr.match.PSEUDO, "" ); } selector = Expr.relative[selector] ? selector + "*" : selector; for ( var i = 0, l = root.length; i < l; i++ ) { Sizzle( selector, root[i], tmpSet, seed ); } return Sizzle.filter( later, tmpSet ); }; // EXPOSE // Override sizzle attribute retrieval Sizzle.attr = jQuery.attr; Sizzle.selectors.attrMap = {}; jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.filters; jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; })(); var runtil = /Until$/, rparentsprev = /^(?:parents|prevUntil|prevAll)/, // Note: This RegExp should be improved, or likely pulled from Sizzle rmultiselector = /,/, isSimple = /^.[^:#\[\.,]*$/, slice = Array.prototype.slice, POS = jQuery.expr.match.POS, // methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, contents: true, next: true, prev: true }; jQuery.fn.extend({ find: function( selector ) { var self = this, i, l; if ( typeof selector !== "string" ) { return jQuery( selector ).filter(function() { for ( i = 0, l = self.length; i < l; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } }); } var ret = this.pushStack( "", "find", selector ), length, n, r; for ( i = 0, l = this.length; i < l; i++ ) { length = ret.length; jQuery.find( selector, this[i], ret ); if ( i > 0 ) { // Make sure that the results are unique for ( n = length; n < ret.length; n++ ) { for ( r = 0; r < length; r++ ) { if ( ret[r] === ret[n] ) { ret.splice(n--, 1); break; } } } } } return ret; }, has: function( target ) { var targets = jQuery( target ); return this.filter(function() { for ( var i = 0, l = targets.length; i < l; i++ ) { if ( jQuery.contains( this, targets[i] ) ) { return true; } } }); }, not: function( selector ) { return this.pushStack( winnow(this, selector, false), "not", selector); }, filter: function( selector ) { return this.pushStack( winnow(this, selector, true), "filter", selector ); }, is: function( selector ) { return !!selector && ( typeof selector === "string" ? // If this is a positional selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". POS.test( selector ) ? jQuery( selector, this.context ).index( this[0] ) >= 0 : jQuery.filter( selector, this ).length > 0 : this.filter( selector ).length > 0 ); }, closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; // Array (deprecated as of jQuery 1.7) if ( jQuery.isArray( selectors ) ) { var level = 1; while ( cur && cur.ownerDocument && cur !== context ) { for ( i = 0; i < selectors.length; i++ ) { if ( jQuery( cur ).is( selectors[ i ] ) ) { ret.push({ selector: selectors[ i ], elem: cur, level: level }); } } cur = cur.parentNode; level++; } return ret; } // String var pos = POS.test( selectors ) || typeof selectors !== "string" ? jQuery( selectors, context || this.context ) : 0; for ( i = 0, l = this.length; i < l; i++ ) { cur = this[i]; while ( cur ) { if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { ret.push( cur ); break; } else { cur = cur.parentNode; if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { break; } } } } ret = ret.length > 1 ? jQuery.unique( ret ) : ret; return this.pushStack( ret, "closest", selectors ); }, // Determine the position of an element within // the matched set of elements index: function( elem ) { // No argument, return index in parent if ( !elem ) { return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; } // index in selector if ( typeof elem === "string" ) { return jQuery.inArray( this[0], jQuery( elem ) ); } // Locate the position of the desired element return jQuery.inArray( // If it receives a jQuery object, the first element is used elem.jquery ? elem[0] : elem, this ); }, add: function( selector, context ) { var set = typeof selector === "string" ? jQuery( selector, context ) : jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), all = jQuery.merge( this.get(), set ); return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? all : jQuery.unique( all ) ); }, andSelf: function() { return this.add( this.prevObject ); } }); // A painfully simple check to see if an element is disconnected // from a document (should be improved, where feasible). function isDisconnected( node ) { return !node || !node.parentNode || node.parentNode.nodeType === 11; } jQuery.each({ parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { return jQuery.dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { return jQuery.dir( elem, "parentNode", until ); }, next: function( elem ) { return jQuery.nth( elem, 2, "nextSibling" ); }, prev: function( elem ) { return jQuery.nth( elem, 2, "previousSibling" ); }, nextAll: function( elem ) { return jQuery.dir( elem, "nextSibling" ); }, prevAll: function( elem ) { return jQuery.dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { return jQuery.dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { return jQuery.dir( elem, "previousSibling", until ); }, siblings: function( elem ) { return jQuery.sibling( elem.parentNode.firstChild, elem ); }, children: function( elem ) { return jQuery.sibling( elem.firstChild ); }, contents: function( elem ) { return jQuery.nodeName( elem, "iframe" ) ? elem.contentDocument || elem.contentWindow.document : jQuery.makeArray( elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var ret = jQuery.map( this, fn, until ); if ( !runtil.test( name ) ) { selector = until; } if ( selector && typeof selector === "string" ) { ret = jQuery.filter( selector, ret ); } ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { ret = ret.reverse(); } return this.pushStack( ret, name, slice.call( arguments ).join(",") ); }; }); jQuery.extend({ filter: function( expr, elems, not ) { if ( not ) { expr = ":not(" + expr + ")"; } return elems.length === 1 ? jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : jQuery.find.matches(expr, elems); }, dir: function( elem, dir, until ) { var matched = [], cur = elem[ dir ]; while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { if ( cur.nodeType === 1 ) { matched.push( cur ); } cur = cur[dir]; } return matched; }, nth: function( cur, result, dir, elem ) { result = result || 1; var num = 0; for ( ; cur; cur = cur[dir] ) { if ( cur.nodeType === 1 && ++num === result ) { break; } } return cur; }, sibling: function( n, elem ) { var r = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { r.push( n ); } } return r; } }); // Implement the identical functionality for filter and not function winnow( elements, qualifier, keep ) { // Can't pass null or undefined to indexOf in Firefox 4 // Set to 0 to skip string check qualifier = qualifier || 0; if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep(elements, function( elem, i ) { var retVal = !!qualifier.call( elem, i, elem ); return retVal === keep; }); } else if ( qualifier.nodeType ) { return jQuery.grep(elements, function( elem, i ) { return ( elem === qualifier ) === keep; }); } else if ( typeof qualifier === "string" ) { var filtered = jQuery.grep(elements, function( elem ) { return elem.nodeType === 1; }); if ( isSimple.test( qualifier ) ) { return jQuery.filter(qualifier, filtered, !keep); } else { qualifier = jQuery.filter( qualifier, filtered ); } } return jQuery.grep(elements, function( elem, i ) { return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; }); } function createSafeFragment( document ) { var list = nodeNames.split( "|" ), safeFrag = document.createDocumentFragment(); if ( safeFrag.createElement ) { while ( list.length ) { safeFrag.createElement( list.pop() ); } } return safeFrag; } var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, rleadingWhitespace = /^\s+/, rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, rtagName = /<([\w:]+)/, rtbody = /", "" ], legend: [ 1, "
    ", "
    " ], thead: [ 1, "", "
    " ], tr: [ 2, "", "
    " ], td: [ 3, "", "
    " ], col: [ 2, "", "
    " ], area: [ 1, "", "" ], _default: [ 0, "", "" ] }, safeFragment = createSafeFragment( document ); wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; // IE can't serialize and {% endblock %} {% extends 'layout.html.twig' %} {% import 'base/macros.html.twig' as macros %} {% block heroUnit %}

    {{ project.name|raw }}

    Documentation

    {% endblock %} {% block content %}
    {% if project.indexes.namespaces|length > 0 or not project.indexes.packages %}
    {% endif %} {% if project.indexes.packages|length > 0 %}
    {% endif %}
    {% endblock %} {% extends 'layout.html.twig' %} {% import 'base/macros.html.twig' as macros %} {% use 'base/class.sidebar.html.twig' %} {% block title %} {{ parent() }} » {{ node.FullyQualifiedStructuralElementName }} {% endblock %} {% block content %}
    {{ block('sidebar') }}

    {{ node.name }}

    {% if node.parent %} Extends {{ node.parent|route|join(', ')|raw }} {% endif %} {% if node.interfaces|length %} Implements {{ node.interfaces|route|join(', ')|raw }} {% endif %}

    {{ node.summary }}

    {{ node.description|markdown|raw }}
    {% for tagList in node.tags %} {% for tag in tagList if tag.name not in ['method', 'property']%} {% endfor %} {% endfor %}
    {{ tag.name }} {% if tag.type %} {{ tag.type|route|join('|')|raw }} {% endif %} {% if (tag.name == "since" or "deprecated") %} {{ tag.version }} {% endif %} {{ tag.description|markdown|raw }}

    Methods

    {% set specialMethods = node.magicMethods ? node.inheritedMethods.merge(node.magicMethods) : node.inheritedMethods %} {% for method in node.methods.merge(specialMethods)|sort_asc %}

    {{ method.summary ?: method.name }}

    {{ method.name }}({% for argument in method.arguments %}{{ argument.types ? argument.types|join('|')~' ' }}{{ argument.byReference ? '&' }}{{ argument.name }}{{ argument.default ? ' = '~argument.default }}{% if not loop.last %}, {% endif %}{% endfor %}) {{ method.response.types ? ': '~method.response.types|join('|') }}
    {% if method.parent.name != node.name %}inherited{% endif %} {% if method.static %}static{% endif %} {% if method.final %}final{% endif %} {% if method.abstract %}abstract{% endif %} {% if method.tags.api is defined %}api{% endif %}
    {% include 'method.html.twig' with {'method': method} %}
    {% endfor %} {% if node.constants.merge(node.inheritedConstants)|length > 0 %}

    Constants

    {% for constant in node.constants.merge(node.inheritedConstants) %}

    {{ constant.summary ?: constant.name }}

    {{ constant.name }}
    {% if constant.parent.name != node.name %}inherited{% endif %}
    {{ constant.description|markdown|raw }}
    {% for tagList in constant.tags %} {% endfor %}
    {{ tagList.0.name }} {% for tag in tagList %} {{ tag.description|markdown|raw }} {% endfor %}
    {% endfor %} {% endif %} {% set specialProperties = node.magicProperties ? node.inheritedProperties.merge(node.magicProperties) : node.inheritedProperties %} {% if node.properties.merge(specialProperties)|length > 0 %}

    Properties

    {% for property in node.properties.merge(specialProperties) %}

    {{ property.summary ?: property.var.0.description ?: property.name }}

    {{ property.name }} : {{ property.types|join('|') }}
    {% if property.parent.name != node.name %}inherited{% endif %} {% if property.static %}static{% endif %}
    {{ property.description|markdown|raw }}
    {% for tagList in property.tags %} {% endfor %}
    {{ tagList.0.name }} {% for tag in tagList %} {{ tag.description|markdown|raw }} {% endfor %}
    {% if property.types and property.types|join() != 'void' %}

    Type(s)

    {{ property.types|route|join('|')|raw }} {% endif %}
    {% endfor %} {% endif %}
    {% endblock %} {% use 'base/sidebar.html.twig' %} {% block sidebar_buttons %}
    {% endblock %} {% block sidebar_entry %}
  • {{ item.summary }}
    {{ item.name }}
  • {% endblock %} {% block sidebar_content %} {% endblock %} {% macro renderMarkerCounter(files) %} {% set count = 0 %} {% for file in files %} {% set count = count + file.markers|length %} {% endfor %} {{ count }} {% endmacro %} {% macro renderDeprecatedCounter(elements) %} {% set count = 0 %} {% for element in elements if element.deprecated %} {% set count = count + 1 %} {% endfor %} {{ count }} {% endmacro %} {% macro renderErrorCounter(files) %} {% set count = 0 %} {% for file in files %} {% set count = count + file.allerrors|length %} {% endfor %} {{ count }} {% endmacro %} {% macro buildBreadcrumb(element) %} {% import _self as self %} {% if element.parentNamespace and element.parentNamespace.name != '\\' %} {{ self.buildBreadcrumb(element.parentNamespace) }} {% endif %}
  • \{{ element.name }}
  • {% endmacro %} {% block sidebar_buttons %}{% endblock %} {% block sidebar_content %}{% endblock %} {% block sidebar %} {{ block('sidebar_buttons') }} {{ block('sidebar_content') }} {% endblock %} {% extends 'layout.html.twig' %} {% block title %} {{ project.title }} » Deprecated elements {% endblock %} {% block content %}
    {% for element in project.indexes.elements if element.deprecated %}

    {{ element.file.path }} {{ element.tags.deprecated.count }}

    {% for tag in element.tags.deprecated %} {% endfor %}
    Type Line Description
    {{ element.name }} {{ element.line }} {{ element.description }}
    {% else %}
    No deprecated elements have been found in this project.
    {% endfor %}
    {% endblock %} {% extends 'layout.html.twig' %} {% block title %} {{ project.title }} » Compilation errors {% endblock %} {% block content %}
    {% if errorCount <= 0 %}
    No errors have been found in this project.
    {% endif %} {% for file in project.files %}
    {% if file.allerrors|length > 0 %}

    {{ file.path }} {{ file.allerrors|length }}

    {% for error in file.allerrors %} {% endfor %}
    Type Line Description
    {{ error.severity }} {{ error.line }} {{ error.code|trans(error.context) }}
    {% endif %}
    {% endfor %}
    {% endblock %} {% extends 'layout.html.twig' %} {% block title %} {{ project.title }} » Markers {% endblock %} {% block content %}
    {% if markerCount <= 0 %}
    No markers have been found in this project.
    {% endif %}
    {% for file in project.files %} {% if file.markers|length > 0 %}

    {{ file.path }} {{ file.markers|length }}

    {% for marker in file.markers %} {% endfor %}
    Type Line Description
    {{ marker.type }} {{ marker.line }} {{ marker.message }}
    {% endif %} {% endfor %}
    {% endblock %} {% extends 'layout.html.twig' %} {% macro elementSummary(element, type) %}

    {{ element.name }}

    {{ element.summary }}

    {{ element.description }}
    « More »
    {% endmacro %} {% macro buildBreadcrumb(element) %} {% import _self as self %} {% if element.parent and element.parent.name != '\\' %} {{ self.buildBreadcrumb(element.parent) }} {% endif %}
  • \{{ element.name }}
  • {% endmacro %} {% macro renderPackageDetails(node) %} {% import _self as self %} {% if node.classes|length > 0 or node.interfaces|length > 0 or node.traits|length > 0 or node.functions|length > 0 or node.constants|length > 0 %} {% if node.functions|length > 0 %}

    Functions

    {% for function in node.functions %} {{ self.elementSummary(function, 'function') }} {% endfor %}
    {% endif %} {% if node.constants|length > 0 %}

    Constants

    {% for constant in node.constants %} {{ self.elementSummary(constant, 'constant') }} {% endfor %}
    {% endif %} {% if node.classes|length > 0 or node.interfaces|length > 0 or node.traits|length > 0 %}

    Classes, interfaces and traits

    {% for trait in node.traits|sort_asc %} {{ self.elementSummary(trait, 'trait') }} {% endfor %} {% for interface in node.interfaces|sort_asc %} {{ self.elementSummary(interface, 'interface') }} {% endfor %} {% for class in node.classes|sort_asc %} {{ self.elementSummary(class, 'class') }} {% endfor %}
    {% endif %} {% endif %} {% for package in node.children %} {{ self.renderPackageDetails(package) }} {% endfor %} {% endmacro %} {% macro renderPackageSidebar(node) %} {% import _self as self %} {% for package in node.children|sort_asc %}
  • {{ package.name }}
  • {% endfor %} {% endmacro %} {% block title %} {{ project.title }} » {{ node.FullyQualifiedStructuralElementName }} {% endblock %} {% block content %} {% import _self as self %}
    {{ self.renderPackageDetails(node) }}
    {% endblock %} {% import 'base/macros.html.twig' as macros %}
    {{ method.description|markdown|raw }}
    {% for tagList in method.tags if tagList.0.name not in ['param', 'return', 'api', 'throws', 'throw'] %} {% endfor %} {% if method.tags.throws|length > 0 or method.tags.throw|length > 0 %} {% endif %}
    {{ tagList.0.name }} {% for tag in tagList %} {% if (tag.name == "since" or "deprecated") %} {{ tag.version }} {% endif %} {% if (tag.name == "see") %} {{ tag.reference|route|raw }} {% endif %} {{ tag.description|markdown|raw }} {% endfor %}
    Throws
    {% for exception in method.tags.throws %}
    {{ exception.types|route|join('|')|raw }}
    {{ exception.description|markdown|raw }}
    {% endfor %} {% for exception in method.tags.throw %}
    {{ exception.types|route|join('|')|raw }}
    {{ exception.description|markdown|raw }}
    {% endfor %}
    {% if method.arguments|length > 0 %}

    Arguments

    {% for argument in method.arguments %}

    {{ argument.name }}

    {{ argument.types|route|join('|')|raw }}

    {{ argument.description|markdown|raw }}

    {% endfor %} {% endif %} {% if method.response.types and method.response.types|join() != 'void' %}

    Response

    {{ method.response.types|route|join('|')|raw }}

    {{ method.response.description|markdown|raw }}

    {% endif %}
    {% block title %}{{ project.name }}{% endblock %} {% block stylesheets %} {% endblock %} {% block javascripts %} {% endblock %} {% block icons %} {% endblock %} {% block header %} {% endblock header %}
    {% block heroUnit %}{% endblock %} {% block content %}{% endblock %}
    {% block footer %} {% endblock %} {% extends 'layout.html.twig' %} {% macro elementSummary(element, type) %}

    {{ element.name }}{% if path(element) %}{% endif %}

    {{ element.summary }}

    {% if type == 'function' %} {% include 'method.html.twig' with {'method': element} %} {% else %} {{ element.description|markdown|raw }} {% endif %}
    {% if path(element) %}« More »{% endif %}
    {% endmacro %} {% macro buildBreadcrumb(element) %} {% import _self as self %} {% if element.parent and element.parent.name != '\\' %} {{ self.buildBreadcrumb(element.parent) }} {% endif %}
  • \{{ element.name }}
  • {% endmacro %} {% macro renderNamespaceDetails(node) %} {% import _self as self %} {% if node.classes|length > 0 or node.interfaces|length > 0 or node.traits|length > 0 or node.functions|length > 0 or node.constants|length > 0 %} {% if node.functions|length > 0 %}

    Functions

    {% for function in node.functions|sort_asc %} {{ self.elementSummary(function, 'function') }} {% endfor %}
    {% endif %} {% if node.constants|length > 0 %}

    Constants

    {% for constant in node.constants %} {{ self.elementSummary(constant, 'constant') }} {% endfor %}
    {% endif %} {% if node.classes|length > 0 or node.interfaces|length > 0 or node.traits|length > 0 %}

    Classes, interfaces and traits

    {% for trait in node.traits|sort_asc %} {{ self.elementSummary(trait, 'trait') }} {% endfor %} {% for interface in node.interfaces|sort_asc %} {{ self.elementSummary(interface, 'interface') }} {% endfor %} {% for class in node.classes|sort_asc %} {{ self.elementSummary(class, 'class') }} {% endfor %}
    {% endif %} {% endif %} {% for namespace in node.children %} {{ self.renderNamespaceDetails(namespace) }} {% endfor %} {% endmacro %} {% macro renderNamespaceSidebar(node) %} {% import _self as self %} {% for namespace in node.children|sort_asc %}
  • {{ namespace.name }}
  • {% endfor %} {% endmacro %} {% block title %} {{ project.title }} » {{ node.FullyQualifiedStructuralElementName }} {% endblock %} {% block content %} {% import _self as self %}
    {{ self.renderNamespaceDetails(node) }}
    {% endblock %}

    phpDocumentor

    Documentation

    »
  •  
  •  
  • <xsl:value-of select="$title" disable-output-escaping="yes" /> <xsl:if test="$title = ''">phpDocumentor</xsl:if> <xsl:apply-templates select="." mode="title"/> <!DOCTYPE html>
  •  Errors 
  •  Markers 
  •  Deprecated elements 
  •  
  • »
    No deprecated elements have been found in this project.

    Type Line Description
    No errors have been found in this project.

    Type Line Description
    No markers have been found in this project.
    The following markers were found:

    Type Line Description
    article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;} audio,canvas,video{display:inline-block;*display:inline;*zoom:1;} audio:not([controls]){display:none;} html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;} a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} a:hover,a:active{outline:0;} sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;} sup{top:-0.5em;} sub{bottom:-0.25em;} img{max-width:100%;height:auto;border:0;-ms-interpolation-mode:bicubic;} button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;} button,input{*overflow:visible;line-height:normal;} button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;} button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;} input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;} input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;} textarea{overflow:auto;vertical-align:top;} body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333333;background-color:#ffffff;} a{color:#0088cc;text-decoration:none;} a:hover{color:#005580;text-decoration:underline;} .row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:20px;} .span1{width:60px;} .span2{width:140px;} .span3{width:220px;} .span4{width:300px;} .span5{width:380px;} .span6{width:460px;} .span7{width:540px;} .span8{width:620px;} .span9{width:700px;} .span10{width:780px;} .span11{width:860px;} .span12,.container{width:940px;} .offset1{margin-left:100px;} .offset2{margin-left:180px;} .offset3{margin-left:260px;} .offset4{margin-left:340px;} .offset5{margin-left:420px;} .offset6{margin-left:500px;} .offset7{margin-left:580px;} .offset8{margin-left:660px;} .offset9{margin-left:740px;} .offset10{margin-left:820px;} .offset11{margin-left:900px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid>[class*="span"]{float:left;margin-left:2.127659574%;} .row-fluid>[class*="span"]:first-child{margin-left:0;} .row-fluid .span1{width:6.382978723%;} .row-fluid .span2{width:14.89361702%;} .row-fluid .span3{width:23.404255317%;} .row-fluid .span4{width:31.914893614%;} .row-fluid .span5{width:40.425531911%;} .row-fluid .span6{width:48.93617020799999%;} .row-fluid .span7{width:57.446808505%;} .row-fluid .span8{width:65.95744680199999%;} .row-fluid .span9{width:74.468085099%;} .row-fluid .span10{width:82.97872339599999%;} .row-fluid .span11{width:91.489361693%;} .row-fluid .span12{width:99.99999998999999%;} .container{width:940px;margin-left:auto;margin-right:auto;*zoom:1;}.container:before,.container:after{display:table;content:"";} .container:after{clear:both;} .container-fluid{padding-left:20px;padding-right:20px;*zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";} .container-fluid:after{clear:both;} p{margin:0 0 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;}p small{font-size:11px;color:#999999;} .lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px;} h1,h2,h3,h4,h5,h6{margin:0;font-weight:bold;color:#333333;text-rendering:optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#999999;} h1{font-size:30px;line-height:36px;}h1 small{font-size:18px;} h2{font-size:24px;line-height:36px;}h2 small{font-size:18px;} h3{line-height:27px;font-size:18px;}h3 small{font-size:14px;} h4,h5,h6{line-height:18px;} h4{font-size:14px;}h4 small{font-size:12px;} h5{font-size:12px;} h6{font-size:11px;color:#999999;text-transform:uppercase;} .page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eeeeee;} .page-header h1{line-height:1;} ul,ol{padding:0;margin:0 0 9px 25px;} ul ul,ul ol,ol ol,ol ul{margin-bottom:0;} ul{list-style:disc;} ol{list-style:decimal;} li{line-height:18px;} ul.unstyled{margin-left:0;list-style:none;} dl{margin-bottom:18px;} dt,dd{line-height:18px;} dt{font-weight:bold;} dd{margin-left:9px;} hr{margin:18px 0;border:0;border-top:1px solid #e5e5e5;border-bottom:1px solid #ffffff;} strong{font-weight:bold;} em{font-style:italic;} .muted{color:#999999;} abbr{font-size:90%;text-transform:uppercase;border-bottom:1px dotted #ddd;cursor:help;} blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eeeeee;}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px;} blockquote small{display:block;line-height:18px;color:#999999;}blockquote small:before{content:'\2014 \00A0';} blockquote.pull-right{float:right;padding-left:0;padding-right:15px;border-left:0;border-right:5px solid #eeeeee;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;} q:before,q:after,blockquote:before,blockquote:after{content:"";} address{display:block;margin-bottom:18px;line-height:18px;font-style:normal;} small{font-size:100%;} cite{font-style:normal;} code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,"Courier New",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} code{padding:3px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;} pre{display:block;padding:8.5px;margin:0 0 9px;font-size:12px;line-height:18px;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;white-space:pre;white-space:pre-wrap;word-break:break-all;}pre.prettyprint{margin-bottom:18px;} pre code{padding:0;background-color:transparent;} form{margin:0 0 18px;} fieldset{padding:0;margin:0;border:0;} legend{display:block;width:100%;padding:0;margin-bottom:27px;font-size:19.5px;line-height:36px;color:#333333;border:0;border-bottom:1px solid #eee;} label,input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:18px;} label{display:block;margin-bottom:5px;color:#333333;} input,textarea,select,.uneditable-input{display:inline-block;width:210px;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555555;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .uneditable-textarea{width:auto;height:auto;} label input,label textarea,label select{display:block;} input[type="image"],input[type="checkbox"],input[type="radio"]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;border:0;cursor:pointer;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} input[type="file"]{padding:initial;line-height:initial;border:initial;background-color:#ffffff;background-color:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} input[type="button"],input[type="reset"],input[type="submit"]{width:auto;height:auto;} select,input[type="file"]{height:28px;*margin-top:4px;line-height:28px;} select{width:220px;background-color:#ffffff;} select[multiple],select[size]{height:auto;} input[type="image"]{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} textarea{height:auto;} input[type="hidden"]{display:none;} .radio,.checkbox{padding-left:18px;} .radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px;} .controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px;} .radio.inline,.checkbox.inline{display:inline-block;margin-bottom:0;vertical-align:middle;} .radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px;} .controls>.radio.inline:first-child,.controls>.checkbox.inline:first-child{padding-top:0;} input,textarea{-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border linear 0.2s,box-shadow linear 0.2s;-moz-transition:border linear 0.2s,box-shadow linear 0.2s;-ms-transition:border linear 0.2s,box-shadow linear 0.2s;-o-transition:border linear 0.2s,box-shadow linear 0.2s;transition:border linear 0.2s,box-shadow linear 0.2s;} input:focus,textarea:focus{border-color:rgba(82, 168, 236, 0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);outline:0;outline:thin dotted \9;} input[type="file"]:focus,input[type="checkbox"]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} .input-mini{width:60px;} .input-small{width:90px;} .input-medium{width:150px;} .input-large{width:210px;} .input-xlarge{width:270px;} .input-xxlarge{width:530px;} input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{float:none;margin-left:0;} input.span1,textarea.span1,.uneditable-input.span1{width:50px;} input.span2,textarea.span2,.uneditable-input.span2{width:130px;} input.span3,textarea.span3,.uneditable-input.span3{width:210px;} input.span4,textarea.span4,.uneditable-input.span4{width:290px;} input.span5,textarea.span5,.uneditable-input.span5{width:370px;} input.span6,textarea.span6,.uneditable-input.span6{width:450px;} input.span7,textarea.span7,.uneditable-input.span7{width:530px;} input.span8,textarea.span8,.uneditable-input.span8{width:610px;} input.span9,textarea.span9,.uneditable-input.span9{width:690px;} input.span10,textarea.span10,.uneditable-input.span10{width:770px;} input.span11,textarea.span11,.uneditable-input.span11{width:850px;} input.span12,textarea.span12,.uneditable-input.span12{width:930px;} input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{background-color:#f5f5f5;border-color:#ddd;cursor:not-allowed;} .control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853;} .control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;border-color:#c09853;}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:0 0 6px #dbc59e;-moz-box-shadow:0 0 6px #dbc59e;box-shadow:0 0 6px #dbc59e;} .control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853;} .control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48;} .control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;border-color:#b94a48;}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:0 0 6px #d59392;-moz-box-shadow:0 0 6px #d59392;box-shadow:0 0 6px #d59392;} .control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48;} .control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847;} .control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;border-color:#468847;}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:0 0 6px #7aba7b;-moz-box-shadow:0 0 6px #7aba7b;box-shadow:0 0 6px #7aba7b;} .control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847;} input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b;}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;} .form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #ddd;} .uneditable-input{display:block;background-color:#ffffff;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;} :-moz-placeholder{color:#999999;} ::-webkit-input-placeholder{color:#999999;} .help-block{margin-top:5px;margin-bottom:0;color:#999999;} .help-inline{display:inline-block;*display:inline;*zoom:1;margin-bottom:9px;vertical-align:middle;padding-left:5px;} .input-prepend,.input-append{margin-bottom:5px;*zoom:1;}.input-prepend:before,.input-append:before,.input-prepend:after,.input-append:after{display:table;content:"";} .input-prepend:after,.input-append:after{clear:both;} .input-prepend input,.input-append input,.input-prepend .uneditable-input,.input-append .uneditable-input{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}.input-prepend input:focus,.input-append input:focus,.input-prepend .uneditable-input:focus,.input-append .uneditable-input:focus{position:relative;z-index:2;} .input-prepend .uneditable-input,.input-append .uneditable-input{border-left-color:#ccc;} .input-prepend .add-on,.input-append .add-on{float:left;display:block;width:auto;min-width:16px;height:18px;margin-right:-1px;padding:4px 5px;font-weight:normal;line-height:18px;color:#999999;text-align:center;text-shadow:0 1px 0 #ffffff;background-color:#f5f5f5;border:1px solid #ccc;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} .input-prepend .active,.input-append .active{background-color:#a9dba9;border-color:#46a546;} .input-prepend .add-on{*margin-top:1px;} .input-append input,.input-append .uneditable-input{float:left;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} .input-append .uneditable-input{border-right-color:#ccc;} .input-append .add-on{margin-right:0;margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;} .input-append input:first-child{*margin-left:-160px;}.input-append input:first-child+.add-on{*margin-left:-21px;} .search-query{padding-left:14px;padding-right:14px;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px;} .form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input{display:inline-block;margin-bottom:0;} .form-search label,.form-inline label,.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{display:inline-block;} .form-search .input-append .add-on,.form-inline .input-prepend .add-on,.form-search .input-append .add-on,.form-inline .input-prepend .add-on{vertical-align:middle;} .control-group{margin-bottom:9px;} .form-horizontal legend+.control-group{margin-top:18px;-webkit-margin-top-collapse:separate;} .form-horizontal .control-group{margin-bottom:18px;*zoom:1;}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";} .form-horizontal .control-group:after{clear:both;} .form-horizontal .control-group>label{float:left;width:140px;padding-top:5px;text-align:right;} .form-horizontal .controls{margin-left:160px;} .form-horizontal .form-actions{padding-left:160px;} table{max-width:100%;border-collapse:collapse;border-spacing:0;} .table{width:100%;margin-bottom:18px;}.table th,.table td{padding:8px;line-height:18px;text-align:left;border-top:1px solid #ddd;} .table th{font-weight:bold;vertical-align:bottom;} .table td{vertical-align:top;} .table thead:first-child tr th,.table thead:first-child tr td{border-top:0;} .table tbody+tbody{border-top:2px solid #ddd;} .table-condensed th,.table-condensed td{padding:4px 5px;} .table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapsed;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th+th,.table-bordered td+td,.table-bordered th+td,.table-bordered td+th{border-left:1px solid #ddd;} .table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0;} .table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;border-radius:4px 0 0 0;} .table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0;} .table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;} .table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0;} .table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9;} table .span1{float:none;width:44px;margin-left:0;} table .span2{float:none;width:124px;margin-left:0;} table .span3{float:none;width:204px;margin-left:0;} table .span4{float:none;width:284px;margin-left:0;} table .span5{float:none;width:364px;margin-left:0;} table .span6{float:none;width:444px;margin-left:0;} table .span7{float:none;width:524px;margin-left:0;} table .span8{float:none;width:604px;margin-left:0;} table .span9{float:none;width:684px;margin-left:0;} table .span10{float:none;width:764px;margin-left:0;} table .span11{float:none;width:844px;margin-left:0;} table .span12{float:none;width:924px;margin-left:0;} [class^="icon-"]{display:inline-block;width:14px;height:14px;vertical-align:text-top;background-image:url(../img/glyphicons-halflings.png);background-position:14px 14px;background-repeat:no-repeat;*margin-right:.3em;}[class^="icon-"]:last-child{*margin-left:0;} .icon-white{background-image:url(../img/glyphicons-halflings-white.png);} .icon-glass{background-position:0 0;} .icon-music{background-position:-24px 0;} .icon-search{background-position:-48px 0;} .icon-envelope{background-position:-72px 0;} .icon-heart{background-position:-96px 0;} .icon-star{background-position:-120px 0;} .icon-star-empty{background-position:-144px 0;} .icon-user{background-position:-168px 0;} .icon-film{background-position:-192px 0;} .icon-th-large{background-position:-216px 0;} .icon-th{background-position:-240px 0;} .icon-th-list{background-position:-264px 0;} .icon-ok{background-position:-288px 0;} .icon-remove{background-position:-312px 0;} .icon-zoom-in{background-position:-336px 0;} .icon-zoom-out{background-position:-360px 0;} .icon-off{background-position:-384px 0;} .icon-signal{background-position:-408px 0;} .icon-cog{background-position:-432px 0;} .icon-trash{background-position:-456px 0;} .icon-home{background-position:0 -24px;} .icon-file{background-position:-24px -24px;} .icon-time{background-position:-48px -24px;} .icon-road{background-position:-72px -24px;} .icon-download-alt{background-position:-96px -24px;} .icon-download{background-position:-120px -24px;} .icon-upload{background-position:-144px -24px;} .icon-inbox{background-position:-168px -24px;} .icon-play-circle{background-position:-192px -24px;} .icon-repeat{background-position:-216px -24px;} .icon-refresh{background-position:-240px -24px;} .icon-list-alt{background-position:-264px -24px;} .icon-lock{background-position:-287px -24px;} .icon-flag{background-position:-312px -24px;} .icon-headphones{background-position:-336px -24px;} .icon-volume-off{background-position:-360px -24px;} .icon-volume-down{background-position:-384px -24px;} .icon-volume-up{background-position:-408px -24px;} .icon-qrcode{background-position:-432px -24px;} .icon-barcode{background-position:-456px -24px;} .icon-tag{background-position:0 -48px;} .icon-tags{background-position:-25px -48px;} .icon-book{background-position:-48px -48px;} .icon-bookmark{background-position:-72px -48px;} .icon-print{background-position:-96px -48px;} .icon-camera{background-position:-120px -48px;} .icon-font{background-position:-144px -48px;} .icon-bold{background-position:-167px -48px;} .icon-italic{background-position:-192px -48px;} .icon-text-height{background-position:-216px -48px;} .icon-text-width{background-position:-240px -48px;} .icon-align-left{background-position:-264px -48px;} .icon-align-center{background-position:-288px -48px;} .icon-align-right{background-position:-312px -48px;} .icon-align-justify{background-position:-336px -48px;} .icon-list{background-position:-360px -48px;} .icon-indent-left{background-position:-384px -48px;} .icon-indent-right{background-position:-408px -48px;} .icon-facetime-video{background-position:-432px -48px;} .icon-picture{background-position:-456px -48px;} .icon-pencil{background-position:0 -72px;} .icon-map-marker{background-position:-24px -72px;} .icon-adjust{background-position:-48px -72px;} .icon-tint{background-position:-72px -72px;} .icon-edit{background-position:-96px -72px;} .icon-share{background-position:-120px -72px;} .icon-check{background-position:-144px -72px;} .icon-move{background-position:-168px -72px;} .icon-step-backward{background-position:-192px -72px;} .icon-fast-backward{background-position:-216px -72px;} .icon-backward{background-position:-240px -72px;} .icon-play{background-position:-264px -72px;} .icon-pause{background-position:-288px -72px;} .icon-stop{background-position:-312px -72px;} .icon-forward{background-position:-336px -72px;} .icon-fast-forward{background-position:-360px -72px;} .icon-step-forward{background-position:-384px -72px;} .icon-eject{background-position:-408px -72px;} .icon-chevron-left{background-position:-432px -72px;} .icon-chevron-right{background-position:-456px -72px;} .icon-plus-sign{background-position:0 -96px;} .icon-minus-sign{background-position:-24px -96px;} .icon-remove-sign{background-position:-48px -96px;} .icon-ok-sign{background-position:-72px -96px;} .icon-question-sign{background-position:-96px -96px;} .icon-info-sign{background-position:-120px -96px;} .icon-screenshot{background-position:-144px -96px;} .icon-remove-circle{background-position:-168px -96px;} .icon-ok-circle{background-position:-192px -96px;} .icon-ban-circle{background-position:-216px -96px;} .icon-arrow-left{background-position:-240px -96px;} .icon-arrow-right{background-position:-264px -96px;} .icon-arrow-up{background-position:-289px -96px;} .icon-arrow-down{background-position:-312px -96px;} .icon-share-alt{background-position:-336px -96px;} .icon-resize-full{background-position:-360px -96px;} .icon-resize-small{background-position:-384px -96px;} .icon-plus{background-position:-408px -96px;} .icon-minus{background-position:-433px -96px;} .icon-asterisk{background-position:-456px -96px;} .icon-exclamation-sign{background-position:0 -120px;} .icon-gift{background-position:-24px -120px;} .icon-leaf{background-position:-48px -120px;} .icon-fire{background-position:-72px -120px;} .icon-eye-open{background-position:-96px -120px;} .icon-eye-close{background-position:-120px -120px;} .icon-warning-sign{background-position:-144px -120px;} .icon-plane{background-position:-168px -120px;} .icon-calendar{background-position:-192px -120px;} .icon-random{background-position:-216px -120px;} .icon-comment{background-position:-240px -120px;} .icon-magnet{background-position:-264px -120px;} .icon-chevron-up{background-position:-288px -120px;} .icon-chevron-down{background-position:-313px -119px;} .icon-retweet{background-position:-336px -120px;} .icon-shopping-cart{background-position:-360px -120px;} .icon-folder-close{background-position:-384px -120px;} .icon-folder-open{background-position:-408px -120px;} .icon-resize-vertical{background-position:-432px -119px;} .icon-resize-horizontal{background-position:-456px -118px;} .dropdown{position:relative;} .dropdown-toggle{*margin-bottom:-3px;} .dropdown-toggle:active,.open .dropdown-toggle{outline:0;} .caret{display:inline-block;width:0;height:0;text-indent:-99999px;*text-indent:0;vertical-align:top;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000000;opacity:0.3;filter:alpha(opacity=30);content:"\2193";} .dropdown .caret{margin-top:8px;margin-left:2px;} .dropdown:hover .caret,.open.dropdown .caret{opacity:1;filter:alpha(opacity=100);} .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;float:left;display:none;min-width:160px;max-width:220px;_width:160px;padding:4px 0;margin:0;list-style:none;background-color:#ffffff;border-color:#ccc;border-color:rgba(0, 0, 0, 0.2);border-style:solid;border-width:1px;-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;*border-right-width:2px;*border-bottom-width:2px;}.dropdown-menu.bottom-up{top:auto;bottom:100%;margin-bottom:2px;} .dropdown-menu .divider{height:1px;margin:5px 1px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;*width:100%;*margin:-5px 0 5px;} .dropdown-menu a{display:block;padding:3px 15px;clear:both;font-weight:normal;line-height:18px;color:#555555;white-space:nowrap;} .dropdown-menu li>a:hover,.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#ffffff;text-decoration:none;background-color:#0088cc;} .dropdown.open{*z-index:1000;}.dropdown.open .dropdown-toggle{color:#ffffff;background:#ccc;background:rgba(0, 0, 0, 0.3);} .dropdown.open .dropdown-menu{display:block;} .typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #eee;border:1px solid rgba(0, 0, 0, 0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);} .fade{-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-ms-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;opacity:0;}.fade.in{opacity:1;} .collapse{-webkit-transition:height 0.35s ease;-moz-transition:height 0.35s ease;-ms-transition:height 0.35s ease;-o-transition:height 0.35s ease;transition:height 0.35s ease;position:relative;overflow:hidden;height:0;}.collapse.in{height:auto;} .close{float:right;font-size:20px;font-weight:bold;line-height:18px;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20);}.close:hover{color:#000000;text-decoration:none;opacity:0.4;filter:alpha(opacity=40);cursor:pointer;} .btn{display:inline-block;padding:4px 10px 4px;font-size:13px;line-height:18px;color:#333333;text-align:center;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#fafafa;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);background-image:-ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);cursor:pointer;*margin-left:.3em;}.btn:first-child{*margin-left:0;} .btn:hover{color:#333333;text-decoration:none;background-color:#e6e6e6;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-ms-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;} .btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} .btn.active,.btn:active{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);background-color:#e6e6e6;background-color:#d9d9d9 \9;color:rgba(0, 0, 0, 0.5);outline:0;} .btn.disabled,.btn[disabled]{cursor:default;background-image:none;background-color:#e6e6e6;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .btn-large{padding:9px 14px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} .btn-large .icon{margin-top:1px;} .btn-small{padding:5px 9px;font-size:11px;line-height:16px;} .btn-small .icon{margin-top:-1px;} .btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover{text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);color:#ffffff;} .btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active{color:rgba(255, 255, 255, 0.75);} .btn-primary{background-color:#006dcc;background-image:-moz-linear-gradient(top, #0088cc, #0044cc);background-image:-ms-linear-gradient(top, #0088cc, #0044cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));background-image:-webkit-linear-gradient(top, #0088cc, #0044cc);background-image:-o-linear-gradient(top, #0088cc, #0044cc);background-image:linear-gradient(top, #0088cc, #0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#0044cc;} .btn-primary:active,.btn-primary.active{background-color:#003399 \9;} .btn-warning{background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-ms-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(top, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406;} .btn-warning:active,.btn-warning.active{background-color:#c67605 \9;} .btn-danger{background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-ms-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(top, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f;} .btn-danger:active,.btn-danger.active{background-color:#942a25 \9;} .btn-success{background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-ms-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(top, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351;} .btn-success:active,.btn-success.active{background-color:#408140 \9;} .btn-info{background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-ms-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(top, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4;} .btn-info:active,.btn-info.active{background-color:#24748c \9;} button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;} button.btn.large,input[type="submit"].btn.large{*padding-top:7px;*padding-bottom:7px;} button.btn.small,input[type="submit"].btn.small{*padding-top:3px;*padding-bottom:3px;} .btn-group{position:relative;*zoom:1;*margin-left:.3em;}.btn-group:before,.btn-group:after{display:table;content:"";} .btn-group:after{clear:both;} .btn-group:first-child{*margin-left:0;} .btn-group+.btn-group{margin-left:5px;} .btn-toolbar{margin-top:9px;margin-bottom:9px;}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1;} .btn-group .btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} .btn-group .btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;} .btn-group .btn:last-child,.btn-group .dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;} .btn-group .btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;} .btn-group .btn.large:last-child,.btn-group .large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;} .btn-group .btn:hover,.btn-group .btn:focus,.btn-group .btn:active,.btn-group .btn.active{z-index:2;} .btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;} .btn-group .dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);*padding-top:5px;*padding-bottom:5px;} .btn-group.open{*z-index:1000;}.btn-group.open .dropdown-menu{display:block;margin-top:1px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} .btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);} .btn .caret{margin-top:7px;margin-left:0;} .btn:hover .caret,.open.btn-group .caret{opacity:1;filter:alpha(opacity=100);} .btn-primary .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret{border-top-color:#ffffff;opacity:0.75;filter:alpha(opacity=75);} .btn-small .caret{margin-top:4px;} .alert{padding:8px 35px 8px 14px;margin-bottom:18px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .alert,.alert-heading{color:#c09853;} .alert .close{position:relative;top:-2px;right:-21px;line-height:18px;} .alert-success{background-color:#dff0d8;border-color:#d6e9c6;} .alert-success,.alert-success .alert-heading{color:#468847;} .alert-danger,.alert-error{background-color:#f2dede;border-color:#eed3d7;} .alert-danger,.alert-error,.alert-danger .alert-heading,.alert-error .alert-heading{color:#b94a48;} .alert-info{background-color:#d9edf7;border-color:#bce8f1;} .alert-info,.alert-info .alert-heading{color:#3a87ad;} .alert-block{padding-top:14px;padding-bottom:14px;} .alert-block>p,.alert-block>ul{margin-bottom:0;} .alert-block p+p{margin-top:5px;} .nav{margin-left:0;margin-bottom:18px;list-style:none;} .nav>li>a{display:block;} .nav>li>a:hover{text-decoration:none;background-color:#eeeeee;} .nav-list{padding-left:14px;padding-right:14px;margin-bottom:0;} .nav-list>li>a,.nav-list .nav-header{display:block;padding:3px 15px;margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);} .nav-list .nav-header{font-size:11px;font-weight:bold;line-height:18px;color:#999999;text-transform:uppercase;} .nav-list .nav-header *{text-transform:none;} .nav-list>li+.nav-header{margin-top:9px;} .nav-list .active>a,.nav-list .active>a:hover{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.2);background-color:#0088cc;} .nav-list [class^="icon-"]{margin-right:2px;} .nav-tabs,.nav-pills{*zoom:1;}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:"";} .nav-tabs:after,.nav-pills:after{clear:both;} .nav-tabs>li,.nav-pills>li{float:left;} .nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px;} .nav-tabs{border-bottom:1px solid #ddd;} .nav-tabs>li{margin-bottom:-1px;} .nav-tabs>li>a{padding-top:9px;padding-bottom:9px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd;} .nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555555;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;} .nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} .nav-pills .active>a,.nav-pills .active>a:hover{color:#ffffff;background-color:#0088cc;} .nav-stacked>li{float:none;} .nav-stacked>li>a{margin-right:0;} .nav-tabs.nav-stacked{border-bottom:0;} .nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} .nav-tabs.nav-stacked>li:first-child>a{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;} .nav-tabs.nav-stacked>li:last-child>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;} .nav-tabs.nav-stacked>li>a:hover{border-color:#ddd;z-index:2;} .nav-pills.nav-stacked>li>a{margin-bottom:3px;} .nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px;} .nav-tabs .dropdown-menu,.nav-pills .dropdown-menu{margin-top:1px;border-width:1px;} .nav-pills .dropdown-menu{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .nav-tabs .dropdown-toggle .caret,.nav-pills .dropdown-toggle .caret{border-top-color:#0088cc;margin-top:6px;} .nav-tabs .dropdown-toggle:hover .caret,.nav-pills .dropdown-toggle:hover .caret{border-top-color:#005580;} .nav-tabs .active .dropdown-toggle .caret,.nav-pills .active .dropdown-toggle .caret{border-top-color:#333333;} .nav>.dropdown.active>a:hover{color:#000000;cursor:pointer;} .nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>.open.active>a:hover{color:#ffffff;background-color:#999999;border-color:#999999;} .nav .open .caret,.nav .open.active .caret,.nav .open a:hover .caret{border-top-color:#ffffff;opacity:1;filter:alpha(opacity=100);} .tabs-stacked .open>a:hover{border-color:#999999;} .tabbable{*zoom:1;}.tabbable:before,.tabbable:after{display:table;content:"";} .tabbable:after{clear:both;} .tabs-below .nav-tabs,.tabs-right .nav-tabs,.tabs-left .nav-tabs{border-bottom:0;} .tab-content>.tab-pane,.pill-content>.pill-pane{display:none;} .tab-content>.active,.pill-content>.active{display:block;} .tabs-below .nav-tabs{border-top:1px solid #ddd;} .tabs-below .nav-tabs>li{margin-top:-1px;margin-bottom:0;} .tabs-below .nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.tabs-below .nav-tabs>li>a:hover{border-bottom-color:transparent;border-top-color:#ddd;} .tabs-below .nav-tabs .active>a,.tabs-below .nav-tabs .active>a:hover{border-color:transparent #ddd #ddd #ddd;} .tabs-left .nav-tabs>li,.tabs-right .nav-tabs>li{float:none;} .tabs-left .nav-tabs>li>a,.tabs-right .nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px;} .tabs-left .nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd;} .tabs-left .nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;} .tabs-left .nav-tabs>li>a:hover{border-color:#eeeeee #dddddd #eeeeee #eeeeee;} .tabs-left .nav-tabs .active>a,.tabs-left .nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#ffffff;} .tabs-right .nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd;} .tabs-right .nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;} .tabs-right .nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #eeeeee #dddddd;} .tabs-right .nav-tabs .active>a,.tabs-right .nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#ffffff;} .navbar{overflow:visible;margin-bottom:18px;} .navbar-inner{padding-left:20px;padding-right:20px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);} .btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);border-color:#222222 #222222 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);}.btn-navbar:hover,.btn-navbar:active,.btn-navbar.active,.btn-navbar.disabled,.btn-navbar[disabled]{background-color:#222222;} .btn-navbar:active,.btn-navbar.active{background-color:#080808 \9;} .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);-moz-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);} .btn-navbar .icon-bar+.icon-bar{margin-top:3px;} .nav-collapse.collapse{height:auto;} .navbar .brand:hover{text-decoration:none;} .navbar .brand{float:left;display:block;padding:8px 20px 12px;margin-left:-20px;font-size:20px;font-weight:200;line-height:1;color:#ffffff;} .navbar .navbar-text{margin-bottom:0;line-height:40px;color:#999999;}.navbar .navbar-text a:hover{color:#ffffff;background-color:transparent;} .navbar .btn,.navbar .btn-group{margin-top:5px;} .navbar .btn-group .btn{margin-top:0;} .navbar-form{margin-bottom:0;*zoom:1;}.navbar-form:before,.navbar-form:after{display:table;content:"";} .navbar-form:after{clear:both;} .navbar-form input,.navbar-form select{display:inline-block;margin-top:5px;margin-bottom:0;} .navbar-form .radio,.navbar-form .checkbox{margin-top:5px;} .navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px;} .navbar-search{position:relative;float:left;margin-top:6px;margin-bottom:0;}.navbar-search .search-query{padding:4px 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;color:#ffffff;color:rgba(255, 255, 255, 0.75);background:#666;background:rgba(255, 255, 255, 0.3);border:1px solid #111;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none;}.navbar-search .search-query :-moz-placeholder{color:#eeeeee;} .navbar-search .search-query::-webkit-input-placeholder{color:#eeeeee;} .navbar-search .search-query:hover{color:#ffffff;background-color:#999999;background-color:rgba(255, 255, 255, 0.5);} .navbar-search .search-query:focus,.navbar-search .search-query.focused{padding:5px 10px;color:#333333;text-shadow:0 1px 0 #ffffff;background-color:#ffffff;border:0;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);outline:0;} .navbar-fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030;} .navbar-fixed-top .navbar-inner{padding-left:0;padding-right:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} .navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0;} .navbar .nav.pull-right{float:right;} .navbar .nav>li{display:block;float:left;} .navbar .nav>li>a{float:none;padding:10px 10px 11px;line-height:19px;color:#999999;text-decoration:none;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);} .navbar .nav>li>a:hover{background-color:transparent;color:#ffffff;text-decoration:none;} .navbar .nav .active>a,.navbar .nav .active>a:hover{color:#ffffff;text-decoration:none;background-color:#222222;background-color:rgba(0, 0, 0, 0.5);} .navbar .divider-vertical{height:40px;width:1px;margin:0 9px;overflow:hidden;background-color:#222222;border-right:1px solid #333333;} .navbar .nav.pull-right{margin-left:10px;margin-right:0;} .navbar .dropdown-menu{margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.navbar .dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0, 0, 0, 0.2);position:absolute;top:-7px;left:9px;} .navbar .dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:10px;} .navbar .nav .dropdown-toggle .caret,.navbar .nav .open.dropdown .caret{border-top-color:#ffffff;} .navbar .nav .active .caret{opacity:1;filter:alpha(opacity=100);} .navbar .nav .open>.dropdown-toggle,.navbar .nav .active>.dropdown-toggle,.navbar .nav .open.active>.dropdown-toggle{background-color:transparent;} .navbar .nav .active>.dropdown-toggle:hover{color:#ffffff;} .navbar .nav.pull-right .dropdown-menu{left:auto;right:0;}.navbar .nav.pull-right .dropdown-menu:before{left:auto;right:12px;} .navbar .nav.pull-right .dropdown-menu:after{left:auto;right:13px;} .breadcrumb{padding:7px 14px;margin:0 0 18px;background-color:#fbfbfb;background-image:-moz-linear-gradient(top, #ffffff, #f5f5f5);background-image:-ms-linear-gradient(top, #ffffff, #f5f5f5);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5));background-image:-webkit-linear-gradient(top, #ffffff, #f5f5f5);background-image:-o-linear-gradient(top, #ffffff, #f5f5f5);background-image:linear-gradient(top, #ffffff, #f5f5f5);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;}.breadcrumb li{display:inline;text-shadow:0 1px 0 #ffffff;} .breadcrumb .divider{padding:0 5px;color:#999999;} .breadcrumb .active a{color:#333333;} .pagination{height:36px;margin:18px 0;} .pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);} .pagination li{display:inline;} .pagination a{float:left;padding:0 14px;line-height:34px;text-decoration:none;border:1px solid #ddd;border-left-width:0;} .pagination a:hover,.pagination .active a{background-color:#f5f5f5;} .pagination .active a{color:#999999;cursor:default;} .pagination .disabled a,.pagination .disabled a:hover{color:#999999;background-color:transparent;cursor:default;} .pagination li:first-child a{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} .pagination li:last-child a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;} .pagination-centered{text-align:center;} .pagination-right{text-align:right;} .pager{margin-left:0;margin-bottom:18px;list-style:none;text-align:center;*zoom:1;}.pager:before,.pager:after{display:table;content:"";} .pager:after{clear:both;} .pager li{display:inline;} .pager a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;} .pager a:hover{text-decoration:none;background-color:#f5f5f5;} .pager .next a{float:right;} .pager .previous a{float:left;} .modal-open .dropdown-menu{z-index:2050;} .modal-open .dropdown.open{*z-index:2050;} .modal-open .popover{z-index:2060;} .modal-open .tooltip{z-index:2070;} .modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000;}.modal-backdrop.fade{opacity:0;} .modal-backdrop,.modal-backdrop.fade.in{opacity:0.8;filter:alpha(opacity=80);} .modal{position:fixed;top:50%;left:50%;z-index:1050;max-height:500px;overflow:auto;width:560px;margin:-250px 0 0 -280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-ms-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;} .modal.fade.in{top:50%;} .modal-header{padding:9px 15px;border-bottom:1px solid #eee;}.modal-header .close{margin-top:2px;} .modal-body{padding:15px;} .modal-footer{padding:14px 15px 15px;margin-bottom:0;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;*zoom:1;}.modal-footer:before,.modal-footer:after{display:table;content:"";} .modal-footer:after{clear:both;} .modal-footer .btn{float:right;margin-left:5px;margin-bottom:0;} .tooltip{position:absolute;z-index:1020;display:block;visibility:visible;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.8;filter:alpha(opacity=80);} .tooltip.top{margin-top:-2px;} .tooltip.right{margin-left:2px;} .tooltip.bottom{margin-top:2px;} .tooltip.left{margin-left:-2px;} .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;} .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;} .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;} .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;} .tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .tooltip-arrow{position:absolute;width:0;height:0;} .popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px;}.popover.top{margin-top:-5px;} .popover.right{margin-left:5px;} .popover.bottom{margin-top:5px;} .popover.left{margin-left:-5px;} .popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;} .popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;} .popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;} .popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;} .popover .arrow{position:absolute;width:0;height:0;} .popover-inner{padding:3px;width:280px;overflow:hidden;background:#000000;background:rgba(0, 0, 0, 0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);} .popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;} .popover-content{padding:14px;background-color:#ffffff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0;} .thumbnails{margin-left:-20px;list-style:none;*zoom:1;}.thumbnails:before,.thumbnails:after{display:table;content:"";} .thumbnails:after{clear:both;} .thumbnails>li{float:left;margin:0 0 18px 20px;} .thumbnail{display:block;padding:4px;line-height:1;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);} a.thumbnail:hover{border-color:#0088cc;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);} .thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto;} .thumbnail .caption{padding:9px;} .label{padding:1px 3px 2px;font-size:9.75px;font-weight:bold;color:#ffffff;text-transform:uppercase;background-color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .label-important{background-color:#b94a48;} .label-warning{background-color:#f89406;} .label-success{background-color:#468847;} .label-info{background-color:#3a87ad;} @-webkit-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@-moz-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}.progress{overflow:hidden;height:18px;margin-bottom:18px;background-color:#f7f7f7;background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-ms-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(top, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .progress .bar{width:0%;height:18px;color:#ffffff;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-ms-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(top, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width 0.6s ease;-moz-transition:width 0.6s ease;-ms-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;} .progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px;} .progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite;} .progress-danger .bar{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-ms-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(top, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);} .progress-danger.progress-striped .bar{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);} .progress-success .bar{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-ms-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(top, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);} .progress-success.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);} .progress-info .bar{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-ms-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(top, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);} .progress-info.progress-striped .bar{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);} .accordion{margin-bottom:18px;} .accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} .accordion-heading{border-bottom:0;} .accordion-heading .accordion-toggle{display:block;padding:8px 15px;} .accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;} .carousel{position:relative;margin-bottom:18px;line-height:1;} .carousel-inner{overflow:hidden;width:100%;position:relative;} .carousel .item{display:none;position:relative;-webkit-transition:0.6s ease-in-out left;-moz-transition:0.6s ease-in-out left;-ms-transition:0.6s ease-in-out left;-o-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left;} .carousel .item>img{display:block;line-height:1;} .carousel .active,.carousel .next,.carousel .prev{display:block;} .carousel .active{left:0;} .carousel .next,.carousel .prev{position:absolute;top:0;width:100%;} .carousel .next{left:100%;} .carousel .prev{left:-100%;} .carousel .next.left,.carousel .prev.right{left:0;} .carousel .active.left{left:-100%;} .carousel .active.right{left:100%;} .carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#ffffff;text-align:center;background:#222222;border:3px solid #ffffff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:0.5;filter:alpha(opacity=50);}.carousel-control.right{left:auto;right:15px;} .carousel-control:hover{color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90);} .carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:10px 15px 5px;background:#333333;background:rgba(0, 0, 0, 0.75);} .carousel-caption h4,.carousel-caption p{color:#ffffff;} .hero-unit{padding:60px;margin-bottom:30px;background-color:#f5f5f5;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;} .hero-unit p{font-size:18px;font-weight:200;line-height:27px;} .pull-right{float:right;} .pull-left{float:left;} .hide{display:none;} .show{display:block;} .invisible{visibility:hidden;} .hidden{display:none;visibility:hidden;} @media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0);} .page-header h1 small{display:block;line-height:18px;} input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;} .input-prepend input[class*="span"],.input-append input[class*="span"]{width:auto;} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc;} .form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left;} .form-horizontal .controls{margin-left:0;} .form-horizontal .control-list{padding-top:0;} .form-horizontal .form-actions{padding-left:10px;padding-right:10px;} .modal{position:absolute;top:10px;left:10px;right:10px;width:auto;margin:0;}.modal.fade.in{top:auto;} .modal-header .close{padding:10px;margin:-10px;} .carousel-caption{position:static;}}@media (max-width:768px){.container{width:auto;padding:0 20px;} .row-fluid{width:100%;} .row{margin-left:0;} .row>[class*="span"],.row-fluid>[class*="span"]{float:none;display:block;width:auto;margin:0;}}@media (min-width:768px) and (max-width:980px){.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:20px;} .span1{width:42px;} .span2{width:104px;} .span3{width:166px;} .span4{width:228px;} .span5{width:290px;} .span6{width:352px;} .span7{width:414px;} .span8{width:476px;} .span9{width:538px;} .span10{width:600px;} .span11{width:662px;} .span12,.container{width:724px;} .offset1{margin-left:82px;} .offset2{margin-left:144px;} .offset3{margin-left:206px;} .offset4{margin-left:268px;} .offset5{margin-left:330px;} .offset6{margin-left:392px;} .offset7{margin-left:454px;} .offset8{margin-left:516px;} .offset9{margin-left:578px;} .offset10{margin-left:640px;} .offset11{margin-left:702px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid>[class*="span"]{float:left;margin-left:2.762430939%;} .row-fluid>[class*="span"]:first-child{margin-left:0;} .row-fluid .span1{width:5.801104972%;} .row-fluid .span2{width:14.364640883%;} .row-fluid .span3{width:22.928176794%;} .row-fluid .span4{width:31.491712705%;} .row-fluid .span5{width:40.055248616%;} .row-fluid .span6{width:48.618784527%;} .row-fluid .span7{width:57.182320438000005%;} .row-fluid .span8{width:65.74585634900001%;} .row-fluid .span9{width:74.30939226%;} .row-fluid .span10{width:82.87292817100001%;} .row-fluid .span11{width:91.436464082%;} .row-fluid .span12{width:99.999999993%;} input.span1,textarea.span1,.uneditable-input.span1{width:32px;} input.span2,textarea.span2,.uneditable-input.span2{width:94px;} input.span3,textarea.span3,.uneditable-input.span3{width:156px;} input.span4,textarea.span4,.uneditable-input.span4{width:218px;} input.span5,textarea.span5,.uneditable-input.span5{width:280px;} input.span6,textarea.span6,.uneditable-input.span6{width:342px;} input.span7,textarea.span7,.uneditable-input.span7{width:404px;} input.span8,textarea.span8,.uneditable-input.span8{width:466px;} input.span9,textarea.span9,.uneditable-input.span9{width:528px;} input.span10,textarea.span10,.uneditable-input.span10{width:590px;} input.span11,textarea.span11,.uneditable-input.span11{width:652px;} input.span12,textarea.span12,.uneditable-input.span12{width:714px;}}@media (max-width:980px){body{padding-top:0;} .navbar-fixed-top{position:static;margin-bottom:18px;} .navbar-fixed-top .navbar-inner{padding:5px;} .navbar .container{width:auto;padding:0;} .navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px;} .navbar .nav-collapse{clear:left;} .navbar .nav{float:none;margin:0 0 9px;} .navbar .nav>li{float:none;} .navbar .nav>li>a{margin-bottom:2px;} .navbar .nav>.divider-vertical{display:none;} .navbar .nav>li>a,.navbar .dropdown-menu a{padding:6px 15px;font-weight:bold;color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .navbar .dropdown-menu li+li a{margin-bottom:2px;} .navbar .nav>li>a:hover,.navbar .dropdown-menu a:hover{background-color:#222222;} .navbar .dropdown-menu{position:static;top:auto;left:auto;float:none;display:block;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .navbar .dropdown-menu:before,.navbar .dropdown-menu:after{display:none;} .navbar .dropdown-menu .divider{display:none;} .navbar-form,.navbar-search{float:none;padding:9px 15px;margin:9px 0;border-top:1px solid #222222;border-bottom:1px solid #222222;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);} .navbar .nav.pull-right{float:none;margin-left:0;} .navbar-static .navbar-inner{padding-left:10px;padding-right:10px;} .btn-navbar{display:block;} .nav-collapse{overflow:hidden;height:0;}}@media (min-width:980px){.nav-collapse.collapse{height:auto !important;}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1;}.row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:30px;} .span1{width:70px;} .span2{width:170px;} .span3{width:270px;} .span4{width:370px;} .span5{width:470px;} .span6{width:570px;} .span7{width:670px;} .span8{width:770px;} .span9{width:870px;} .span10{width:970px;} .span11{width:1070px;} .span12,.container{width:1170px;} .offset1{margin-left:130px;} .offset2{margin-left:230px;} .offset3{margin-left:330px;} .offset4{margin-left:430px;} .offset5{margin-left:530px;} .offset6{margin-left:630px;} .offset7{margin-left:730px;} .offset8{margin-left:830px;} .offset9{margin-left:930px;} .offset10{margin-left:1030px;} .offset11{margin-left:1130px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid>[class*="span"]{float:left;margin-left:2.564102564%;} .row-fluid>[class*="span"]:first-child{margin-left:0;} .row-fluid .span1{width:5.982905983%;} .row-fluid .span2{width:14.529914530000001%;} .row-fluid .span3{width:23.076923077%;} .row-fluid .span4{width:31.623931624%;} .row-fluid .span5{width:40.170940171000005%;} .row-fluid .span6{width:48.717948718%;} .row-fluid .span7{width:57.264957265%;} .row-fluid .span8{width:65.81196581200001%;} .row-fluid .span9{width:74.358974359%;} .row-fluid .span10{width:82.905982906%;} .row-fluid .span11{width:91.45299145300001%;} .row-fluid .span12{width:100%;} input.span1,textarea.span1,.uneditable-input.span1{width:60px;} input.span2,textarea.span2,.uneditable-input.span2{width:160px;} input.span3,textarea.span3,.uneditable-input.span3{width:260px;} input.span4,textarea.span4,.uneditable-input.span4{width:360px;} input.span5,textarea.span5,.uneditable-input.span5{width:460px;} input.span6,textarea.span6,.uneditable-input.span6{width:560px;} input.span7,textarea.span7,.uneditable-input.span7{width:660px;} input.span8,textarea.span8,.uneditable-input.span8{width:760px;} input.span9,textarea.span9,.uneditable-input.span9{width:860px;} input.span10,textarea.span10,.uneditable-input.span10{width:960px;} input.span11,textarea.span11,.uneditable-input.span11{width:1060px;} input.span12,textarea.span12,.uneditable-input.span12{width:1160px;} .thumbnails{margin-left:-30px;} .thumbnails>li{margin-left:30px;}} /*! * Bootstrap v2.0.0 * * Copyright 2012 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */ article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; } audio:not([controls]) { display: none; } html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } a:focus { outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } a:hover, a:active { outline: 0; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } img { max-width: 100%; height: auto; border: 0; -ms-interpolation-mode: bicubic; } button, input, select, textarea { margin: 0; font-size: 100%; vertical-align: middle; } button, input { *overflow: visible; line-height: normal; } button::-moz-focus-inner, input::-moz-focus-inner { padding: 0; border: 0; } button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; } input[type="search"] { -webkit-appearance: textfield; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; } input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; } textarea { overflow: auto; vertical-align: top; } body { margin: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px; color: #333333; background-color: #ffffff; } a { color: #0088cc; text-decoration: none; } a:hover { color: #005580; text-decoration: underline; } .row { margin-left: -20px; *zoom: 1; } .row:before, .row:after { display: table; content: ""; } .row:after { clear: both; } [class*="span"] { float: left; margin-left: 20px; } .span1 { width: 60px; } .span2 { width: 140px; } .span3 { width: 220px; } .span4 { width: 300px; } .span5 { width: 380px; } .span6 { width: 460px; } .span7 { width: 540px; } .span8 { width: 620px; } .span9 { width: 700px; } .span10 { width: 780px; } .span11 { width: 860px; } .span12, .container { width: 940px; } .offset1 { margin-left: 100px; } .offset2 { margin-left: 180px; } .offset3 { margin-left: 260px; } .offset4 { margin-left: 340px; } .offset5 { margin-left: 420px; } .offset6 { margin-left: 500px; } .offset7 { margin-left: 580px; } .offset8 { margin-left: 660px; } .offset9 { margin-left: 740px; } .offset10 { margin-left: 820px; } .offset11 { margin-left: 900px; } .row-fluid { width: 100%; *zoom: 1; } .row-fluid:before, .row-fluid:after { display: table; content: ""; } .row-fluid:after { clear: both; } .row-fluid > [class*="span"] { float: left; margin-left: 2.127659574%; } .row-fluid > [class*="span"]:first-child { margin-left: 0; } .row-fluid .span1 { width: 6.382978723%; } .row-fluid .span2 { width: 14.89361702%; } .row-fluid .span3 { width: 23.404255317%; } .row-fluid .span4 { width: 31.914893614%; } .row-fluid .span5 { width: 40.425531911%; } .row-fluid .span6 { width: 48.93617020799999%; } .row-fluid .span7 { width: 57.446808505%; } .row-fluid .span8 { width: 65.95744680199999%; } .row-fluid .span9 { width: 74.468085099%; } .row-fluid .span10 { width: 82.97872339599999%; } .row-fluid .span11 { width: 91.489361693%; } .row-fluid .span12 { width: 99.99999998999999%; } .container { width: 940px; margin-left: auto; margin-right: auto; *zoom: 1; } .container:before, .container:after { display: table; content: ""; } .container:after { clear: both; } .container-fluid { padding-left: 20px; padding-right: 20px; *zoom: 1; } .container-fluid:before, .container-fluid:after { display: table; content: ""; } .container-fluid:after { clear: both; } p { margin: 0 0 9px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px; } p small { font-size: 11px; color: #999999; } .lead { margin-bottom: 18px; font-size: 20px; font-weight: 200; line-height: 27px; } h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: bold; color: #333333; text-rendering: optimizelegibility; } h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-weight: normal; color: #999999; } h1 { font-size: 30px; line-height: 36px; } h1 small { font-size: 18px; } h2 { font-size: 24px; line-height: 36px; } h2 small { font-size: 18px; } h3 { line-height: 27px; font-size: 18px; } h3 small { font-size: 14px; } h4, h5, h6 { line-height: 18px; } h4 { font-size: 14px; } h4 small { font-size: 12px; } h5 { font-size: 12px; } h6 { font-size: 11px; color: #999999; text-transform: uppercase; } .page-header { padding-bottom: 17px; margin: 18px 0; border-bottom: 1px solid #eeeeee; } .page-header h1 { line-height: 1; } ul, ol { padding: 0; margin: 0 0 9px 25px; } ul ul, ul ol, ol ol, ol ul { margin-bottom: 0; } ul { list-style: disc; } ol { list-style: decimal; } li { line-height: 18px; } ul.unstyled { margin-left: 0; list-style: none; } dl { margin-bottom: 18px; } dt, dd { line-height: 18px; } dt { font-weight: bold; } dd { margin-left: 9px; } hr { margin: 18px 0; border: 0; border-top: 1px solid #e5e5e5; border-bottom: 1px solid #ffffff; } strong { font-weight: bold; } em { font-style: italic; } .muted { color: #999999; } abbr { font-size: 90%; text-transform: uppercase; border-bottom: 1px dotted #ddd; cursor: help; } blockquote { padding: 0 0 0 15px; margin: 0 0 18px; border-left: 5px solid #eeeeee; } blockquote p { margin-bottom: 0; font-size: 16px; font-weight: 300; line-height: 22.5px; } blockquote small { display: block; line-height: 18px; color: #999999; } blockquote small:before { content: '\2014 \00A0'; } blockquote.pull-right { float: right; padding-left: 0; padding-right: 15px; border-left: 0; border-right: 5px solid #eeeeee; } blockquote.pull-right p, blockquote.pull-right small { text-align: right; } q:before, q:after, blockquote:before, blockquote:after { content: ""; } address { display: block; margin-bottom: 18px; line-height: 18px; font-style: normal; } small { font-size: 100%; } cite { font-style: normal; } code, pre { padding: 0 3px 2px; font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; color: #333333; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } code { padding: 3px 4px; color: #d14; background-color: #f7f7f9; border: 1px solid #e1e1e8; } pre { display: block; padding: 8.5px; margin: 0 0 9px; font-size: 12px; line-height: 18px; background-color: #f5f5f5; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.15); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; white-space: pre; white-space: pre-wrap; word-break: break-all; } pre.prettyprint { margin-bottom: 18px; } pre code { padding: 0; background-color: transparent; } form { margin: 0 0 18px; } fieldset { padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; padding: 0; margin-bottom: 27px; font-size: 19.5px; line-height: 36px; color: #333333; border: 0; border-bottom: 1px solid #eee; } label, input, button, select, textarea { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; line-height: 18px; } label { display: block; margin-bottom: 5px; color: #333333; } input, textarea, select, .uneditable-input { display: inline-block; width: 210px; height: 18px; padding: 4px; margin-bottom: 9px; font-size: 13px; line-height: 18px; color: #555555; border: 1px solid #ccc; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .uneditable-textarea { width: auto; height: auto; } label input, label textarea, label select { display: block; } input[type="image"], input[type="checkbox"], input[type="radio"] { width: auto; height: auto; padding: 0; margin: 3px 0; *margin-top: 0; /* IE7 */ line-height: normal; border: 0; cursor: pointer; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } input[type="file"] { padding: initial; line-height: initial; border: initial; background-color: #ffffff; background-color: initial; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } input[type="button"], input[type="reset"], input[type="submit"] { width: auto; height: auto; } select, input[type="file"] { height: 28px; /* In IE7, the height of the select element cannot be changed by height, only font-size */ *margin-top: 4px; /* For IE7, add top margin to align select with labels */ line-height: 28px; } select { width: 220px; background-color: #ffffff; } select[multiple], select[size] { height: auto; } input[type="image"] { -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } textarea { height: auto; } input[type="hidden"] { display: none; } .radio, .checkbox { padding-left: 18px; } .radio input[type="radio"], .checkbox input[type="checkbox"] { float: left; margin-left: -18px; } .controls > .radio:first-child, .controls > .checkbox:first-child { padding-top: 5px; } .radio.inline, .checkbox.inline { display: inline-block; margin-bottom: 0; vertical-align: middle; } .radio.inline + .radio.inline, .checkbox.inline + .checkbox.inline { margin-left: 10px; } .controls > .radio.inline:first-child, .controls > .checkbox.inline:first-child { padding-top: 0; } input, textarea { -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; -moz-transition: border linear 0.2s, box-shadow linear 0.2s; -ms-transition: border linear 0.2s, box-shadow linear 0.2s; -o-transition: border linear 0.2s, box-shadow linear 0.2s; transition: border linear 0.2s, box-shadow linear 0.2s; } input:focus, textarea:focus { border-color: rgba(82, 168, 236, 0.8); -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); outline: 0; outline: thin dotted \9; /* IE6-8 */ } input[type="file"]:focus, input[type="checkbox"]:focus, select:focus { -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .input-mini { width: 60px; } .input-small { width: 90px; } .input-medium { width: 150px; } .input-large { width: 210px; } .input-xlarge { width: 270px; } .input-xxlarge { width: 530px; } input[class*="span"], select[class*="span"], textarea[class*="span"], .uneditable-input { float: none; margin-left: 0; } input.span1, textarea.span1, .uneditable-input.span1 { width: 50px; } input.span2, textarea.span2, .uneditable-input.span2 { width: 130px; } input.span3, textarea.span3, .uneditable-input.span3 { width: 210px; } input.span4, textarea.span4, .uneditable-input.span4 { width: 290px; } input.span5, textarea.span5, .uneditable-input.span5 { width: 370px; } input.span6, textarea.span6, .uneditable-input.span6 { width: 450px; } input.span7, textarea.span7, .uneditable-input.span7 { width: 530px; } input.span8, textarea.span8, .uneditable-input.span8 { width: 610px; } input.span9, textarea.span9, .uneditable-input.span9 { width: 690px; } input.span10, textarea.span10, .uneditable-input.span10 { width: 770px; } input.span11, textarea.span11, .uneditable-input.span11 { width: 850px; } input.span12, textarea.span12, .uneditable-input.span12 { width: 930px; } input[disabled], select[disabled], textarea[disabled], input[readonly], select[readonly], textarea[readonly] { background-color: #f5f5f5; border-color: #ddd; cursor: not-allowed; } .control-group.warning > label, .control-group.warning .help-block, .control-group.warning .help-inline { color: #c09853; } .control-group.warning input, .control-group.warning select, .control-group.warning textarea { color: #c09853; border-color: #c09853; } .control-group.warning input:focus, .control-group.warning select:focus, .control-group.warning textarea:focus { border-color: #a47e3c; -webkit-box-shadow: 0 0 6px #dbc59e; -moz-box-shadow: 0 0 6px #dbc59e; box-shadow: 0 0 6px #dbc59e; } .control-group.warning .input-prepend .add-on, .control-group.warning .input-append .add-on { color: #c09853; background-color: #fcf8e3; border-color: #c09853; } .control-group.error > label, .control-group.error .help-block, .control-group.error .help-inline { color: #b94a48; } .control-group.error input, .control-group.error select, .control-group.error textarea { color: #b94a48; border-color: #b94a48; } .control-group.error input:focus, .control-group.error select:focus, .control-group.error textarea:focus { border-color: #953b39; -webkit-box-shadow: 0 0 6px #d59392; -moz-box-shadow: 0 0 6px #d59392; box-shadow: 0 0 6px #d59392; } .control-group.error .input-prepend .add-on, .control-group.error .input-append .add-on { color: #b94a48; background-color: #f2dede; border-color: #b94a48; } .control-group.success > label, .control-group.success .help-block, .control-group.success .help-inline { color: #468847; } .control-group.success input, .control-group.success select, .control-group.success textarea { color: #468847; border-color: #468847; } .control-group.success input:focus, .control-group.success select:focus, .control-group.success textarea:focus { border-color: #356635; -webkit-box-shadow: 0 0 6px #7aba7b; -moz-box-shadow: 0 0 6px #7aba7b; box-shadow: 0 0 6px #7aba7b; } .control-group.success .input-prepend .add-on, .control-group.success .input-append .add-on { color: #468847; background-color: #dff0d8; border-color: #468847; } input:focus:required:invalid, textarea:focus:required:invalid, select:focus:required:invalid { color: #b94a48; border-color: #ee5f5b; } input:focus:required:invalid:focus, textarea:focus:required:invalid:focus, select:focus:required:invalid:focus { border-color: #e9322d; -webkit-box-shadow: 0 0 6px #f8b9b7; -moz-box-shadow: 0 0 6px #f8b9b7; box-shadow: 0 0 6px #f8b9b7; } .form-actions { padding: 17px 20px 18px; margin-top: 18px; margin-bottom: 18px; background-color: #f5f5f5; border-top: 1px solid #ddd; } .uneditable-input { display: block; background-color: #ffffff; border-color: #eee; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); cursor: not-allowed; } :-moz-placeholder { color: #999999; } ::-webkit-input-placeholder { color: #999999; } .help-block { margin-top: 5px; margin-bottom: 0; color: #999999; } .help-inline { display: inline-block; *display: inline; /* IE7 inline-block hack */ *zoom: 1; margin-bottom: 9px; vertical-align: middle; padding-left: 5px; } .input-prepend, .input-append { margin-bottom: 5px; *zoom: 1; } .input-prepend:before, .input-append:before, .input-prepend:after, .input-append:after { display: table; content: ""; } .input-prepend:after, .input-append:after { clear: both; } .input-prepend input, .input-append input, .input-prepend .uneditable-input, .input-append .uneditable-input { -webkit-border-radius: 0 3px 3px 0; -moz-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; } .input-prepend input:focus, .input-append input:focus, .input-prepend .uneditable-input:focus, .input-append .uneditable-input:focus { position: relative; z-index: 2; } .input-prepend .uneditable-input, .input-append .uneditable-input { border-left-color: #ccc; } .input-prepend .add-on, .input-append .add-on { float: left; display: block; width: auto; min-width: 16px; height: 18px; margin-right: -1px; padding: 4px 5px; font-weight: normal; line-height: 18px; color: #999999; text-align: center; text-shadow: 0 1px 0 #ffffff; background-color: #f5f5f5; border: 1px solid #ccc; -webkit-border-radius: 3px 0 0 3px; -moz-border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px; } .input-prepend .active, .input-append .active { background-color: #a9dba9; border-color: #46a546; } .input-prepend .add-on { *margin-top: 1px; /* IE6-7 */ } .input-append input, .input-append .uneditable-input { float: left; -webkit-border-radius: 3px 0 0 3px; -moz-border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px; } .input-append .uneditable-input { border-right-color: #ccc; } .input-append .add-on { margin-right: 0; margin-left: -1px; -webkit-border-radius: 0 3px 3px 0; -moz-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; } .input-append input:first-child { *margin-left: -160px; } .input-append input:first-child + .add-on { *margin-left: -21px; } .search-query { padding-left: 14px; padding-right: 14px; margin-bottom: 0; -webkit-border-radius: 14px; -moz-border-radius: 14px; border-radius: 14px; } .form-search input, .form-inline input, .form-horizontal input, .form-search textarea, .form-inline textarea, .form-horizontal textarea, .form-search select, .form-inline select, .form-horizontal select, .form-search .help-inline, .form-inline .help-inline, .form-horizontal .help-inline, .form-search .uneditable-input, .form-inline .uneditable-input, .form-horizontal .uneditable-input { display: inline-block; margin-bottom: 0; } .form-search label, .form-inline label, .form-search .input-append, .form-inline .input-append, .form-search .input-prepend, .form-inline .input-prepend { display: inline-block; } .form-search .input-append .add-on, .form-inline .input-prepend .add-on, .form-search .input-append .add-on, .form-inline .input-prepend .add-on { vertical-align: middle; } .control-group { margin-bottom: 9px; } .form-horizontal legend + .control-group { margin-top: 18px; -webkit-margin-top-collapse: separate; } .form-horizontal .control-group { margin-bottom: 18px; *zoom: 1; } .form-horizontal .control-group:before, .form-horizontal .control-group:after { display: table; content: ""; } .form-horizontal .control-group:after { clear: both; } .form-horizontal .control-group > label { float: left; width: 140px; padding-top: 5px; text-align: right; } .form-horizontal .controls { margin-left: 160px; } .form-horizontal .form-actions { padding-left: 160px; } table { max-width: 100%; border-collapse: collapse; border-spacing: 0; } .table { width: 100%; margin-bottom: 18px; } .table th, .table td { padding: 8px; line-height: 18px; text-align: left; border-top: 1px solid #ddd; } .table th { font-weight: bold; vertical-align: bottom; } .table td { vertical-align: top; } .table thead:first-child tr th, .table thead:first-child tr td { border-top: 0; } .table tbody + tbody { border-top: 2px solid #ddd; } .table-condensed th, .table-condensed td { padding: 4px 5px; } .table-bordered { border: 1px solid #ddd; border-collapse: separate; *border-collapse: collapsed; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .table-bordered th + th, .table-bordered td + td, .table-bordered th + td, .table-bordered td + th { border-left: 1px solid #ddd; } .table-bordered thead:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child td { border-top: 0; } .table-bordered thead:first-child tr:first-child th:first-child, .table-bordered tbody:first-child tr:first-child td:first-child { -webkit-border-radius: 4px 0 0 0; -moz-border-radius: 4px 0 0 0; border-radius: 4px 0 0 0; } .table-bordered thead:first-child tr:first-child th:last-child, .table-bordered tbody:first-child tr:first-child td:last-child { -webkit-border-radius: 0 4px 0 0; -moz-border-radius: 0 4px 0 0; border-radius: 0 4px 0 0; } .table-bordered thead:last-child tr:last-child th:first-child, .table-bordered tbody:last-child tr:last-child td:first-child { -webkit-border-radius: 0 0 0 4px; -moz-border-radius: 0 0 0 4px; border-radius: 0 0 0 4px; } .table-bordered thead:last-child tr:last-child th:last-child, .table-bordered tbody:last-child tr:last-child td:last-child { -webkit-border-radius: 0 0 4px 0; -moz-border-radius: 0 0 4px 0; border-radius: 0 0 4px 0; } .table-striped tbody tr:nth-child(odd) td, .table-striped tbody tr:nth-child(odd) th { background-color: #f9f9f9; } table .span1 { float: none; width: 44px; margin-left: 0; } table .span2 { float: none; width: 124px; margin-left: 0; } table .span3 { float: none; width: 204px; margin-left: 0; } table .span4 { float: none; width: 284px; margin-left: 0; } table .span5 { float: none; width: 364px; margin-left: 0; } table .span6 { float: none; width: 444px; margin-left: 0; } table .span7 { float: none; width: 524px; margin-left: 0; } table .span8 { float: none; width: 604px; margin-left: 0; } table .span9 { float: none; width: 684px; margin-left: 0; } table .span10 { float: none; width: 764px; margin-left: 0; } table .span11 { float: none; width: 844px; margin-left: 0; } table .span12 { float: none; width: 924px; margin-left: 0; } [class^="icon-"] { display: inline-block; width: 14px; height: 14px; vertical-align: text-top; background-image: url(../img/glyphicons-halflings.png); background-position: 14px 14px; background-repeat: no-repeat; *margin-right: .3em; } [class^="icon-"]:last-child { *margin-left: 0; } .icon-white { background-image: url(../img/glyphicons-halflings-white.png); } .icon-glass { background-position: 0 0; } .icon-music { background-position: -24px 0; } .icon-search { background-position: -48px 0; } .icon-envelope { background-position: -72px 0; } .icon-heart { background-position: -96px 0; } .icon-star { background-position: -120px 0; } .icon-star-empty { background-position: -144px 0; } .icon-user { background-position: -168px 0; } .icon-film { background-position: -192px 0; } .icon-th-large { background-position: -216px 0; } .icon-th { background-position: -240px 0; } .icon-th-list { background-position: -264px 0; } .icon-ok { background-position: -288px 0; } .icon-remove { background-position: -312px 0; } .icon-zoom-in { background-position: -336px 0; } .icon-zoom-out { background-position: -360px 0; } .icon-off { background-position: -384px 0; } .icon-signal { background-position: -408px 0; } .icon-cog { background-position: -432px 0; } .icon-trash { background-position: -456px 0; } .icon-home { background-position: 0 -24px; } .icon-file { background-position: -24px -24px; } .icon-time { background-position: -48px -24px; } .icon-road { background-position: -72px -24px; } .icon-download-alt { background-position: -96px -24px; } .icon-download { background-position: -120px -24px; } .icon-upload { background-position: -144px -24px; } .icon-inbox { background-position: -168px -24px; } .icon-play-circle { background-position: -192px -24px; } .icon-repeat { background-position: -216px -24px; } .icon-refresh { background-position: -240px -24px; } .icon-list-alt { background-position: -264px -24px; } .icon-lock { background-position: -287px -24px; } .icon-flag { background-position: -312px -24px; } .icon-headphones { background-position: -336px -24px; } .icon-volume-off { background-position: -360px -24px; } .icon-volume-down { background-position: -384px -24px; } .icon-volume-up { background-position: -408px -24px; } .icon-qrcode { background-position: -432px -24px; } .icon-barcode { background-position: -456px -24px; } .icon-tag { background-position: 0 -48px; } .icon-tags { background-position: -25px -48px; } .icon-book { background-position: -48px -48px; } .icon-bookmark { background-position: -72px -48px; } .icon-print { background-position: -96px -48px; } .icon-camera { background-position: -120px -48px; } .icon-font { background-position: -144px -48px; } .icon-bold { background-position: -167px -48px; } .icon-italic { background-position: -192px -48px; } .icon-text-height { background-position: -216px -48px; } .icon-text-width { background-position: -240px -48px; } .icon-align-left { background-position: -264px -48px; } .icon-align-center { background-position: -288px -48px; } .icon-align-right { background-position: -312px -48px; } .icon-align-justify { background-position: -336px -48px; } .icon-list { background-position: -360px -48px; } .icon-indent-left { background-position: -384px -48px; } .icon-indent-right { background-position: -408px -48px; } .icon-facetime-video { background-position: -432px -48px; } .icon-picture { background-position: -456px -48px; } .icon-pencil { background-position: 0 -72px; } .icon-map-marker { background-position: -24px -72px; } .icon-adjust { background-position: -48px -72px; } .icon-tint { background-position: -72px -72px; } .icon-edit { background-position: -96px -72px; } .icon-share { background-position: -120px -72px; } .icon-check { background-position: -144px -72px; } .icon-move { background-position: -168px -72px; } .icon-step-backward { background-position: -192px -72px; } .icon-fast-backward { background-position: -216px -72px; } .icon-backward { background-position: -240px -72px; } .icon-play { background-position: -264px -72px; } .icon-pause { background-position: -288px -72px; } .icon-stop { background-position: -312px -72px; } .icon-forward { background-position: -336px -72px; } .icon-fast-forward { background-position: -360px -72px; } .icon-step-forward { background-position: -384px -72px; } .icon-eject { background-position: -408px -72px; } .icon-chevron-left { background-position: -432px -72px; } .icon-chevron-right { background-position: -456px -72px; } .icon-plus-sign { background-position: 0 -96px; } .icon-minus-sign { background-position: -24px -96px; } .icon-remove-sign { background-position: -48px -96px; } .icon-ok-sign { background-position: -72px -96px; } .icon-question-sign { background-position: -96px -96px; } .icon-info-sign { background-position: -120px -96px; } .icon-screenshot { background-position: -144px -96px; } .icon-remove-circle { background-position: -168px -96px; } .icon-ok-circle { background-position: -192px -96px; } .icon-ban-circle { background-position: -216px -96px; } .icon-arrow-left { background-position: -240px -96px; } .icon-arrow-right { background-position: -264px -96px; } .icon-arrow-up { background-position: -289px -96px; } .icon-arrow-down { background-position: -312px -96px; } .icon-share-alt { background-position: -336px -96px; } .icon-resize-full { background-position: -360px -96px; } .icon-resize-small { background-position: -384px -96px; } .icon-plus { background-position: -408px -96px; } .icon-minus { background-position: -433px -96px; } .icon-asterisk { background-position: -456px -96px; } .icon-exclamation-sign { background-position: 0 -120px; } .icon-gift { background-position: -24px -120px; } .icon-leaf { background-position: -48px -120px; } .icon-fire { background-position: -72px -120px; } .icon-eye-open { background-position: -96px -120px; } .icon-eye-close { background-position: -120px -120px; } .icon-warning-sign { background-position: -144px -120px; } .icon-plane { background-position: -168px -120px; } .icon-calendar { background-position: -192px -120px; } .icon-random { background-position: -216px -120px; } .icon-comment { background-position: -240px -120px; } .icon-magnet { background-position: -264px -120px; } .icon-chevron-up { background-position: -288px -120px; } .icon-chevron-down { background-position: -313px -119px; } .icon-retweet { background-position: -336px -120px; } .icon-shopping-cart { background-position: -360px -120px; } .icon-folder-close { background-position: -384px -120px; } .icon-folder-open { background-position: -408px -120px; } .icon-resize-vertical { background-position: -432px -119px; } .icon-resize-horizontal { background-position: -456px -118px; } .dropdown { position: relative; } .dropdown-toggle { *margin-bottom: -3px; } .dropdown-toggle:active, .open .dropdown-toggle { outline: 0; } .caret { display: inline-block; width: 0; height: 0; text-indent: -99999px; *text-indent: 0; vertical-align: top; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 4px solid #000000; opacity: 0.3; filter: alpha(opacity=30); content: "\2193"; } .dropdown .caret { margin-top: 8px; margin-left: 2px; } .dropdown:hover .caret, .open.dropdown .caret { opacity: 1; filter: alpha(opacity=100); } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; float: left; display: none; min-width: 160px; max-width: 220px; _width: 160px; padding: 4px 0; margin: 0; list-style: none; background-color: #ffffff; border-color: #ccc; border-color: rgba(0, 0, 0, 0.2); border-style: solid; border-width: 1px; -webkit-border-radius: 0 0 5px 5px; -moz-border-radius: 0 0 5px 5px; border-radius: 0 0 5px 5px; -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -webkit-background-clip: padding-box; -moz-background-clip: padding; background-clip: padding-box; *border-right-width: 2px; *border-bottom-width: 2px; } .dropdown-menu.bottom-up { top: auto; bottom: 100%; margin-bottom: 2px; } .dropdown-menu .divider { height: 1px; margin: 5px 1px; overflow: hidden; background-color: #e5e5e5; border-bottom: 1px solid #ffffff; *width: 100%; *margin: -5px 0 5px; } .dropdown-menu a { display: block; padding: 3px 15px; clear: both; font-weight: normal; line-height: 18px; color: #555555; white-space: nowrap; } .dropdown-menu li > a:hover, .dropdown-menu .active > a, .dropdown-menu .active > a:hover { color: #ffffff; text-decoration: none; background-color: #0088cc; } .dropdown.open { *z-index: 1000; } .dropdown.open .dropdown-toggle { color: #ffffff; background: #ccc; background: rgba(0, 0, 0, 0.3); } .dropdown.open .dropdown-menu { display: block; } .typeahead { margin-top: 2px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .well { min-height: 20px; padding: 19px; margin-bottom: 20px; background-color: #f5f5f5; border: 1px solid #eee; border: 1px solid rgba(0, 0, 0, 0.05); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); } .well blockquote { border-color: #ddd; border-color: rgba(0, 0, 0, 0.15); } .fade { -webkit-transition: opacity 0.15s linear; -moz-transition: opacity 0.15s linear; -ms-transition: opacity 0.15s linear; -o-transition: opacity 0.15s linear; transition: opacity 0.15s linear; opacity: 0; } .fade.in { opacity: 1; } .collapse { -webkit-transition: height 0.35s ease; -moz-transition: height 0.35s ease; -ms-transition: height 0.35s ease; -o-transition: height 0.35s ease; transition: height 0.35s ease; position: relative; overflow: hidden; height: 0; } .collapse.in { height: auto; } .close { float: right; font-size: 20px; font-weight: bold; line-height: 18px; color: #000000; text-shadow: 0 1px 0 #ffffff; opacity: 0.2; filter: alpha(opacity=20); } .close:hover { color: #000000; text-decoration: none; opacity: 0.4; filter: alpha(opacity=40); cursor: pointer; } .btn { display: inline-block; padding: 4px 10px 4px; font-size: 13px; line-height: 18px; color: #333333; text-align: center; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); background-color: #fafafa; background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); background-repeat: no-repeat; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); border: 1px solid #ccc; border-bottom-color: #bbb; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); cursor: pointer; *margin-left: .3em; } .btn:first-child { *margin-left: 0; } .btn:hover { color: #333333; text-decoration: none; background-color: #e6e6e6; background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; -ms-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; } .btn:focus { outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .btn.active, .btn:active { background-image: none; -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); background-color: #e6e6e6; background-color: #d9d9d9 \9; color: rgba(0, 0, 0, 0.5); outline: 0; } .btn.disabled, .btn[disabled] { cursor: default; background-image: none; background-color: #e6e6e6; opacity: 0.65; filter: alpha(opacity=65); -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } .btn-large { padding: 9px 14px; font-size: 15px; line-height: normal; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .btn-large .icon { margin-top: 1px; } .btn-small { padding: 5px 9px; font-size: 11px; line-height: 16px; } .btn-small .icon { margin-top: -1px; } .btn-primary, .btn-primary:hover, .btn-warning, .btn-warning:hover, .btn-danger, .btn-danger:hover, .btn-success, .btn-success:hover, .btn-info, .btn-info:hover { text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); color: #ffffff; } .btn-primary.active, .btn-warning.active, .btn-danger.active, .btn-success.active, .btn-info.active { color: rgba(255, 255, 255, 0.75); } .btn-primary { background-color: #006dcc; background-image: -moz-linear-gradient(top, #0088cc, #0044cc); background-image: -ms-linear-gradient(top, #0088cc, #0044cc); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); background-image: -o-linear-gradient(top, #0088cc, #0044cc); background-image: linear-gradient(top, #0088cc, #0044cc); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); border-color: #0044cc #0044cc #002a80; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] { background-color: #0044cc; } .btn-primary:active, .btn-primary.active { background-color: #003399 \9; } .btn-warning { background-color: #faa732; background-image: -moz-linear-gradient(top, #fbb450, #f89406); background-image: -ms-linear-gradient(top, #fbb450, #f89406); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); background-image: -webkit-linear-gradient(top, #fbb450, #f89406); background-image: -o-linear-gradient(top, #fbb450, #f89406); background-image: linear-gradient(top, #fbb450, #f89406); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); border-color: #f89406 #f89406 #ad6704; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .btn-warning:hover, .btn-warning:active, .btn-warning.active, .btn-warning.disabled, .btn-warning[disabled] { background-color: #f89406; } .btn-warning:active, .btn-warning.active { background-color: #c67605 \9; } .btn-danger { background-color: #da4f49; background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); background-image: linear-gradient(top, #ee5f5b, #bd362f); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0); border-color: #bd362f #bd362f #802420; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .btn-danger:hover, .btn-danger:active, .btn-danger.active, .btn-danger.disabled, .btn-danger[disabled] { background-color: #bd362f; } .btn-danger:active, .btn-danger.active { background-color: #942a25 \9; } .btn-success { background-color: #5bb75b; background-image: -moz-linear-gradient(top, #62c462, #51a351); background-image: -ms-linear-gradient(top, #62c462, #51a351); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); background-image: -webkit-linear-gradient(top, #62c462, #51a351); background-image: -o-linear-gradient(top, #62c462, #51a351); background-image: linear-gradient(top, #62c462, #51a351); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0); border-color: #51a351 #51a351 #387038; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .btn-success:hover, .btn-success:active, .btn-success.active, .btn-success.disabled, .btn-success[disabled] { background-color: #51a351; } .btn-success:active, .btn-success.active { background-color: #408140 \9; } .btn-info { background-color: #49afcd; background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); background-image: linear-gradient(top, #5bc0de, #2f96b4); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0); border-color: #2f96b4 #2f96b4 #1f6377; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .btn-info:hover, .btn-info:active, .btn-info.active, .btn-info.disabled, .btn-info[disabled] { background-color: #2f96b4; } .btn-info:active, .btn-info.active { background-color: #24748c \9; } button.btn, input[type="submit"].btn { *padding-top: 2px; *padding-bottom: 2px; } button.btn::-moz-focus-inner, input[type="submit"].btn::-moz-focus-inner { padding: 0; border: 0; } button.btn.large, input[type="submit"].btn.large { *padding-top: 7px; *padding-bottom: 7px; } button.btn.small, input[type="submit"].btn.small { *padding-top: 3px; *padding-bottom: 3px; } .btn-group { position: relative; *zoom: 1; *margin-left: .3em; } .btn-group:before, .btn-group:after { display: table; content: ""; } .btn-group:after { clear: both; } .btn-group:first-child { *margin-left: 0; } .btn-group + .btn-group { margin-left: 5px; } .btn-toolbar { margin-top: 9px; margin-bottom: 9px; } .btn-toolbar .btn-group { display: inline-block; *display: inline; /* IE7 inline-block hack */ *zoom: 1; } .btn-group .btn { position: relative; float: left; margin-left: -1px; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .btn-group .btn:first-child { margin-left: 0; -webkit-border-top-left-radius: 4px; -moz-border-radius-topleft: 4px; border-top-left-radius: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomleft: 4px; border-bottom-left-radius: 4px; } .btn-group .btn:last-child, .btn-group .dropdown-toggle { -webkit-border-top-right-radius: 4px; -moz-border-radius-topright: 4px; border-top-right-radius: 4px; -webkit-border-bottom-right-radius: 4px; -moz-border-radius-bottomright: 4px; border-bottom-right-radius: 4px; } .btn-group .btn.large:first-child { margin-left: 0; -webkit-border-top-left-radius: 6px; -moz-border-radius-topleft: 6px; border-top-left-radius: 6px; -webkit-border-bottom-left-radius: 6px; -moz-border-radius-bottomleft: 6px; border-bottom-left-radius: 6px; } .btn-group .btn.large:last-child, .btn-group .large.dropdown-toggle { -webkit-border-top-right-radius: 6px; -moz-border-radius-topright: 6px; border-top-right-radius: 6px; -webkit-border-bottom-right-radius: 6px; -moz-border-radius-bottomright: 6px; border-bottom-right-radius: 6px; } .btn-group .btn:hover, .btn-group .btn:focus, .btn-group .btn:active, .btn-group .btn.active { z-index: 2; } .btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { outline: 0; } .btn-group .dropdown-toggle { padding-left: 8px; padding-right: 8px; -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); *padding-top: 5px; *padding-bottom: 5px; } .btn-group.open { *z-index: 1000; } .btn-group.open .dropdown-menu { display: block; margin-top: 1px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .btn-group.open .dropdown-toggle { background-image: none; -webkit-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); } .btn .caret { margin-top: 7px; margin-left: 0; } .btn:hover .caret, .open.btn-group .caret { opacity: 1; filter: alpha(opacity=100); } .btn-primary .caret, .btn-danger .caret, .btn-info .caret, .btn-success .caret { border-top-color: #ffffff; opacity: 0.75; filter: alpha(opacity=75); } .btn-small .caret { margin-top: 4px; } .alert { padding: 8px 35px 8px 14px; margin-bottom: 18px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); background-color: #fcf8e3; border: 1px solid #fbeed5; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .alert, .alert-heading { color: #c09853; } .alert .close { position: relative; top: -2px; right: -21px; line-height: 18px; } .alert-success { background-color: #dff0d8; border-color: #d6e9c6; } .alert-success, .alert-success .alert-heading { color: #468847; } .alert-danger, .alert-error { background-color: #f2dede; border-color: #eed3d7; } .alert-danger, .alert-error, .alert-danger .alert-heading, .alert-error .alert-heading { color: #b94a48; } .alert-info { background-color: #d9edf7; border-color: #bce8f1; } .alert-info, .alert-info .alert-heading { color: #3a87ad; } .alert-block { padding-top: 14px; padding-bottom: 14px; } .alert-block > p, .alert-block > ul { margin-bottom: 0; } .alert-block p + p { margin-top: 5px; } .nav { margin-left: 0; margin-bottom: 18px; list-style: none; } .nav > li > a { display: block; } .nav > li > a:hover { text-decoration: none; background-color: #eeeeee; } .nav-list { padding-left: 14px; padding-right: 14px; margin-bottom: 0; } .nav-list > li > a, .nav-list .nav-header { display: block; padding: 3px 15px; margin-left: -15px; margin-right: -15px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); } .nav-list .nav-header { font-size: 11px; font-weight: bold; line-height: 18px; color: #999999; text-transform: uppercase; } .nav-list .nav-header * { text-transform:none; } .nav-list > li + .nav-header { margin-top: 9px; } .nav-list .active > a, .nav-list .active > a:hover { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); background-color: #0088cc; } .nav-list [class^="icon-"] { margin-right: 2px; } .nav-tabs, .nav-pills { *zoom: 1; } .nav-tabs:before, .nav-pills:before, .nav-tabs:after, .nav-pills:after { display: table; content: ""; } .nav-tabs:after, .nav-pills:after { clear: both; } .nav-tabs > li, .nav-pills > li { float: left; } .nav-tabs > li > a, .nav-pills > li > a { padding-right: 12px; padding-left: 12px; margin-right: 2px; line-height: 14px; } .nav-tabs { border-bottom: 1px solid #ddd; } .nav-tabs > li { margin-bottom: -1px; } .nav-tabs > li > a { padding-top: 9px; padding-bottom: 9px; border: 1px solid transparent; -webkit-border-radius: 4px 4px 0 0; -moz-border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0; } .nav-tabs > li > a:hover { border-color: #eeeeee #eeeeee #dddddd; } .nav-tabs > .active > a, .nav-tabs > .active > a:hover { color: #555555; background-color: #ffffff; border: 1px solid #ddd; border-bottom-color: transparent; cursor: default; } .nav-pills > li > a { padding-top: 8px; padding-bottom: 8px; margin-top: 2px; margin-bottom: 2px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .nav-pills .active > a, .nav-pills .active > a:hover { color: #ffffff; background-color: #0088cc; } .nav-stacked > li { float: none; } .nav-stacked > li > a { margin-right: 0; } .nav-tabs.nav-stacked { border-bottom: 0; } .nav-tabs.nav-stacked > li > a { border: 1px solid #ddd; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .nav-tabs.nav-stacked > li:first-child > a { -webkit-border-radius: 4px 4px 0 0; -moz-border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0; } .nav-tabs.nav-stacked > li:last-child > a { -webkit-border-radius: 0 0 4px 4px; -moz-border-radius: 0 0 4px 4px; border-radius: 0 0 4px 4px; } .nav-tabs.nav-stacked > li > a:hover { border-color: #ddd; z-index: 2; } .nav-pills.nav-stacked > li > a { margin-bottom: 3px; } .nav-pills.nav-stacked > li:last-child > a { margin-bottom: 1px; } .nav-tabs .dropdown-menu, .nav-pills .dropdown-menu { margin-top: 1px; border-width: 1px; } .nav-pills .dropdown-menu { -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .nav-tabs .dropdown-toggle .caret, .nav-pills .dropdown-toggle .caret { border-top-color: #0088cc; margin-top: 6px; } .nav-tabs .dropdown-toggle:hover .caret, .nav-pills .dropdown-toggle:hover .caret { border-top-color: #005580; } .nav-tabs .active .dropdown-toggle .caret, .nav-pills .active .dropdown-toggle .caret { border-top-color: #333333; } .nav > .dropdown.active > a:hover { color: #000000; cursor: pointer; } .nav-tabs .open .dropdown-toggle, .nav-pills .open .dropdown-toggle, .nav > .open.active > a:hover { color: #ffffff; background-color: #999999; border-color: #999999; } .nav .open .caret, .nav .open.active .caret, .nav .open a:hover .caret { border-top-color: #ffffff; opacity: 1; filter: alpha(opacity=100); } .tabs-stacked .open > a:hover { border-color: #999999; } .tabbable { *zoom: 1; } .tabbable:before, .tabbable:after { display: table; content: ""; } .tabbable:after { clear: both; } .tabs-below .nav-tabs, .tabs-right .nav-tabs, .tabs-left .nav-tabs { border-bottom: 0; } .tab-content > .tab-pane, .pill-content > .pill-pane { display: none; } .tab-content > .active, .pill-content > .active { display: block; } .tabs-below .nav-tabs { border-top: 1px solid #ddd; } .tabs-below .nav-tabs > li { margin-top: -1px; margin-bottom: 0; } .tabs-below .nav-tabs > li > a { -webkit-border-radius: 0 0 4px 4px; -moz-border-radius: 0 0 4px 4px; border-radius: 0 0 4px 4px; } .tabs-below .nav-tabs > li > a:hover { border-bottom-color: transparent; border-top-color: #ddd; } .tabs-below .nav-tabs .active > a, .tabs-below .nav-tabs .active > a:hover { border-color: transparent #ddd #ddd #ddd; } .tabs-left .nav-tabs > li, .tabs-right .nav-tabs > li { float: none; } .tabs-left .nav-tabs > li > a, .tabs-right .nav-tabs > li > a { min-width: 74px; margin-right: 0; margin-bottom: 3px; } .tabs-left .nav-tabs { float: left; margin-right: 19px; border-right: 1px solid #ddd; } .tabs-left .nav-tabs > li > a { margin-right: -1px; -webkit-border-radius: 4px 0 0 4px; -moz-border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px; } .tabs-left .nav-tabs > li > a:hover { border-color: #eeeeee #dddddd #eeeeee #eeeeee; } .tabs-left .nav-tabs .active > a, .tabs-left .nav-tabs .active > a:hover { border-color: #ddd transparent #ddd #ddd; *border-right-color: #ffffff; } .tabs-right .nav-tabs { float: right; margin-left: 19px; border-left: 1px solid #ddd; } .tabs-right .nav-tabs > li > a { margin-left: -1px; -webkit-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } .tabs-right .nav-tabs > li > a:hover { border-color: #eeeeee #eeeeee #eeeeee #dddddd; } .tabs-right .nav-tabs .active > a, .tabs-right .nav-tabs .active > a:hover { border-color: #ddd #ddd #ddd transparent; *border-left-color: #ffffff; } .navbar { overflow: visible; margin-bottom: 18px; } .navbar-inner { padding-left: 20px; padding-right: 20px; background-color: #2c2c2c; background-image: -moz-linear-gradient(top, #333333, #222222); background-image: -ms-linear-gradient(top, #333333, #222222); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); background-image: -webkit-linear-gradient(top, #333333, #222222); background-image: -o-linear-gradient(top, #333333, #222222); background-image: linear-gradient(top, #333333, #222222); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); } .btn-navbar { display: none; float: right; padding: 7px 10px; margin-left: 5px; margin-right: 5px; background-color: #2c2c2c; background-image: -moz-linear-gradient(top, #333333, #222222); background-image: -ms-linear-gradient(top, #333333, #222222); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222)); background-image: -webkit-linear-gradient(top, #333333, #222222); background-image: -o-linear-gradient(top, #333333, #222222); background-image: linear-gradient(top, #333333, #222222); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); border-color: #222222 #222222 #000000; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); } .btn-navbar:hover, .btn-navbar:active, .btn-navbar.active, .btn-navbar.disabled, .btn-navbar[disabled] { background-color: #222222; } .btn-navbar:active, .btn-navbar.active { background-color: #080808 \9; } .btn-navbar .icon-bar { display: block; width: 18px; height: 2px; background-color: #f5f5f5; -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); } .btn-navbar .icon-bar + .icon-bar { margin-top: 3px; } .nav-collapse.collapse { height: auto; } .navbar .brand:hover { text-decoration: none; } .navbar .brand { float: left; display: block; padding: 8px 20px 12px; margin-left: -20px; font-size: 20px; font-weight: 200; line-height: 1; color: #ffffff; } .navbar .navbar-text { margin-bottom: 0; line-height: 40px; color: #999999; } .navbar .navbar-text a:hover { color: #ffffff; background-color: transparent; } .navbar .btn, .navbar .btn-group { margin-top: 5px; } .navbar .btn-group .btn { margin-top: 0; } .navbar-form { margin-bottom: 0; *zoom: 1; } .navbar-form:before, .navbar-form:after { display: table; content: ""; } .navbar-form:after { clear: both; } .navbar-form input, .navbar-form select { display: inline-block; margin-top: 5px; margin-bottom: 0; } .navbar-form .radio, .navbar-form .checkbox { margin-top: 5px; } .navbar-form input[type="image"], .navbar-form input[type="checkbox"], .navbar-form input[type="radio"] { margin-top: 3px; } .navbar-search { position: relative; float: left; margin-top: 6px; margin-bottom: 0; } .navbar-search .search-query { padding: 4px 9px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; line-height: 1; color: #ffffff; color: rgba(255, 255, 255, 0.75); background: #666; background: rgba(255, 255, 255, 0.3); border: 1px solid #111; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15); -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none; transition: none; } .navbar-search .search-query :-moz-placeholder { color: #eeeeee; } .navbar-search .search-query::-webkit-input-placeholder { color: #eeeeee; } .navbar-search .search-query:hover { color: #ffffff; background-color: #999999; background-color: rgba(255, 255, 255, 0.5); } .navbar-search .search-query:focus, .navbar-search .search-query.focused { padding: 5px 10px; color: #333333; text-shadow: 0 1px 0 #ffffff; background-color: #ffffff; border: 0; -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); outline: 0; } .navbar-fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030; } .navbar-fixed-top .navbar-inner { padding-left: 0; padding-right: 0; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .navbar .nav { position: relative; left: 0; display: block; float: left; margin: 0 10px 0 0; } .navbar .nav.pull-right { float: right; } .navbar .nav > li { display: block; float: left; } .navbar .nav > li > a { float: none; padding: 10px 10px 11px; line-height: 19px; color: #999999; text-decoration: none; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); } .navbar .nav > li > a:hover { background-color: transparent; color: #ffffff; text-decoration: none; } .navbar .nav .active > a, .navbar .nav .active > a:hover { color: #ffffff; text-decoration: none; background-color: #222222; background-color: rgba(0, 0, 0, 0.5); } .navbar .divider-vertical { height: 40px; width: 1px; margin: 0 9px; overflow: hidden; background-color: #222222; border-right: 1px solid #333333; } .navbar .nav.pull-right { margin-left: 10px; margin-right: 0; } .navbar .dropdown-menu { margin-top: 1px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .navbar .dropdown-menu:before { content: ''; display: inline-block; border-left: 7px solid transparent; border-right: 7px solid transparent; border-bottom: 7px solid #ccc; border-bottom-color: rgba(0, 0, 0, 0.2); position: absolute; top: -7px; left: 9px; } .navbar .dropdown-menu:after { content: ''; display: inline-block; border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 6px solid #ffffff; position: absolute; top: -6px; left: 10px; } .navbar .nav .dropdown-toggle .caret, .navbar .nav .open.dropdown .caret { border-top-color: #ffffff; } .navbar .nav .active .caret { opacity: 1; filter: alpha(opacity=100); } .navbar .nav .open > .dropdown-toggle, .navbar .nav .active > .dropdown-toggle, .navbar .nav .open.active > .dropdown-toggle { background-color: transparent; } .navbar .nav .active > .dropdown-toggle:hover { color: #ffffff; } .navbar .nav.pull-right .dropdown-menu { left: auto; right: 0; } .navbar .nav.pull-right .dropdown-menu:before { left: auto; right: 12px; } .navbar .nav.pull-right .dropdown-menu:after { left: auto; right: 13px; } .breadcrumb { padding: 7px 14px; margin: 0 0 18px; background-color: #fbfbfb; background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); background-image: linear-gradient(top, #ffffff, #f5f5f5); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); border: 1px solid #ddd; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; } .breadcrumb li { display: inline; text-shadow: 0 1px 0 #ffffff; } .breadcrumb .divider { padding: 0 5px; color: #999999; } .breadcrumb .active a { color: #333333; } .pagination { height: 36px; margin: 18px 0; } .pagination ul { display: inline-block; *display: inline; /* IE7 inline-block hack */ *zoom: 1; margin-left: 0; margin-bottom: 0; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } .pagination li { display: inline; } .pagination a { float: left; padding: 0 14px; line-height: 34px; text-decoration: none; border: 1px solid #ddd; border-left-width: 0; } .pagination a:hover, .pagination .active a { background-color: #f5f5f5; } .pagination .active a { color: #999999; cursor: default; } .pagination .disabled a, .pagination .disabled a:hover { color: #999999; background-color: transparent; cursor: default; } .pagination li:first-child a { border-left-width: 1px; -webkit-border-radius: 3px 0 0 3px; -moz-border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px; } .pagination li:last-child a { -webkit-border-radius: 0 3px 3px 0; -moz-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; } .pagination-centered { text-align: center; } .pagination-right { text-align: right; } .pager { margin-left: 0; margin-bottom: 18px; list-style: none; text-align: center; *zoom: 1; } .pager:before, .pager:after { display: table; content: ""; } .pager:after { clear: both; } .pager li { display: inline; } .pager a { display: inline-block; padding: 5px 14px; background-color: #fff; border: 1px solid #ddd; -webkit-border-radius: 15px; -moz-border-radius: 15px; border-radius: 15px; } .pager a:hover { text-decoration: none; background-color: #f5f5f5; } .pager .next a { float: right; } .pager .previous a { float: left; } .modal-open .dropdown-menu { z-index: 2050; } .modal-open .dropdown.open { *z-index: 2050; } .modal-open .popover { z-index: 2060; } .modal-open .tooltip { z-index: 2070; } .modal-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1040; background-color: #000000; } .modal-backdrop.fade { opacity: 0; } .modal-backdrop, .modal-backdrop.fade.in { opacity: 0.8; filter: alpha(opacity=80); } .modal { position: fixed; top: 50%; left: 50%; z-index: 1050; max-height: 500px; overflow: auto; width: 560px; margin: -250px 0 0 -280px; background-color: #ffffff; border: 1px solid #999; border: 1px solid rgba(0, 0, 0, 0.3); *border: 1px solid #999; /* IE6-7 */ -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -webkit-background-clip: padding-box; -moz-background-clip: padding-box; background-clip: padding-box; } .modal.fade { -webkit-transition: opacity .3s linear, top .3s ease-out; -moz-transition: opacity .3s linear, top .3s ease-out; -ms-transition: opacity .3s linear, top .3s ease-out; -o-transition: opacity .3s linear, top .3s ease-out; transition: opacity .3s linear, top .3s ease-out; top: -25%; } .modal.fade.in { top: 50%; } .modal-header { padding: 9px 15px; border-bottom: 1px solid #eee; } .modal-header .close { margin-top: 2px; } .modal-body { padding: 15px; } .modal-footer { padding: 14px 15px 15px; margin-bottom: 0; background-color: #f5f5f5; border-top: 1px solid #ddd; -webkit-border-radius: 0 0 6px 6px; -moz-border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; *zoom: 1; } .modal-footer:before, .modal-footer:after { display: table; content: ""; } .modal-footer:after { clear: both; } .modal-footer .btn { float: right; margin-left: 5px; margin-bottom: 0; } .tooltip { position: absolute; z-index: 1020; display: block; visibility: visible; padding: 5px; font-size: 11px; opacity: 0; filter: alpha(opacity=0); } .tooltip.in { opacity: 0.8; filter: alpha(opacity=80); } .tooltip.top { margin-top: -2px; } .tooltip.right { margin-left: 2px; } .tooltip.bottom { margin-top: 2px; } .tooltip.left { margin-left: -2px; } .tooltip.top .tooltip-arrow { bottom: 0; left: 50%; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 5px solid #000000; } .tooltip.left .tooltip-arrow { top: 50%; right: 0; margin-top: -5px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; border-left: 5px solid #000000; } .tooltip.bottom .tooltip-arrow { top: 0; left: 50%; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 5px solid #000000; } .tooltip.right .tooltip-arrow { top: 50%; left: 0; margin-top: -5px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; border-right: 5px solid #000000; } .tooltip-inner { max-width: 200px; padding: 3px 8px; color: #ffffff; text-align: center; text-decoration: none; background-color: #000000; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .tooltip-arrow { position: absolute; width: 0; height: 0; } .popover { position: absolute; top: 0; left: 0; z-index: 1010; display: none; padding: 5px; } .popover.top { margin-top: -5px; } .popover.right { margin-left: 5px; } .popover.bottom { margin-top: 5px; } .popover.left { margin-left: -5px; } .popover.top .arrow { bottom: 0; left: 50%; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 5px solid #000000; } .popover.right .arrow { top: 50%; left: 0; margin-top: -5px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; border-right: 5px solid #000000; } .popover.bottom .arrow { top: 0; left: 50%; margin-left: -5px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 5px solid #000000; } .popover.left .arrow { top: 50%; right: 0; margin-top: -5px; border-top: 5px solid transparent; border-bottom: 5px solid transparent; border-left: 5px solid #000000; } .popover .arrow { position: absolute; width: 0; height: 0; } .popover-inner { padding: 3px; width: 280px; overflow: hidden; background: #000000; background: rgba(0, 0, 0, 0.8); -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); } .popover-title { padding: 9px 15px; line-height: 1; background-color: #f5f5f5; border-bottom: 1px solid #eee; -webkit-border-radius: 3px 3px 0 0; -moz-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; } .popover-content { padding: 14px; background-color: #ffffff; -webkit-border-radius: 0 0 3px 3px; -moz-border-radius: 0 0 3px 3px; border-radius: 0 0 3px 3px; -webkit-background-clip: padding-box; -moz-background-clip: padding-box; background-clip: padding-box; } .popover-content p, .popover-content ul, .popover-content ol { margin-bottom: 0; } .thumbnails { margin-left: -20px; list-style: none; *zoom: 1; } .thumbnails:before, .thumbnails:after { display: table; content: ""; } .thumbnails:after { clear: both; } .thumbnails > li { float: left; margin: 0 0 18px 20px; } .thumbnail { display: block; padding: 4px; line-height: 1; border: 1px solid #ddd; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075); } a.thumbnail:hover { border-color: #0088cc; -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); } .thumbnail > img { display: block; max-width: 100%; margin-left: auto; margin-right: auto; } .thumbnail .caption { padding: 9px; } .label { padding: 1px 3px 2px; font-size: 9.75px; font-weight: bold; color: #ffffff; text-transform: uppercase; background-color: #999999; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .label-important { background-color: #b94a48; } .label-warning { background-color: #f89406; } .label-success { background-color: #468847; } .label-info { background-color: #3a87ad; } @-webkit-keyframes progress-bar-stripes { from { background-position: 0 0; } to { background-position: 40px 0; } } @-moz-keyframes progress-bar-stripes { from { background-position: 0 0; } to { background-position: 40px 0; } } @keyframes progress-bar-stripes { from { background-position: 0 0; } to { background-position: 40px 0; } } .progress { overflow: hidden; height: 18px; margin-bottom: 18px; background-color: #f7f7f7; background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: linear-gradient(top, #f5f5f5, #f9f9f9); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0); -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .progress .bar { width: 0%; height: 18px; color: #ffffff; font-size: 12px; text-align: center; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #0e90d2; background-image: -moz-linear-gradient(top, #149bdf, #0480be); background-image: -ms-linear-gradient(top, #149bdf, #0480be); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); background-image: -webkit-linear-gradient(top, #149bdf, #0480be); background-image: -o-linear-gradient(top, #149bdf, #0480be); background-image: linear-gradient(top, #149bdf, #0480be); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0); -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-transition: width 0.6s ease; -moz-transition: width 0.6s ease; -ms-transition: width 0.6s ease; -o-transition: width 0.6s ease; transition: width 0.6s ease; } .progress-striped .bar { background-color: #62c462; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -webkit-background-size: 40px 40px; -moz-background-size: 40px 40px; -o-background-size: 40px 40px; background-size: 40px 40px; } .progress.active .bar { -webkit-animation: progress-bar-stripes 2s linear infinite; -moz-animation: progress-bar-stripes 2s linear infinite; animation: progress-bar-stripes 2s linear infinite; } .progress-danger .bar { background-color: #dd514c; background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); background-image: linear-gradient(top, #ee5f5b, #c43c35); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); } .progress-danger.progress-striped .bar { background-color: #ee5f5b; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-success .bar { background-color: #5eb95e; background-image: -moz-linear-gradient(top, #62c462, #57a957); background-image: -ms-linear-gradient(top, #62c462, #57a957); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); background-image: -webkit-linear-gradient(top, #62c462, #57a957); background-image: -o-linear-gradient(top, #62c462, #57a957); background-image: linear-gradient(top, #62c462, #57a957); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); } .progress-success.progress-striped .bar { background-color: #62c462; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-info .bar { background-color: #4bb1cf; background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); background-image: -o-linear-gradient(top, #5bc0de, #339bb9); background-image: linear-gradient(top, #5bc0de, #339bb9); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); } .progress-info.progress-striped .bar { background-color: #5bc0de; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .accordion { margin-bottom: 18px; } .accordion-group { margin-bottom: 2px; border: 1px solid #e5e5e5; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .accordion-heading { border-bottom: 0; } .accordion-heading .accordion-toggle { display: block; padding: 8px 15px; } .accordion-inner { padding: 9px 15px; border-top: 1px solid #e5e5e5; } .carousel { position: relative; margin-bottom: 18px; line-height: 1; } .carousel-inner { overflow: hidden; width: 100%; position: relative; } .carousel .item { display: none; position: relative; -webkit-transition: 0.6s ease-in-out left; -moz-transition: 0.6s ease-in-out left; -ms-transition: 0.6s ease-in-out left; -o-transition: 0.6s ease-in-out left; transition: 0.6s ease-in-out left; } .carousel .item > img { display: block; line-height: 1; } .carousel .active, .carousel .next, .carousel .prev { display: block; } .carousel .active { left: 0; } .carousel .next, .carousel .prev { position: absolute; top: 0; width: 100%; } .carousel .next { left: 100%; } .carousel .prev { left: -100%; } .carousel .next.left, .carousel .prev.right { left: 0; } .carousel .active.left { left: -100%; } .carousel .active.right { left: 100%; } .carousel-control { position: absolute; top: 40%; left: 15px; width: 40px; height: 40px; margin-top: -20px; font-size: 60px; font-weight: 100; line-height: 30px; color: #ffffff; text-align: center; background: #222222; border: 3px solid #ffffff; -webkit-border-radius: 23px; -moz-border-radius: 23px; border-radius: 23px; opacity: 0.5; filter: alpha(opacity=50); } .carousel-control.right { left: auto; right: 15px; } .carousel-control:hover { color: #ffffff; text-decoration: none; opacity: 0.9; filter: alpha(opacity=90); } .carousel-caption { position: absolute; left: 0; right: 0; bottom: 0; padding: 10px 15px 5px; background: #333333; background: rgba(0, 0, 0, 0.75); } .carousel-caption h4, .carousel-caption p { color: #ffffff; } .hero-unit { padding: 60px; margin-bottom: 30px; background-color: #f5f5f5; -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; } .hero-unit h1 { margin-bottom: 0; font-size: 60px; line-height: 1; letter-spacing: -1px; } .hero-unit p { font-size: 18px; font-weight: 200; line-height: 27px; } .pull-right { float: right; } .pull-left { float: left; } .hide { display: none; } .show { display: block; } .invisible { visibility: hidden; } /*! * Bootstrap Responsive v2.0.0 * * Copyright 2012 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */ .hidden { display: none; visibility: hidden; } @media (max-width: 480px) { .nav-collapse { -webkit-transform: translate3d(0, 0, 0); } .page-header h1 small { display: block; line-height: 18px; } input[class*="span"], select[class*="span"], textarea[class*="span"], .uneditable-input { display: block; width: 100%; height: 28px; /* Make inputs at least the height of their button counterpart */ /* Makes inputs behave like true block-level elements */ -webkit-box-sizing: border-box; /* Older Webkit */ -moz-box-sizing: border-box; /* Older FF */ -ms-box-sizing: border-box; /* IE8 */ box-sizing: border-box; /* CSS3 spec*/ } .input-prepend input[class*="span"], .input-append input[class*="span"] { width: auto; } input[type="checkbox"], input[type="radio"] { border: 1px solid #ccc; } .form-horizontal .control-group > label { float: none; width: auto; padding-top: 0; text-align: left; } .form-horizontal .controls { margin-left: 0; } .form-horizontal .control-list { padding-top: 0; } .form-horizontal .form-actions { padding-left: 10px; padding-right: 10px; } .modal { position: absolute; top: 10px; left: 10px; right: 10px; width: auto; margin: 0; } .modal.fade.in { top: auto; } .modal-header .close { padding: 10px; margin: -10px; } .carousel-caption { position: static; } } @media (max-width: 768px) { .container { width: auto; padding: 0 20px; } .row-fluid { width: 100%; } .row { margin-left: 0; } .row > [class*="span"], .row-fluid > [class*="span"] { float: none; display: block; width: auto; margin: 0; } } @media (min-width: 768px) and (max-width: 980px) { .row { margin-left: -20px; *zoom: 1; } .row:before, .row:after { display: table; content: ""; } .row:after { clear: both; } [class*="span"] { float: left; margin-left: 20px; } .span1 { width: 42px; } .span2 { width: 104px; } .span3 { width: 166px; } .span4 { width: 228px; } .span5 { width: 290px; } .span6 { width: 352px; } .span7 { width: 414px; } .span8 { width: 476px; } .span9 { width: 538px; } .span10 { width: 600px; } .span11 { width: 662px; } .span12, .container { width: 724px; } .offset1 { margin-left: 82px; } .offset2 { margin-left: 144px; } .offset3 { margin-left: 206px; } .offset4 { margin-left: 268px; } .offset5 { margin-left: 330px; } .offset6 { margin-left: 392px; } .offset7 { margin-left: 454px; } .offset8 { margin-left: 516px; } .offset9 { margin-left: 578px; } .offset10 { margin-left: 640px; } .offset11 { margin-left: 702px; } .row-fluid { width: 100%; *zoom: 1; } .row-fluid:before, .row-fluid:after { display: table; content: ""; } .row-fluid:after { clear: both; } .row-fluid > [class*="span"] { float: left; margin-left: 2.762430939%; } .row-fluid > [class*="span"]:first-child { margin-left: 0; } .row-fluid .span1 { width: 5.801104972%; } .row-fluid .span2 { width: 14.364640883%; } .row-fluid .span3 { width: 22.928176794%; } .row-fluid .span4 { width: 31.491712705%; } .row-fluid .span5 { width: 40.055248616%; } .row-fluid .span6 { width: 48.618784527%; } .row-fluid .span7 { width: 57.182320438000005%; } .row-fluid .span8 { width: 65.74585634900001%; } .row-fluid .span9 { width: 74.30939226%; } .row-fluid .span10 { width: 82.87292817100001%; } .row-fluid .span11 { width: 91.436464082%; } .row-fluid .span12 { width: 99.999999993%; } input.span1, textarea.span1, .uneditable-input.span1 { width: 32px; } input.span2, textarea.span2, .uneditable-input.span2 { width: 94px; } input.span3, textarea.span3, .uneditable-input.span3 { width: 156px; } input.span4, textarea.span4, .uneditable-input.span4 { width: 218px; } input.span5, textarea.span5, .uneditable-input.span5 { width: 280px; } input.span6, textarea.span6, .uneditable-input.span6 { width: 342px; } input.span7, textarea.span7, .uneditable-input.span7 { width: 404px; } input.span8, textarea.span8, .uneditable-input.span8 { width: 466px; } input.span9, textarea.span9, .uneditable-input.span9 { width: 528px; } input.span10, textarea.span10, .uneditable-input.span10 { width: 590px; } input.span11, textarea.span11, .uneditable-input.span11 { width: 652px; } input.span12, textarea.span12, .uneditable-input.span12 { width: 714px; } } @media (max-width: 980px) { body { padding-top: 0; } .navbar-fixed-top { position: static; margin-bottom: 18px; } .navbar-fixed-top .navbar-inner { padding: 5px; } .navbar .container { width: auto; padding: 0; } .navbar .brand { padding-left: 10px; padding-right: 10px; margin: 0 0 0 -5px; } .navbar .nav-collapse { clear: left; } .navbar .nav { float: none; margin: 0 0 9px; } .navbar .nav > li { float: none; } .navbar .nav > li > a { margin-bottom: 2px; } .navbar .nav > .divider-vertical { display: none; } .navbar .nav > li > a, .navbar .dropdown-menu a { padding: 6px 15px; font-weight: bold; color: #999999; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .navbar .dropdown-menu li + li a { margin-bottom: 2px; } .navbar .nav > li > a:hover, .navbar .dropdown-menu a:hover { background-color: #222222; } .navbar .dropdown-menu { position: static; top: auto; left: auto; float: none; display: block; max-width: none; margin: 0 15px; padding: 0; background-color: transparent; border: none; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } .navbar .dropdown-menu:before, .navbar .dropdown-menu:after { display: none; } .navbar .dropdown-menu .divider { display: none; } .navbar-form, .navbar-search { float: none; padding: 9px 15px; margin: 9px 0; border-top: 1px solid #222222; border-bottom: 1px solid #222222; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); } .navbar .nav.pull-right { float: none; margin-left: 0; } .navbar-static .navbar-inner { padding-left: 10px; padding-right: 10px; } .btn-navbar { display: block; } .nav-collapse { overflow: hidden; height: 0; } } @media (min-width: 980px) { .nav-collapse.collapse { height: auto !important; } } @media (min-width: 1200px) { .row { margin-left: -30px; *zoom: 1; } .row:before, .row:after { display: table; content: ""; } .row:after { clear: both; } [class*="span"] { float: left; margin-left: 30px; } .span1 { width: 70px; } .span2 { width: 170px; } .span3 { width: 270px; } .span4 { width: 370px; } .span5 { width: 470px; } .span6 { width: 570px; } .span7 { width: 670px; } .span8 { width: 770px; } .span9 { width: 870px; } .span10 { width: 970px; } .span11 { width: 1070px; } .span12, .container { width: 1170px; } .offset1 { margin-left: 130px; } .offset2 { margin-left: 230px; } .offset3 { margin-left: 330px; } .offset4 { margin-left: 430px; } .offset5 { margin-left: 530px; } .offset6 { margin-left: 630px; } .offset7 { margin-left: 730px; } .offset8 { margin-left: 830px; } .offset9 { margin-left: 930px; } .offset10 { margin-left: 1030px; } .offset11 { margin-left: 1130px; } .row-fluid { width: 100%; *zoom: 1; } .row-fluid:before, .row-fluid:after { display: table; content: ""; } .row-fluid:after { clear: both; } .row-fluid > [class*="span"] { float: left; margin-left: 2.564102564%; } .row-fluid > [class*="span"]:first-child { margin-left: 0; } .row-fluid .span1 { width: 5.982905983%; } .row-fluid .span2 { width: 14.529914530000001%; } .row-fluid .span3 { width: 23.076923077%; } .row-fluid .span4 { width: 31.623931624%; } .row-fluid .span5 { width: 40.170940171000005%; } .row-fluid .span6 { width: 48.717948718%; } .row-fluid .span7 { width: 57.264957265%; } .row-fluid .span8 { width: 65.81196581200001%; } .row-fluid .span9 { width: 74.358974359%; } .row-fluid .span10 { width: 82.905982906%; } .row-fluid .span11 { width: 91.45299145300001%; } .row-fluid .span12 { width: 100%; } input.span1, textarea.span1, .uneditable-input.span1 { width: 60px; } input.span2, textarea.span2, .uneditable-input.span2 { width: 160px; } input.span3, textarea.span3, .uneditable-input.span3 { width: 260px; } input.span4, textarea.span4, .uneditable-input.span4 { width: 360px; } input.span5, textarea.span5, .uneditable-input.span5 { width: 460px; } input.span6, textarea.span6, .uneditable-input.span6 { width: 560px; } input.span7, textarea.span7, .uneditable-input.span7 { width: 660px; } input.span8, textarea.span8, .uneditable-input.span8 { width: 760px; } input.span9, textarea.span9, .uneditable-input.span9 { width: 860px; } input.span10, textarea.span10, .uneditable-input.span10 { width: 960px; } input.span11, textarea.span11, .uneditable-input.span11 { width: 1060px; } input.span12, textarea.span12, .uneditable-input.span12 { width: 1160px; } .thumbnails { margin-left: -30px; } .thumbnails > li { margin-left: 30px; } } @import url(bootstrap.min.css); @import url(bootstrap-responsive.css); @import url(prettify.css); @import url(jquery.iviewer.css); @import url(https://fonts.googleapis.com/css?family=Forum); body { padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */ background: #f9f9f9; color: #444; } a { color: #55A72F; } td p:last-of-type { margin: 0; } li.l0, li.l1, li.l2, li.l3, li.l5, li.l6, li.l7, li.l8 { list-style-type: decimal; } a.brand, h2, .hero-unit h1 { font-family: 'Forum', "Helvetica Neue", Helvetica, Arial, sans-serif; } .element .span4 { width: 275px; } .namespace-contents hr, .package-contents hr { border-top: 3px dotted silver; } .namespace-indent, .package-indent { padding-left: 10px; border-left: 1px dashed #f0f0f0; } .element h3 i, .namespace-contents h3 i, .package-contents h3 i { margin-top: 2px; margin-right: 5px; } .element h3, .namespace-contents h3, .package-contents h3 { margin-top: 25px; margin-bottom: 20px; border-bottom: 1px solid silver; } .element h3:first-of-type, .namespace-contents h3:first-of-type, .package-contents h3:first-of-type { margin-top: 30px; } .element h2 { font-family: inherit; font-size: 1.2em; color: black; } .element .type { font-weight: bold; } #search-query { height: auto; } .hero-unit, div.element, .well { border: 1px solid #e0e0e0; background: white; } .dropdown-menu a{ overflow: hidden; text-overflow: ellipsis; } h2 { border-bottom: 1px dashed #55A72F; margin-bottom: 10px; padding-bottom: 0; padding-left: 5px; color: #e9e9e9; font-weight: normal; margin-top: 40px; } h2:first-of-type { margin-top: 0; } .hero-unit { background: #75a70d; /* Old browsers */ background: -moz-radial-gradient(center, ellipse cover, #bfd255 0%, #8eb92a 72%, #72aa00 96%, #9ecb2d 100%); /* FF3.6+ */ background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,#bfd255), color-stop(72%,#8eb92a), color-stop(96%,#72aa00), color-stop(100%,#9ecb2d)); /* Chrome,Safari4+ */ background: -webkit-radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* Chrome10+,Safari5.1+ */ background: -o-radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* Opera 12+ */ background: -ms-radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* IE10+ */ background: radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#bfd255', endColorstr='#9ecb2d',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */ padding: 40px 0 15px 0; box-shadow: inset 0 0 10px gray; } .hero-unit h1 { font-weight: normal; text-align: center; color: white; text-shadow: black 0 0 15px; } .hero-unit h2 { border: none; color: white; background: rgba(48, 48, 48, 0.5); padding: 0; margin: 0; margin-top: 15px; text-align: center; } .namespace-contents h2, .package-contents h2 { padding-left: 44px; background: transparent url('../img/icons/icon-th-big.png') no-repeat 3px center; } .package-contents h2 { background-image: url('../img/icons/icon-folder-open-big.png'); } .namespace-contents .element h2, .package-contents .element h2 { padding-left: 0; background: none; } div.element { border-left: 10px solid #55A72F; border-radius: 5px; padding: 7px 7px 2px 7px; margin-bottom: 15px; margin-left: 0; } div.element.protected { border-left-color: orange; } div.element.private { border-left-color: red; } div.element.class, div.element.interface, div.element.trait { border-left-color: #e0e0e0; } div.element.class.abstract h1, div.element.interface.abstract h1 { font-style: italic; } div.element h1 { font-size: 1.2em; line-height: 1.5em; margin-bottom: 10px; padding-left: 22px; background: transparent no-repeat left 2px; word-wrap: break-word; } div.element h1 a { color: transparent; margin-left: 10px; } div.element h1:hover a { color: silver; } div.element h1 a:hover { color: navy; } div.element a.more:hover { background: #f0f0f0; color: #444; text-decoration: none; } div.element a.more { font-weight: bold; text-align: center; color: gray; border-top: 1px dashed silver; display: block; margin-top: 5px; padding: 5px 0; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; } div.element p { font-size: 0.9em; } div.element .table { font-size: 0.9em; } div.element .table th { text-transform: capitalize; } div.detail-description { padding-left: 30px; } div.detail-description table th { vertical-align: top; } body.invert { background: white; } body.invert div.element { background: #f9f9f9; } ul.side-nav { clear: both; } ul.side-nav li { word-wrap: break-word; padding-left: 10px; text-indent: -10px; } ul.side-nav li a { background: transparent no-repeat 5px 3px; padding-bottom: 10px; font-style: italic; } ul.side-nav li pre { font-size: 0.8em; margin: 5px 15px 0 15px; padding: 2px 5px; background-color: #f8f8f8; color: gray; font-style: normal; word-wrap: break-word; text-indent: 0; } ul.side-nav li.view-simple span.description { display: none; } ul.side-nav li.view-simple pre { font-size: inherit; margin: inherit; padding: inherit; background-color: inherit; border: none; color: inherit; font-family: inherit; font-style: inherit; padding-bottom: 0; padding-left: 5px; } ul.side-nav li.view-simple a { padding-bottom: 0; } i.icon-custom { width: 16px; height: 16px; background-position: 0; } .table.markers { background: white; } /* JS only functionality; disable by default */ .btn-group.visibility, .btn-group.view, .btn-group.type-filter { display: none; } .visibility button { height: 24px; } div.element.constant h1, i.icon-constant { background-image: url('../img/icons/constant.png'); } div.element.function h1, i.icon-function { background-image: url('../img/icons/function.png'); } div.element.method h1, i.icon-method { background-image: url('../img/icons/method.png'); } div.element.class h1, i.icon-class { background-image: url('../img/icons/class.png'); } div.element.interface h1, i.icon-interface { background-image: url('../img/icons/interface.png'); } div.element.trait h1, i.icon-trait { background-image: url('../img/icons/trait.png'); } div.element.property h1, i.icon-property { background-image: url('../img/icons/property.png'); } span.empty-namespace { color: silver; } footer { text-align: right; font-size: 0.8em; opacity: 0.5; } #mapHolder { border: 4px solid #555; padding: 0 !important; overflow: hidden } div.element div.subelement { margin-left: 10px; padding-bottom: 5px; clear: both; } pre code { border: none; } div.element div.subelement > code { font-size: 0.8em; float: left; margin-right: 10px; padding: 0 5px; line-height: 16px; } div.element div.subelement > p { margin-left: 20px; margin-right: 50px; } div.element div.subelement h4 { color: #666; margin-bottom: 5px; } div.element div.subelement.response { padding-bottom: 15px; margin-right: 50px; } div.labels { text-align: right; } .nav-list .nav-header { font-size: 13px; } .nav-list .nav-header .side-nav-header { font-weight: bold; line-height: 18px; color: #999999; text-transform: uppercase; } .detail-description code { white-space: pre; display: inline-block; padding: 10px; } .go_to_top { float: right; margin-right: 20px; background: #2C2C2C; color: #999; padding: 3px 10px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); line-height: 19px; } .visibility .btn { text-transform: uppercase; font-size: 0.7em; font-weight: bold; } .iviewer_common { z-index: 100; } @media (min-width: 980px) { a[name] { margin-top: -50px; position: absolute; } } @media (min-width: 1200px) { .method .span4 { width: 345px; } } /* redefined because twitter bootstrap assumes that bootstrap-responsive.css */ @media (max-width: 980px) { body { padding-top: 0; } .go_to_top { display: none; } .btn-group.visibility { font-size: 0.80em; margin-bottom: 7px; display: inline-block; float: right; } } @media (max-width: 768px) { .hero-unit h1 { font-size: 30px; } .hero-unit h2 { font-size: 19px; } } @media (min-width: 768px) and (max-width: 980px) { .method .span4 { width: 203px; } } .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}.iviewer_common { position:absolute; bottom:10px; border: 1px solid #000; height: 28px; z-index: 5000; } .iviewer_cursor { cursor: url(../img/iviewer/hand.cur) 6 8, pointer; } .iviewer_drag_cursor { cursor: url(../img/iviewer/grab.cur) 6 8, pointer; } .iviewer_button { width: 28px; cursor: pointer; background-position: center center; background-repeat: no-repeat; } .iviewer_zoom_in { left: 20px; background: url(../img/iviewer/iviewer.zoom_in.png); } .iviewer_zoom_out { left: 55px; background: url(../img/iviewer/iviewer.zoom_out.png); } .iviewer_zoom_zero { left: 90px; background: url(../img/iviewer/iviewer.zoom_zero.png); } .iviewer_zoom_fit { left: 125px; background: url(../img/iviewer/iviewer.zoom_fit.png); } .iviewer_zoom_status { left: 160px; font: 1em/28px Sans; color: #000; background-color: #fff; text-align: center; width: 60px; } .iviewer_rotate_left { left: 227px; background: #fff url(../img/iviewer/iviewer.rotate_left.png) center center no-repeat; } .iviewer_rotate_right { left: 262px; background: #fff url(../img/iviewer/iviewer.rotate_right.png) center center no-repeat; } .viewer { width: 100%; height: 500px; position: relative; background: transparent url('../img/loader.gif') no-repeat center center; } .viewer img { max-width: none; } .wrapper { overflow: hidden; } .iviewer_common { border: 0; bottom: auto; top: 10px; } .iviewer_zoom_status { border: 1px solid black; }  = 
  • inherited () ::
    ()
  • inherited
    ()
  • active \
  • This namespace does not contain any documentable elements

    Functions

    Classes, interfaces, and traits

    Constants

  • This package does not contain any documentable elements

    Functions

    Classes, interfaces, and traits

    Constants

  • classes/.html classes/.html

     Methods

     Properties

     Constants

                
                 
                
                    
                
            

    Default

    ()    
                
                (
                
                    
                    
                    
                
                
                
                    
                
            

    API Inherited Static
    span4 detail-description

    Parameters

    Exceptions

    Returns

    Examples

                                    
                                
                
                 = 
                
                 
                
                    
                
            
     

    API Inherited Static
    span4 detail-description

    Examples

                                    
                                
    PNG  IHDR99sRGBbKGD pHYs  tIME 'w+( IDATh͛ygY?;ɝr3s!B$L-jŪ*TV*HQZJI Had2sr;7S\mWZ^}vd?7~[^ZJV^'(%"9k!HHcDb@+Ae9)ukO 2@$DB@RjC!SBb6W899}1Eδnfyg ͌lll2DT",ۖ#* J {\Ca,6ӈ("Bn#5>%1Jȵ9U@+ Z4my1ymw_<ے`\դ?klgcgD41D ~Fhں*CL=.E^ EaIFC BS;Li !RuD%TuKY kA%v3z[ǴVJ\ۦ2+d볲wp}Cnz˯2( t=zsk^[?\/>yEZ"OJ+IB-F $eYbd9ܢ1y -!2'5fX 1 tgdGC/5J kOVcRgEVӴ/nx+=~ݷ߾q/}ݼgG}4 )wH<ˈ)CHh1Fc IVi$J. (52BHh Z(f4mK(ȌYScAk# Qc ^:|\/z5ğW j~}ٹ+&ֈQDiф %B̐sSN-uV@(kIa"5{5DcEnR"&(&&hۖf"h@iiӦ^a:o 痗ГG+ hΙ1%4-) \̚ !3`lwmh!ALhcNKHX!ѓ$G5QZCJn"h! T&31Z#$TӔ 1l>p@/>3ݷR}(%F+Ci!v@)oAYb I  EOBKhMBA(Q݊fx %EA ڐ)RBSikj3+Y#((!){VnW-M'ILF RIgR;ZI1:zJ =T%m wh]$K<'E͘ԳiWyFkoBRV8QD$zB}ĘD5RB Mgt:\sOXH}Y)P$ZOfef)rKV55H kjFwA F SlG2Z̦yBT/zT ZV!dJB@jFk2IiՁBO;pKg(@ ×_ T5_3];9\@ Jw- (I4.0mZ<((mHn=;q蹲du]~/Z`c{mSҌ&Ak yf8>_~W&RuT,)9bT?#i֟~X i _(IO Csoa~)_|O]>zI(lF4(V5hm([e"ɴγ="Y'On J+BYK&~QS͏sHBd_yϰ+ɐtNFYS3<+вpsӏ~s~ /7'7 .o䢋Qxpkoe|ŋI)PW4ш (M %BtC/IP)cˆhE#9ƣZd~_| ?@C_hp-" "!vAKE[)D)MgiiMkXŃy&HR6c4p*dR7-VDJ9?m|9N{hRJnooQM{O~Z 1yȔh HBµ 1Q7 m1|4=) 1(dZfu}/{|/a뙇!fuUB!Sؘpjfc_.~<5.[hӆD=(_3N2OZߦ3ZDh*]K :2QA`Ɛ ʒhE׿$jS-Jmy\S:\{O ^[c\|-a flL01b(EjZ*oFNG۸[I 3^wˋλs\5˜LVAn:k<ŸM,#(yOc\RӸރ=gqMpƾw6go3_GƘ'~@ϗY ŭ.&Ȯ(ҡD}t<i.` zmzYpk䵯Gș_p}#}?+9c_^.)<;Z}q%/Ax[3(EI|{!e[GDh}H=~>6M/+[Ch@R# L~V,6||ѱ'IR^d<앯GsY9t!cl|n'y37\υW_ó~/Ɨq%/IJf 78"p]w!yB#gǷc L;AhɋX:x'^_sg{~k?·_*6Ngo=1 F?+{XY^C "* 4 0Y4F"Fm4y=\(lV1X%mU3X9m:r"Gx\p%7>r;<.. xs,Ɉsrknm,/"g: zYH=sg,wAXV8;bM")M:}`4R5UPHm#sP$b1V ̛緸z ?¡. s6OK.~=2\׼s.#}\v L[|c=2H)ҳZtXʲdn u눘ऄGt`Z| x'[K6slg(Ҿ,?@GhUWS/_'_Jzbg׿h/L^l}3/7o!hWZե CRL"%L_͐JI_B;OY\P=]g0WFZ^-WbϻO~ o%ώ)Ko>sOY^3W^ K|6mMR(cvPJ(:RI2 c [{?l׿'Y9s?x?_ݬ> c*:7ha AF>TUR֤]s Ѵ&Dwv"ňI b+HhҬlr&vFLF#,-R~Ͻ\SoE>ͬٯw}99Iaѡl ȗʷ\3~J ]( ou1vwxO#&H]WĀ:Q(k q_lyMfƀ2P[w|fsdLjVy/.@Jmy AiO#XJ(JMjrkȴBIgufU\b90y[l>?/z;a1U7?y'bkl}z/_:_J$BL*8zbTk;8O UնX[gsgx2m]y1|'\{c{VEe<'I+hqyùc~)CK"DK99Wœ&5g~@EK4S{OXYo5*FBP"(e4OĔP)J(eW7VBg?9,@?mz Fd65?hBdI|DlsƉ1-9GrMӪM~g~$ a P9 L 54ՔEv"L%r2y9pG፷P1xus> [f.a{rُ8.vy讯ro&lO`m2ApV!ư8qc\#o7\ e?cs8%xҊ,/ֲ0g56tTL^~gS"ӊ̉gw-*&s ב;~nzT4)DF ZN}$p6O?> a$;;lGچ1Uͭ-q=7ߏWiIsǓ Bٜݦs}VQ¬hRgP]*<.-^q)!۫sJcR rؚ\| -kkՌd )2zEF!ԉ` g◘YW{ɯ*6;;VuDQfǷ^v=[dzm4sdF#7^.&uw5[W9J\q<''q" zc eZLGCmJJGY۞?b.!*c+Z: )&xT2ڼ@+u-n=wy+7>}/_*Y,3z g;am-!Aiѻ(FCk4;#&S孿0_* 8&f +z5M; VhmP6CH۩oӋy+[' sgtdk,hexB`]_˯a"{WǾA%_d5!$,q-6ĔX`V"K\px'HQDwPږ-tS'Jb$DL6v"$dJqdM_{-sgZ80F[Kn sEof)f(Ҡdei6X]R[8ha0^b{ud:e"Y/c̃,Y_u0&OZO|x{|x{"hSn#QZ iږi0i|g܆3qo4>x"ȴ<4zLFC&P\ ø@Ahyg9l|N3acgB"n6WVSD445(EQûڤ;UU|R*Mi 2g{{a:/ T \CaOK_9pޥY>c %}B1g󙓜|iN=k?i~vIWӧRVb-zE[ee-фHb)k t`ЄHI1kiLqR?&D rj76dv{b !xOMoVI#(J꨹՝:i+l4-ǎKLh7R("@d0krkA񗘄=Ӻ;@imv-i}m[<'bk4B8CumJ\"I5Y"0:5l*ɳk/VlEl77Sse rw0ڒ4">.Zn$"Z[|Hp13ALxI:6;eXs URO 36&CO 0޵>:g6RY*7MsZmiBJRO{TTu~p BJi]k28ZSdR5 BQdh}dV7 eJֆJ"SuxS{Ut#eMz8!&Me"ƦM)tFPmm=6Pi5 RW ! y.خ| Һsu!yZqz/ f$4gԷOl70id=%qݨ6{Kw_fJ+|ՍMaw;rT:(X(MVkfń1u$kiCi0m=n{GЄDTOokiJU]I䙍ι}F ~ugֆ=ƽ,]}xsN}HT5Z1#B۶Ѱ[$v nn\}H4$mC6( EIY^2*`4ܦjy*?~c۳o_A{K&XN)4p8._-IDATzХߦΊ@D}XRIENDB`PNG  IHDR:PLTE333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333gT+tRNS/_?MOo ثKHuÓ'*zǽ̎sIDATx^흉r8h_fMp+̹J`pjt**qo }H)B~uY-o2Jl!aOpŷVcqJHR`f(WQY&)A^蜫/dկqX+bFcOS!paTUJwpIdt;fX^d|M/ LUZk!k [s#v[n'//j3Ǡw_ _/UOT=S^QooR;U|*Ugi[YsTfgXq}ہx?] R5j*IrH;z] Xȕ~(O+AEjSJۿ͈@DZT THUBGHl;??_v8 ށdg( _S@RXcx }Ș{vˎ+N5=ƥM^{sgcq#ϖsw*͖S}Tɒ+6L1ogl~ryenc e`5 u9!C0T 5j\]r.q_9p*߅hSm%a%T-JS>pʿO*)<$TerXK]ՕSgBv!miGzkdͫKJX|7ˑj:q36kqt8GՒ 2NSϹNeȽk[1_yT9NFKqpίňjQ`(TDʤ4D\-/- 6~T=Vy* AJFFҤq!/ b3C}@ط f-5jמ)$'@ހc|*䠯z@Z+ >#)[~OcDq_ux;E5{3)/Ry!"_T=MZ* FGfF8qo3a>8>NvʑF(4zQ}7T[~^i`>^CQF80KO\s%t5TUi:7Mq"@,\Gy幞jã<([omխsk>*"Tg'@q,ƙ#\g ْk̖:[uKWt l)%8UGW[߫JuV6TϻTUTӸuUG̾*귻 28^_uu1U1U.|'KH!ʋ,ozj^TS)I9gG=]k#|Du֩z5pru7(f?<-#e ՚zW߉EYE1m2oӳrgʸҚOv*VlS=YlP$!<.QM@OU>g6KPVlɬԷ>["vm0 ?>=Vhoٱnw!̰heK\@ҧKO<7z\Sgρ8mTR?7 mkޅ5mUۄPz?Sݩ|ϓCWY]]]]]]]]]]]]]]]]]]]m ]n_C{.[ THR#k0]bF>RˇZ~d @=xd~S0 @RvZA4-SO.a*U֠ $910v{Oȥo%9+f.@@AN3<0X~WT.o|p}0v}'~Tac1Zv^Lgu|K ?Gj1',UU_dTalL]~:C=CP4J`°Qݠ2 &nz&CDuJۻTa* ŧPe26T0}Q 'P D[Ne@:|*Ws|q]i rQZ#pcZ.俩H"?:xIpU[ 5ӈjLq SIPig*O{U׿W =[ `O7|Z|9% ):d+'Bl=EZnziՐlʺ^-0O+-\[|^Oi˷-oyoɾD%]dxg.z|f=>*8mq~_e2ɛ25]A5:"#Jyp>X=4+~"4VR?C0<.ޢj@tK/ٶM5zyDs7yKYFkݏAW%#Z$zjqkosEDB:HoiM39_,tt#Ύ޲6b=O;sG9Mu|qXO\ԍ|6yDG>G /"Pn?bO3v~1G{UT'W(|؃X+='Um*e`"N+U%JqDlߌ瓳T!>Syc%qoa/IB~ZxWJydFGj5fKlz+. bUoU͇ 9 Hqx˳Ϛ-}IW6H/J|ڜ ]^+kF]=}N 48E5r2ryVSe]oD/E8T3E &./g믿ַo|>ɭ?l2:cE0?EAkA쬣fsy??'u`D!h?*bƅQ,UmxO)zk{71LY&/7:rJt!PPC|39\YRea7r7ztyj}}sGy*{e]do}fX\3Uj{^`)z/7^V9.$`,LIu0SeM{xFydQ=JnߴJ&z Lot*&Yli%r*;ݢ)K5,U%{Lut)z|d?[QAF8g4vXQA5. {>LK9iDʥuG TngKȴg ") is յ[o&~ZS(DMʀ*i+ʔ`\; s敍eh+k!~ J.l@kxZ'@1FR4[9C|lm4TUSU$jSyށ[0;I1/8#ue/W`7Ƈi~Զ$)" P|ߟKXH֒)$Z&T,8xTQk 2 a( <*s߶9MӐeO=O|n9 eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3bKGD pHYs  tIME&PIDAT8}kG3{ssosMjBRTP[Zčv#bݸu!..tU V;7I͇Ixg9]܏. ss0f} ^}5_\>r򞝚XXK۩_>x]߇*;3ڊRiqw޻pqu?=?S6 é|>yb[ zWb8D E^gnNG?|  bDu؊V\cخ=izYs!"FJl! F=et/ifD=5A !L͡=i;;rT#Ah ) w7bZ&.+݂@nkjFkRCiKn66-Iܟ rKsK%QC+{yOTTg75+pACTQ3>D%O2&0SOoXơFVoq=ʮҍƧ7~厙~>usqu_ј5Otu[\t|GۍsM~ԕ$HRk/ I IENDB`PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<mIDAT8œ"Qkz@N&A|#&ML|IhHA` lM1Seofe=PpOpVSgKT#O %}#cXm⧤~Ie9˅nGP#y!I$I6 Fiu2 aPpvm=IUV ȋnqjbxqC0"d$: HyÁVeY4M,zM:s:bƂ$Jٌ v%STNy5L$ER5~=-A(Hǣ$0I Q =лIENDB`GIF89ajlbAԽ|9tmp|_,;X%ܬPƤ7i4e'E j dq56p1tJU$;PNG  IHDRĴl;1IDATx1 8A&:=`cc^oZ! r(TIENDB`GIF89aZx➭s-҃h$Ç4,7H`KPl\:pL )e9@\"l:+PB;PNG  IHDRa MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3bKGD pHYs  tIME&z;n7IDAT8}Oh\UΛLf$iJ@Oc)PE4)h B.qeE((,?(D M6ЖhH$޻{\$.z79s8<}@p+HNո8Sᩱ[bv{iOqo}776jf;WϜ=! "F"D1b!(PI>s"RWe=Q H\ Q+h_ZX[΋fP=G@ Y3Wz8OMBLr4"Q༫7VfsKso[\#I̼X1ɻ"u+ձ'CuZ:-TA5Uj4⫞ol)齯&95^:3M`prJ2{W-f=F3%8W`{~THtʪmC`fr98vikLI 6)UUEeE1z<ǬcaGs`d|S>:&ӻ9gO~IENDB` image/svg+xml Co PNG  IHDRasRGBbKGD pHYs  tIME\sIDAT8˕˫RQ-# H" AA"Ms05 #  ΤfgR"&MAc}IO#wM6k>ZD4"pn?T*դlCҌ[!Fb$Ih4.L gA4 pX/WշT*<@~p\D"!t:l9%f(w çD"qfJ)TUjzzsx^||r 6 E(c2R`0PӴL1ctlA;^J)L&Ǜk  5UUJ't:Aj$It:p\.ZÎ (`AE8VzodY~'f3v;-~V}nNZxv: 9GȴIENDB`PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8ˍ=OP)C0[!k_@ @ &~@[%C *UAVJ;dB ,@l_رo}nqHP=<>.]D\cn?/ 8FNq$ɷAIP0Hɦi²,0iDQdAJ|mTU&2t]$ILPT@IMIP[5AJ(Je%6O(~0[dāa(*yUtOлM̾_ ^I P%4UUoVNcc_E{v_B|NuXתA"*kfB"_0-K?6љc.oal7.`Z:g|)bbܬ*āG å2Da.a2A$tCʘ?IENDB`PNG  IHDRc,IDATx Ez ۯ$n h<("N#Ũ@W/*.J@G_ k"y% 8Y,V 'K|nT8ZqdiU&v U'PY1=& U#U݊QCM*n=fג}*IENDB`PNG  IHDRasRGBbKGD pHYs  tIME&s"|IDAT8˅OlLQΛԤLjCkJYV] $D,!DN$,6AXI"HFjռk˂ι!AWkYӴ! =?pSr7N'Gj.ZVsYoGxL]Yï;9*d6x;<[*Z1`Cp.9VtY~K@BTydkO' ن !HNyhkH574~_*ZPL:O0XUjãˣc6c6c6c6c6c6c6c6c6c6c6c6c6c6i>ėyc6c6c6c6c6c6c6pGc6c6c6c6c6c6tKic6c6c6c6c6c6pGǷZpGc6c6c6c6c6c6c6c6c6c6c6c6pGǷZPNG  IHDRĴl; pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-gAMA|Q cHRMz%u0`:o_FIDATxԕLuE $Q^㥵u 7Lw 9;ޮY 3"KY| ;gڲH/XEm v2^N%(B-sB>w}3Ύ0N;dH3)Am u=8TJR@umЬ'tLuG:_j n/B3S&/#) Rr252C WOeV4ƺs$Dc'7C܎/!) ҖTt2 'uۖN U*Ǭ,byw$D:xlzja&"O`ܿHowAeb2ө"J'蜺;Vfsc$k:q\ik6ug CCH9/8m,g sBP%<N@+clտse h?ܬ jNAOD0D]9hZ8q}r贵9\l2n v^;z>z ;3c2p+vcƨgQyͳNl0U_Yyr2~>IvĺdS's5=3Qp\{IENDB`PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDATxb?% X@ĄPFd1U 6b] =@|o@,hzF%X Iq0˟]~n/ T pMSPadeOCV@R@㼰̹`ny*,c/? /ÿ_@WGJKVQ)U`h tO&o 00#ß  L|zpb "<3Ue8s )X~ABW 3@WL%^4ÙKOL4| G88a1@L !&ZB >õo4ϯ  `6f7|`O }`0Vegа^m??^zfVW&зafx`͠ӧ7oJ%w- ,$geȫ!aa> ßw|3>|t̵+Ϟ=_Kwٽ[F"| ,Woo޸y9D3<)z^ͻ@LTfb4;-)oypIENDB`PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8œ=0?O*i)s "TU nH9Br4;y={S0tA>\XWWE+ ` \\a(QI\kǯC~H۶2i)1F4Z+Z1= c$IDzgǷ@euR(m0Ɛ;G8W':~iߎg؜4ʳ7GΏIENDB`PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8œN`hM.nMnewqg!%tjB <s&4 H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-gAMA|Q cHRMz%u0`:o_FIDATx̗mlE{Σ/^/GE[   F(񃆐cŨQD>Q%&Q Fmy +zngٖQqg?B),"Z7 nzܟS`"!Q&hlml >(IJ;MO֚@h潮"Y+0BIRa$ 0]1"M.#( JP*yom29CC-Oh@wa(2؀YeD0> dB[y ͠aáHVr8ㅰbb9԰^Bo5D>7^i>5*&?eؐ*94tӡKK TυxB}fVzv;*)@P=8Gfͪ~ \]KjJ5>r [MLcB8Ƣ۶-\6@BqrlYb\킜|E)p; 7-567";>22a(N̊gtVa;tm" }YsY\/w)԰$>ıG ijϊGVSMy` J~ ̧ŷmԀgwx4iQͿ@B$͑1H%, :?g[NtxyyلC9+;г_)#Jy3e%s'ct*d9.] S3{9W``};: >Ƭy.AvM5lqe-*X(  ɔ$9S psV#s8}z׻wΌ{rr(NQ#`TP97rsIQP@E{sC^L}]Eȹ7ycdi#+dA1CLdڅ903'}=sF/W?p$LjĀC*`C*n@Zb XWR߼ȚX3R*981n`V 7 *)3d$Pg,V &RXq宇u&D*9ҴSq9R ԾВb@E12ڌit9W?ܗm5fؾ@UgHc]g_ ^}Ϯm8;ZΜ9xϜaueӧ0i;1Im-%ԕ;B֌A"ƠYI9s&4e@ȱŨXaPU )Xjoq)V] XO:2 %%ĤdQsiCD43 ]A|t:%wwXc'kfv$+JЄ5!g541҄"X#BA.XvX>{?ǯh38kCL;~#6ziƘ;rm'b yڎ?yȓ}9=s%1A{nՋ)7HsZ@cPMM u1ҧrDCfKKزR ,øGW90ƂxU#֡ )%+ "vxobPUbK! /.4 !&R)⌣PʌrC'N [-^{ջ?|~wv~ *̆wuo?tߟf Z\UcAc`]EL)+ Jь80\UT_DJR1.{-}pj ؖSjrZjT%kN0dV25X`J ,We@}bsޢ3t9SF`g8qFSGtW>oݸn+Pp-ϼhv޺iWW#'OX+Ik=FrFz+ouL)5dUT!>a%=[ ;&2 b 10%a3Y0$Y3"NӂXŖO߳񊠱[ 1B ֣1S8S>ECb HX2"ЎQUb$G9+*jk ]HԾ\*}w`WZ$ HQ;Ol .t%@͊1`rWj9vH˪)PbJ`ȸ& Ccm|?(8Kc ]u0"A3) "6`v[S ]PR| "ʙs[3%BJxfŗ|wsU4yZ'lϬۼu5׿,7ٵ Us>éٹs;K"YsuZ7dc]WR#Y&LiS$,hlPc3T!9S6t!2Nib&Rac)ȁ.$(hg癛qh ,XS1C qWh8f#UeB`b͊d(M,SdS񼛾z~e}2 N%/hmzjyoru/^;><]{yjkؾ};pHbi!0[Xؠlዳ9rWC$f6`Qg*.FR΄L¢9.c/ eBL 5MIצ4ˮQ|UatmߕРboz7k/bQFyCD)^SS5B̆6 ٔj5Oxgv@JJ״t1E=Z522 r֓aNxdص} nE")e&KLW8u'|GƧ:L̉'Ie i.ndqv]⦭ 昙`ljsO_nC{AnY`EZc!du-LwbQUjkޡ#fG"O!^[+/%"kє ]kL*DӮ)CefFJL2 h47Z E&GLC ,Yi37|{~ P=ZgO+1Y9{9z NO< G#ՀŅyvotʅ6Gs榖&$L'+z ֱR_v.[w0wɨk/~O5nȜbEsp1%]"@+Lc-W/cBL6D- oۊ(F))gڶ#Ls6̌P%@Nᠢo :T0X^3;3B]Ȫeq\:)a2:}-^/VQ d}|}w'gX~=;6o`i-duե\Nr Nu1Qeeủrxx~/O6^q%pH@T#_]ɧw9v)6ځ3ӦE 1jCj_hm;b.zؔsڤO\MHIfB h/; mWRg6!d2% jxb %-gOf׾"#dfFC,t)56->׾yiv^4TOQkҌyR<~779Nٴq#skƌO5 "*52P~&1P1[®{v9yss5gN%6︀s^6mP5bpR)DHQhP\̤\zRcȰlS6VaJߺŷ:#m3MU(+h-2x"" ɡu{/_~vlD(DN5!3r㷜^?l֚zˤ\ƄZjP&E }V!H$RN%W-T$m(L"Dʉu7Ͼ~? 6=ݟqz+׭#+,,ĴiI(S4MCʹ Yrj)IPh.ZXY^&a &sj^?idp~* K,%W]}{ٸi9vԕ=JN麎6)mS%^8)y$ĞTbpXq㷜Y@zkv_wϬ\k\HJZTcua Xs^y{b?{} _enqI!5t3Ǐq'~C}y2RnD҅@NzhQ-RWWD)mJԆP1躆iS^Jw/.+{? /g8/@m岫gwslߺk kYhHK?2^Vj`1)9b=Y7;'rfsvq.LA$edzU|:[ƥ1遵ESO:†ݗ_mmQm{pwLJi> >}I3aڴ. ^jV}Dr&['-T׭j/eӶc-("$1As, ]P|>D^:Ǝ[)3LLеfz[cȥ~9F,b+uٞ}rJc$EQеHh,fg?ԡ}ܵ*t 1c!ۦayy LU 2BF*AsQ^JT|?}q/}џGdeypiSG5xӫ{``iZEu+\rdpTlQ Xay =4PW.C B̅ d\sj/qɥb]E?YEGRzMbċ-W<1Wzu&v41?.` mH JyΣk,J =~)úb>]?Ȏ_=Wr8욫BU'.~ƳyߍYm~O`f0DlS麆AERQ5]5}F#0|`Ӆdӎ"&sVغB7> #S$#ghچ)teVxȔŎř;t|z͓ѰV{c{7VzԔzYK3;'>;l`CۤAIJ<1/pee4+g$S* KOe #)FNX⑇Fnx^=|2?_a.ǘUD, ૖Ky/P H$aoH:fƶmiVx)kWL# l:S\z/|RyAx_'; GCKʃ_?3??b$@Wԗx~#C{0O93r24m9#ض,sF>Α}zsϑ{Gi&T͈jTN$I IRW#j)&-9oCiB?k/riIJLz_EGl}YN;EW>W ]D)P_/nLv6fb"i8yf'۾7ʏor/p߭3l`{~Kx[~gh ÷W?QNˋ_ֳzt̮+I=(f ,^"n3ǎa0mڒbǠ jy0|эHXW~ so \|/IzBp_ʴLrHV "3>txړfƛ']Dmr֌cDJۣRQi\}=o7\ [O/sE[NL'Ł;:p ˝7~y杻9^ǿwXzjϿ8 Osl}\i<3 #~tr'n"'q~moS<ɉ/}p#6 (?Eod*޻3+3`41겛rffn_&׼{:i{L~Klݺ"cs`rUS>f(qYx-˓Z}u7Y#yrv {=ӑqbΣ!,(zL~I:4lxջ~Ø;?w@DyˋlB̯_S0ZzDXܲg:UR4gs 9e>qo} |s\wP{7<,lfvq7XrnWL, 3.3=hH%ر%~ hXElUS?sveR]m?N\##ܰ档v3Y;o^iuA'eTt?ɵRz>k ǎ-ss^w% kT(O~WؽcuMcPjṯ#Ǹ>͗O誫y;57 7xГ(g /{;M+SsΎテZz+1ݟ 's[_ClڹK}<}_,/1Zhg<&|$ ))7i|UϽVѻbD9+1~ziGB dx4w֛W&Sz+/ԩO{NS=z'Yj=/rs mܐ{z7l0G;g&ʗ|9IJe8aΜ:3^},nZN *~kndfn{Yzbl;A\r-wpf^淲y*ו ]׿SOߢgذ2.wY\-.M N+V,+zv>߼!1ssU3)泵Tc#[wя0L ʹLRGa0q})N=$x ;.ĺJFPehŭ7r}~|cI9t>j{~[`' DX=$y.y_?ºٳejTIG1yHR o |7ѵb.T$v̠~g3b.AŃGoY7棪ʴ,S4 [Ssi˫ly1CжC QsѮY!ݮm+_P%Lv]?%x&߰|W앬ۺa>ejHY9l4T_ষ\=+Dd O{ F–fDQiv;a=9 gˮ gѵLEH=,3vTpi/)Ƣ@I;{Ў[S(xGZ.״9?, N*ʙU.|eR[;>$ĮFI)̀2X:q)׾7q>]qӹ_{>|O+n|9<^rQ:bF.~lb6_k0 ;q&VNpյN刕t-Xwl]p5G+an";h&=ず>N5I$1 k81"^G(߸/}rAn~Ͽ ~ lt+oFXj>x짙.Un?Wen0~ ͟q5o3'/%߄yY7s5h[-dcY l9!I{MtB!8$dh0xGlY5ZPg=%ݽ֪jiUoO<#׽s>+jJx?B+˩'4"OB9LYQlڒ($]DrzM9m)DRL4uE!'b82vaV4piXw>rݳ#>Mx ȁFvpK>k? Wexǭh}q{~l=W).;lsMfOrϟ|+o~9ooť]əO_F+RdEb9z`Iʐfuh;Sg,_$u[C*B6h"!?j# J<@HaY\I-Q*dJ6g-PQY \qT[ڶllL9З!ֻߍuEUN|=].< /z͛8)_W#ibȫ57qM7q扇y'8~oʗ(FT3gSB !#k#| bՊsgೠ@ ?jJH)Qo"v2 }!SD2kj_ޤČQ4vTuqTBvLgUˎOxooc茼^XU=kX).5j9Ka-E86c{1~'~wßصNPE?|w.xw ny밮YGSҗov?o~wo3ZsqhQD^Œ+I8g/Cơ'v0 3r N釕1" ]|/)_L6I` E=v|)c%`ٴ@BN)˜y95/B_rM\C_)hr<Gب>S+:L+>+ᶷ*fe_(8tɿ7~G=o[ߋk#~C|o# Ry }i)>j/fiZeH3 =)Ӛa_ I\gUYkZ2Sľr3zi,E? ;CȢ#-b1\E`3e U;Ֆ<@P` cA-9pp'esp!. CnZ({q!.r|w~m^=oqNBUե7o{kWp;ln;0!2uz"$uLU,x E6lsf_dɇ+2lMR2: *U! eXvL+ۙq(x)12\.S\v=u/}n4mn*tOU ;rȔ/ow o|`kF@҆k߃~h&m?I4hsV\(p:YqQK0) 1hN?rO~YKbwR ҂b7rʌ̩9 > $JB&F:ʂLjb~8?! ׏C/EsRteK6FT9(e6ۊqөCϵ/>iudY@gzݳXSg9ƕӏ>ʟ_>6lqG]k to~7۸;OaIz~E1C,uY'T ([A҄QA?avʪ:4=ec1 r+"\yudyx~$i!j]8x@!XMJbd؊B|3]߳\vm.d>^!eM J[9!xpysZqՍ7WRbmTV1_xmsݻO?3(W9%׿q+^Y{!v,kt_ELUb`kgG>7~Y/.p쪫n^w)zE)E bC8'I6H~M3ibskNA0oV3,w> ,WV*Ib!ff\!I!0at uUiqPC*$IMQH%llL̓}nh.y{%ʺzEJgHS9/%K?B̎!$Ƙ5r#O7xpgN?hNŁK/%ov^;8|q!g])BT[2uOiP(Z|N,nmU/]Q:A QjOw W^~;#UՈ)Nu"xNY o0(j{"P+RBW,9ըKUfBd kPŊ'y<:0%eoV~|Wn 3'1KD}dGiKÀ_@XʞS"9`ц0iGȕ7ii,y( 1T΀>ܐ`8kVش#+é9o \J ݺA5Ś~g\($@QAZ臱=#!+6RLSW#A|9Q6lx+r7 ,)Xy[_oKA_$7I~)[[aiEc 6EEog) S~.:ț[W|;OP736^u+ǯ ؅"sTyITa4Yk-5Q!&1`sk >귾V{xejỿʡPhɗTJ*y^I&gx?NmЌIc[(kŎmm=s SW>9:!+#װzL[K R7]\rElc|=x5䱓B:_*%TV9?|l]y5W%pS²IԂ+l\W$!XBuCHRbLr ([wydX Ƕ!'vvW<|\qLӘҦDg xI_SaN6L\,`9fggoЂDJGu[΀C&}},W\rdR_/Rq *E֙yZrn2Xyczۛ:~mrH_Xf.*G!FAХ3??&2FԆ)9U E;LN~8m1.! (|J37'L'y'qqA2^&~BXg(kKLbf.a4>e1; *Hi>qr)kcpb+o~v&]k%|30XmBHUUcbFL <.}u(+v_AVLI<,+6!.Q*rojsC@5B9{~8yWPd6)R>J*Qhvv\Wr'`9@5:c \}я>тK5Ƞ3_o="FQJ-k(cR7̚@mGK}'wEa"t}w?y𡓄aTFbRoSetb8tвؗ9>$(=-ZF cLRk=ENZAӠPOkѿx#?u?[ܠ213zd,O?zw5yaQ5<<~=6b` T6 ɄiSQ)6z}fQ]SWu5}@BFˮ*eMSUX%)k*TF}+;i"=7v=x}Ӝ)zrLt^jdVΖab7gݏL&LBdzc>cWGŌbL:ȝ ^&,:M`F>Y;LP}E^K\NLjK5@L ;WW^]s ՚1)B*ɵh" 5M- F !2ʗ*,U]]#X&eq.p 38#)0F+W W30_c+?/o(?;IlM6[:HZ`МR9u}ّMgg-{D ZHsȫ/ҟOY6LbS2c/hm]3?[?W}h"5|l{?qj|^p0EM̆@6 8ǁP金9Gqc/tgQMM[IbEVRsZbtm؜H9nzLdgQV#3[]_vE`*Ge-T1xֽĥRTZsX\8je7܂k p'>\›%rPOOoSL5Ƒ"~޿U^&zྒྷ| TKCΨeZ󳿊ϠufZ}v,wPb(ZW$cmV)>d5G~Om4ӥ (+ErEMg1#]?^E8XjС?+xMQ(>~|o牻kD9AB !E1ĮIu8_o?/:!.TĺN=ˡ-]EN؜5a`FlRê08sN)5 ?8ݼ/= r)?Ie\T=u\~߱"'$ Y<;~#1z)\* )˽=%6m&S,#o%rIgY^qE)DF8'd3C7Tsts!Ə=vF[bM=.ף^0ց1w?$A$-a= )@S9+UR*t%ɇL85acS/~ V|#L\vAډ؍ݚ9u!mH^cHc{I$(V>s~gV].vG4֒f񯽏',[EV@,-ATib=|%f*)XsHk@pGXRqc;p45s ]sRTc2`)|c6)U% y6i>w5R=Gr%y[⚛_0l*iSA154C+,gUז+.?̥GrLj (6&̗+vwwǨ֬YEXȔO <6z5:rgv${)~~^{9_ZP4PFb_,}1ϖ$+l4{@}Us(i!&ѳ^Vca:V5U]A[3 #5l~[?zTO|۾@29yt5s^{FV"3kjJ{diJ!XwkIFp~ , F?R5S[a6uj1 R7T8U^ZMc$) ;wy=/:/{Mm6%mpn?8qIE =!KMu I^k%Dmrlln0NحD<h6&u%9xBsCt{~7[0FN*s[7!B聆Z2m ),$4ۏe#+).j"ekD/JAa+KH9C)wx/gfom_Or /(E=j6c'IaQX /!KR #"f+B]$W(rdM뮓+FZy# Q Nw@ܵa2iM&"HI09:l&FI (b/uےBرM.<p%7cV17N@\rozS9^2&d*c1QW=]u9kP)2F躮'QT-cƙxr>EG?: 0ȡH4մWy+\r!%(vߜP†O)&$[ޯ22ݺLJU'ƏPRsc;}R&3 MS_}J¦nH; E%pnp-F =#w޷\u $vrHCW_mo}Nk=b4LIM_b 8#X Sx舘T~MFZj0P j9}GF+$Fʙ%7NϿˮ؄՜lldT0{y 檫KIYjș,5y񇡰/S̓k]%`*'3<1 5īol*F֫ qiSŤ}$!*0ZªvU%+cL/^Pޓ'L/{먷NCOwa=I%BhjM] £S9Gڵ1RU[cIKK.R3Z|?bi|r7HqA+4SVu`|N^^Opz'TqdVX1l\>Gv; #ԎvE-Wܑ%>{O7$bdkDe4Wl :'vwg1->'B\'BdiGko@U?uݳٛa+GҝWɫ̺[1SWMYB~Ǧ>`vwUm;s-7P Zj͛3΍|7+~6L~d #Y=U_'ҾYTI,U(a.(پ(Tۜs#V'n5DI٘Lu;ir1V]W1TrlLu;!釞#Ƕ8l C`p[BPst@TF\(T*Ւ~tr[9szu0Tҗ[қyۼ-NB(ba#uߦ!p{^rƏH2F֗:VJ\\UkQ'1Y_ bj?Ȫ߯*ؘNjrJ,A! !HT)]K 鄦5ł=Dł= {%:03V^Wq`}'~U"VKTsUx|'O<0O=0x 'Oe9s~!&dF"5` P PZb!z_"wCn(B rMa#xޕ0tNҊHBbnT!=X&MY,x?Ng$˽=(Qrlm cW}Qn|m|ӫ_P$4t9.j _"^[3'ٹCXnRqVRcduǏqaqK1bNKD R3g.Q WO>_CvzV{2sԌzTV`5˾kZmZq(jl9g,:s!)e(y Y",1P]LoDXkpU[xuJo{9,U݂X.g2m%2!sq`CG/af<<y'|?xPn˅,>(eX%:n9^~5ua0= $--kr@+٫kRt|r?IC(e,zυ ,KT S颐R/Iۈ;R叉L.C BN֢TGiicKs4;8vc,> \VkꚪrFe4Mba1_\.1RMfF)E3iKɉbz66t2A w|+׼_~JڕZmFoQ1R&rH! SYLJUX4PD5Fg-JosC<I=/p,+{  "20&a2%rALeàhGq$^"9U WΏhrF%MB@ÕV"yi*ˤi)srJ-!%5)%I+IF3[q/W7=gq9rpنFmvC8MDuU@rdog0Zh3r MUQ7r!!Tc1_03D?ҭTV4)*6՚p'O?>q5/x˹P\DfeYރ(B++ hQ4@Gt7)52a{Z*%p钨Bn$VMe\'61{yAUnRL 51JulªsdZ:!(~ݕ~$bS6U5RIaGɔtFzMLl6^;)${mzѱZp] >9i0i$5oR؜I?{Ͼ79r\~ .:f^!c9t7@Ss_?(g9S }`65X8dq9ǁ&Tރ2tuLNRvRYsQ wLyP嬠ˌAQ&gr[8A|&0V+,>ni0h}qV2Mq`UZuUb%8vAjŭ#1y6f3n2!CKUUa fBNrE" L& uUQCm`yk<~$E7DV NjtZѭ2ichlyÈ1 wNrC"z.҅|d6XQ 1'T\L8" ҆TgqVDn*.ٛYFOȓ}D%wcZ9gpqD*EjX, nZ&XV6,12L&3VXkkbfblceyrN\}*XMXiE#McZNClkcdV;bY[,0B6gZҍ W9c3HS+񣠫SLbt255!&V00t='t6#e\Ɛ#|1kHA0t+9{?\MN軞U/..Tq7dRԭcxD$t?GzI30iU/_QږZ=|$ sTqde7bJT10kГF/gIbwbC0 4Uٺ^,y%'e#'D0z//Қ#>f3-wx(%hublE:6_IDATu:s(pdmN\Q"w@SUTN2' z6~LfL66a0e2a"( \U]O]bLT1 `$SZoq#'DH^ j#V 5뾗8*gƮU0UXcH@Ӵ|9d2neB׌!3EoE ࣔ}%Kh}-,?3Oɰ9_o׌à6Yj3<ŜrA [U41]kfı'M*ڟe>S]W$YYŇՄDGBe*$S9'nCGBd:KlMد%WaD;- Ƒl s! ɄzUj%@FDl1ܸː 65Y/qR %E>*GIqY]s%HMOz t)}CLgχLlI3_v={Cc+'4mX,CG]5To_V*GNFTU]r1n1Lq\-I%gK1N\S%$)9WWED+/; =J;!ZV1a< pV5,1I95ǔцnDL qB̙ʈ;iUBk~ !:|"ʔIn\XǓN^3OquKef#LI3dvEq4u[n' =UUՆ3FdcYukBNXcJ#S7"g-DqGIwE=x/2) u%k9+h'a3uC"ᇑ29KX/j?a +0cBk+W>~*b \|Gʒ8gHEd@F/8(wc 5cJBTZczV@(cZi_zgƠKQr/gΞ^jΟgwoxꆔ2뮗T C5dlʆKӹݘfZP4#@h Ƒr)KB[@8CZxyNEXℵ-\YLXi#9-|1UvUن}?oiVݪ$e~5$✣EiqrPdLJuKej$۹X @N>`I+zXv8N.Ù'ͿsH?k|w^-rL׶4 R]%h'UþW/Cyu8XSZm)GʒB")#}?`̹$RFO#! ϠlZBX&'c')7)Kc Sd); Q. b8W/AʀuY֒霅R+y/"0c#J[%JVnA1O?rcOg&}F0!C._MR(%wCd2Qh&$w-[[&eJٲt@iLbQ@(yKCF(1CJvT(4~%Bk"JIaK{ǢpΡtjz*ѢY Wt@6JRiOLA_E# i~.{d2G–=[k8]By\*%& G~]L&]*GS -OL0F,46ZNcF)DJTUE@Ӎ`EV¸ 93 JSD(hQ-lK;Zs-}6hcA̽ҪY-W)gVuPMQs$f9BAɥ|4mc'eE*WFC#>r*p^59wvv|Ji5i[*)2v^UP[Y\rb{OUIG9$5 )bJTW1F1Xk Bu݈A11Ƚ2Xr"躹XFba9dK[^O4ŵ0U6V$~BGb~-sŊTCV[mɅGNp +)`O{@ ǔԩuBirjY}'otU qYI$qXQp`K\%1DⴤK"P*ZL!""F*^)Q-QQkIcZI"Oq@!HrXx(dFյO ~3[=eIϏfe,5!ƧvV%gRR{ 9ڶEi|`Ft PkQ9.^ p}Kb,o֚bӇͤ`#Z,/"{U3 #a eAyJ(ORf^ڂ,8wRrUb D Ieʋ8Q}m]óZ%x}~'!ZѶ=0h{{{,mk0K4cmu iYڇ{]2]} 6p{sY5XcMI]{/!p8v8chonȯ.֕r3UIr X51j=Ӣ{B+G#ΰ\.yDl[|Yr<HWX &dCUs^cdw8UkXp =#ڳ|l5M> SN.n}y|q~[@έT5߀3fz{YZcZ_ىY,5bC\4RNQ}dTaG!Vs("şR*.S#cʔojv):e#krBX 8k51Ž1V,6FG@f URSrCL]?NSJp׃_&62:[~>}QG~`AWՎ ؓrG#@^FP ,7 G06y~@_~ jJf&s` a߀wma tVjKIENDB`PNG  IHDR:PLTEaY+tRNS/_?MOo ثKHuÓ'*zǽ̎sIDATx^흉r8h_fMp+̹J`pjt**qo }H)B~uY-o2Jl!aOpŷVcqJHR`f(WQY&)A^蜫/dկqX+bFcOS!paTUJwpIdt;fX^d|M/ LUZk!k [s#v[n'//j3Ǡw_ _/UOT=S^QooR;U|*Ugi[YsTfgXq}ہx?] R5j*IrH;z] Xȕ~(O+AEjSJۿ͈@DZT THUBGHl;??_v8 ށdg( _S@RXcx }Ș{vˎ+N5=ƥM^{sgcq#ϖsw*͖S}Tɒ+6L1ogl~ryenc e`5 u9!C0T 5j\]r.q_9p*߅hSm%a%T-JS>pʿO*)<$TerXK]ՕSgBv!miGzkdͫKJX|7ˑj:q36kqt8GՒ 2NSϹNeȽk[1_yT9NFKqpίňjQ`(TDʤ4D\-/- 6~T=Vy* AJFFҤq!/ b3C}@ط f-5jמ)$'@ހc|*䠯z@Z+ >#)[~OcDq_ux;E5{3)/Ry!"_T=MZ* FGfF8qo3a>8>NvʑF(4zQ}7T[~^i`>^CQF80KO\s%t5TUi:7Mq"@,\Gy幞jã<([omխsk>*"Tg'@q,ƙ#\g ْk̖:[uKWt l)%8UGW[߫JuV6TϻTUTӸuUG̾*귻 28^_uu1U1U.|'KH!ʋ,ozj^TS)I9gG=]k#|Du֩z5pru7(f?<-#e ՚zW߉EYE1m2oӳrgʸҚOv*VlS=YlP$!<.QM@OU>g6KPVlɬԷ>["vm0 ?>=Vhoٱnw!̰heK\@ҧKO<7z\Sgρ8mTR?7 mkޅ5mUۄPz?Sݩ|ϓCWY]]]]]]]]]]]]]]]]]]]m ]n_C{.[ THR#k0]bF>RˇZ~d @=xd~S0 @RvZA4-SO.a*U֠ $910v{Oȥo%9+f.@@AN3<0X~WT.o|p}0v}'~Tac1Zv^Lgu|K ?Gj1',UU_dTalL]~:C=CP4J`°Qݠ2 &nz&CDuJۻTa* ŧPe26T0}Q 'P D[Ne@:|*Ws|q]i rQZ#pcZ.俩H"?:xIpU[ 5ӈjLq SIPig*O{U׿W =[ `O7|Z|9% ):d+'Bl=EZnziՐlʺ^-0O+-\[|^Oi˷-oyoɾD%]dxg.z|f=>*8mq~_e2ɛ25]A5:"#Jyp>X=4+~"4VR?C0<.ޢj@tK/ٶM5zyDs7yKYFkݏAW%#Z$zjqkosEDB:HoiM39_,tt#Ύ޲6b=O;sG9Mu|qXO\ԍ|6yDG>G /"Pn?bO3v~1G{UT'W(|؃X+='Um*e`"N+U%JqDlߌ瓳T!>Syc%qoa/IB~ZxWJydFGj5fKlz+. bUoU͇ 9 Hqx˳Ϛ-}IW6H/J|ڜ ]^+kF]=}N 48E5r2ryVSe]oD/E8T3E &./g믿ַo|>ɭ?l2:cE0?EAkA쬣fsy??'u`D!h?*bƅQ,UmxO)zk{71LY&/7:rJt!PPC|39\YRea7r7ztyj}}sGy*{e]do}fX\3Uj{^`)z/7^V9.$`,LIu0SeM{xFydQ=JnߴJ&z Lot*&Yli%r*;ݢ)K5,U%{Lut)z|d?[QAF8g4vXQA5. {>LK9iDʥuG TngKȴg ") is յ[o&~ZS(DMʀ*i+ʔ`\; s敍eh+k!~ J.l s euIDATxb?@&322RĘ1`>f!4mP3TvbU Yhd`nO2jCb`Vb(ţӿE?:^G$$S`IENDB`GIF89a,Aڋ1q=`xpz33屯?ut%iɝPXD3Ԫj;GIF89a,$ڋ޼{ Hb&Ls;PNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<wIDATXŖ{PUj:VDQ:IiS6854MJ!M "7@4P,yInˮEV . + {ݥEL^><1lq KZS<:mgq w ^~N1S Y{qW2ݨ;bYП%J%P݋׭2D2c*D[OoSsܒ(]{ [.p~!Lp,c%̱9ow^ 0\\ G?!v8=j V~C9@UT\9.`1E&3P28`=n; XxBABNLB^HpOHj 6(b84H1oʢ+*&/Xv6:Ƣ)s]_,`4TVGo&_ 6 %Y]Ah!f"=5bp,8=\ScOИ`11b U G\þXBu%Aq5Sš.̩AL+Bjؚ۫{~E8M9GlEne'"UPf0[o #W {#ofP+"2JYS/_׉j7}ZH-@Hc25q2>R,y:4a u'Zw'),z+WPTݮY) Y_>[t܂/?uz)2ڐxDT U0N-kHJ`MST=߀ }(W4Wu*].źLO5+N\&(+ Մ!R¦>Gz$o29 Ppꚅ1r%\O,;m37l xЅtV܇fp٣P\KMEh`&VB#//k reYƶ>T]xBR(O˸uUYn%u)dG Gv^5Gv y =bc'%C]ۂGoaޔ(cy* )mnFӌiƚP9?c4Ӗr-IBu?Ks' OdX!=p0זoj?p)z%&֏00a{Mϰ/%9>/_IENDB` h(      OGIF89a,9X,L}I(d*2\%RbJ!QH3 B ; h(      !!!              PNG  IHDR;0tEXtSoftwareAdobe ImageReadyqe<diTXtXML:com.adobe.xmp TIDATxW] 0 ^& C`[{l{u-ڴn!K.p̲3TM+I^m[rUb3)GjGC!~JĦoɉK7[[AGq׆jczi$Xh3qXIafbt\feNMtfM"u>XyR1Ub !!PgKWi(qQsĵ%!Ֆr%I@}cٽ,>-IENDB`PNG  IHDR;0tEXtSoftwareAdobe ImageReadyqe<diTXtXML:com.adobe.xmp '5rIDATxڼJ@ ȩPBO>'oP PT]KWAxJB^^+82&qevgdv6^i匇hb֠GY 4mpS9^*AO*i1oʂ 45I%\N)W2/-O:=1\+OY+Ǣ&f6ŏH0憹DWgϲKخ̿7 $uطm00_TcP m|_J㴐'@x]:ϕ+y2K⹂Kb\+õy1p?fTC ri|&->}p!ZxTQYBpMYO\x`![ X{V>LG|9˥T!Lg#b { R/a }w]Zc(RqzG3KCU T u < a_<{*} yi.n#2w0B1지se|D5և ~d}q$p&=C`TOϗnwN+S^ cqD3Zӻpb744.6%4uHT!B/'d|NTYL D:"aqQ&k 5h&YMpV@Pb Be.cx7]`\Y N+ިE;k֕:ߟU@pr)G߆G[+|O)E#)$ E.,;)?:OyCN'@5CȠi8,/k^s$1seӜW7vJq$\-i@lkFܾ̒ķ=+\Tǥb'9#@N#d;͡wAZX|32Ьp+ -mX|t_ՒKB5 )i*8Dqo3{7:={)vuv o)&`y''%l<ϧ `)5IENDB`PNG  IHDR;0tEXtSoftwareAdobe ImageReadyqe<diTXtXML:com.adobe.xmp IDATxڼJ@ ȩPBO>'oP P]KWAxJB^^+8lvv82ٙ/;ٝ]UѲ,s C4@1_@#_J@[A[KUd]Г c`,盒0]F6iDT=[_0 fۀ%]c)8}vDS w)6sQ> u qh$s\OW瓈zkIy+ .{?/ xYIP6~+ɛմ_`s ex؃.Zs,l\L9mϱ\"Njc4(,~l%YȒ5/^ٔdCᵂ~#`|4]q0p=#{u]W YWyIENDB`GIF89a,>Aqy[|I(J)(^]Cax4!\Q;h(  888rr B4a)Ak(Bt-I{)Du.J}'D|*G.H'@n(?k4`.R+Ae7d(U#@u9m/M+J9X3T'G9Y8V6f+Cr"8c+Ak/U!8a9R0a'ENgJ`&Cw-Fx6P3\"C%8[)Ao$>k6S2S7\3U1S1M!9f8g/P.S%>l3MymwPX.M8ZsH[<]7YP^Y\'Ao(>g0U*L0Y7e0N9Vv *`.K$?p!9d)I/P2\2Kx8W7Xr{)7m3R8Q~(?g!2R/Q*?h8Q|0MNZ8S=V(?h&8X3V)Cl5Ox>[!3cUfp8U*Fq+Bi$6X0Cb5Ov=UOiFd1@jC`Ok9Qy*Em+?]1Ea6QuD_=X~iLkMkMkIk`|GbA[>X8Lh(?a>UvEbHaQnztId;V|Li>Uv4IjF[}KdJdNjLgUsRm;a:aQmHiPkLfCZ~JdBUw.D]ToRnLgOmSm[x[xNm\yPlKeNg?Vv/#%*0KcG[IdGaD\PgOgNgG`LeJcF\#&+1PNG  IHDRHHUGsRGBbKGD pHYs  tIME &[ IDATxdy%U}YcU3C7 Q@DA@gDBfrFɍQsohLH0I'EP "BMj>>z70젟7F_J)b()EL y[_ǟZ}th9rGf4i(DPJPZ66R T".gb&% YWhqMSjd!)QhM| %ubĈ1k*#LQ8OMZ ރ-ya;A]+SRʐRJZJY$wL_ 3ͯ30\۾d2!p)T9 @E&5~$@ƔPRS$@V2TE)Z\LQ|$61xTB"DP7 jMi-s@60WY"1fƭm B!)g$3Fi 2d F(ItsE+ rBK $h%PRsBhMPV`R D(ʂh$f-3(E4@*qӈ=[f9M@K>q;B !Fa7(mB7Od2JvwHkRsT1]hZ-H9R@K, wHYs6 LCʙ*=!$[Zr-5JI*R)&mCDFxK'mއ~ 9-O=u+rケmJ Ȉ J*j)#%kB13BrĐ0Z!B)H DN()DJ)R~YJ#-RRmIN$ZIxנ;Gi5Z )s1/J}hqS%RwsO ` %PG]JkbJ0Zc ڶ%#h"c $1cD -XL&HJ!@"' A.PRpPJ g)Մqsw 8ByF!Fkn^lvfx3LӄJH)QR"  $Z|;AAH)@ x961}/yݻ97 ߒ)'lc?_7&U#ʲGD D Mp A"@)$ r7w\)aB 5IҴјG\LY$׀Iv ̸nYyQ)7yY#{znFGPOY~tlޱ {"G|:Gx*v!9%]ŗÞoSND Pd1.0  cdSI2n>YktǷ ?_ +pkc^U0(K2ZRuad~v@LZJ|H1Vo~ 99b{C)T&Ye' l߁D?Wrǣ9'pSǒ"g9ބq:Rqv00hh T #LH1|mYQƐW-;!Bkn?o2Ul1 h'H YaJ{f|oKxs/?Ws !=9:|O^EٌEA9&#u['Dy1#c7+`.\qduh{}J6#B(LO-d2yW stf/}o_~yGVpgRLjRLR"Dx׶i[c akǞ brd~s_'- 5&B@M"֚" (I P%N&,N9B$'@!IM3Yxҟ0h&/;x_dn`>Ĥi!Bc@_otkي~ԕ4ȁ?Oqhq~ZƵG~ɨ4԰Y-7C:@H4H"M#%"'| D@@)~cu3ZH!3w΂N>9@K2-KPin\b U,k JcJSCi4(Ƭ'ޓõ-!<wGdCFuKʙQVm5qʉX\ZǃWxG9#І,TɄ#geyulOo~-"\z frL(2ZֆH*GRN4m> Ĕ8uI9!P#JRma,5o?; 7}8D=@ם4Y ɏ~C&qdb rWn5d{7mSBlB΄򬦍ƵV3ojn@ ( ЉgYYZ* \4ށ!!0iZ*R2s }YJR@gD:LTJsJ i['t!4-*1ni={t:@*:"y/}vT"{d abR)Ex cy*/{եq_KnZ1g=?췸.y,GQNoXF쾃;n2g>"|է7s{nga\ǯ\Crs=kslIϸ(J3 )D&Dž@B|Ke;N3N.|1_oykIg^{=OpK_o~zvzǝz4?2w3`Vb4k !}s -t-t^NLG">vAʉ``m'5Y!E")I̹9J*#ؓE(^۾'!#${6m}O:x?s?y ۏ_j~318&y''^%_$G O8_yeu.vlJ!o;և * zNx1l8 :q?eȂD"N{$b;h|Fwʿ2N1&QFa"&J[|՘:{Ik ~fJߺg(E [XcJQ%QF+Kƫvι0F|;)+CiBb _̖m :O;k![gq^!MZ[ lGcX|d|zVN{x\%q)8pwB#LjYN94+2FfzE9S!Oe*Ԥܙ~i.(eZȸqI{I" W#c#rcݷeo|;0w~//|<)OBJ+}K{7/JyغDr゗ ;zlnO˞X;Wz7W71=3epEh&+Aalj'1dqu.8Ў9S;O;(DΑ @ :Yp,C A7FHAΎӟ$>W#a)qv.ghMaN|y\+~OZ@23`ԓqK~a߃YVB z/,QXAzl^I-:B R2ZN QRQYFu.JAZeI!$>~ufs7R"#'u6v @͑f?~J ^7i r&H'=|((#2x cm(Z"DD YLHh[b)c ؑbY D/Jv[0mXOpށEa&Db&%jDyMs_?A dEUs;}/2'y#r79urvJ ?WlBFGD$L / cp&4xDLt)r֏RqbbB"EhЦLBN KAeN/s-,JTSX463#wϯ+|7UJn؇C\ku>9BaS@UdA=|33CیA$ :mo\[\?(Qƒ|DKE ]"ĀPk%:I%)Q I(Buϑ},;oYش@L3;'UՌ_b>g?Gwdu|?rhaw)?YAA!5Uۑs |Щs} A)2eUc OG9vyIy*ZDR\ $}kHD&ĄxO+(C"xLq PY9E/`ߏlu""˯A5ЌϸLg L..Җzx/C{A/sC:FuC:$%@EJmBYCk1MY)"%<.*WY?1޹aeoCnU(-q!Zɑt8ECn[Dj;+0cyl=D-ONэb"UX"0.2jyJMoB mo& QĔZTY^]cc4n) uZ°yu|hMm]FT%A56'P.қHo~+uџ)BB]Л,lUH&b7ppk>ϿUl4S.i[Yɦ?*8,T#9E 6_Pԙ7 , (2RDwsEɜVq0C: Q46PU~ppɗp^!KIRXHKH1".OSL2ҳ _7N@ !K^\EOoH kcBR䄋ih떐Xb0S.XݝKAY\]g=叺,񖍃CIDATgL PMD][ɼl߲|=|OWegEL ̐w`1t -ui3:3ֵꖵk4EB~<V93Pqdi @[3-hкv-c&:(UAe,"tdX7j`pٵPhU<*B*djL&5묯(Y)[Yby8.Fb-2z(ƎV%Jt1pҸCz< X_̧Uv5Kq"'뚞5L*cf23\_HZ|x(f2`u 1>IfNX-%ѵty _ ^dODZ껅 &2 ѵ 1UB<|N|%S/?Fvl%5YkFiNB-2~yzyvsܖ+ׇ6٪WX$&dBH"_TZ|0Y(n 5ǝy2!d_I^}bߞGmLU=-0Ҵ Z(4>xw_2lwPa& zZ("ƄHBeZE1iPNzW$]T9#Fk(%-KeLգMu6/8t9|`g>3y<شs3OyKyڙ^thC04Z|Lxر1Y_mfNxx^ ^6PXDc\K>y/1;gYYYa8 S@ T )MkW,%J5S3[koxiX7% 6 ] hI- "oE Kk6sޯ_Y<"f2׌V7xY;h(mdabqDZП/;7e:~}f$e4&C㽲N7ƍn=1g|ue$6(wXN]D'ŀ +(!)2?3%^JUuw?7̇ɜrI;P:xH&Qƚje%'AAdH<ZE}rRd[,8p ᐹ[iZZ'c(C3vkϳtm-R()A)|sוJuo^P@5 87h"k&;jژ Lf81RRUYdd0i[RJx6HH-pm CmK-X&{1Uŕ2ӦDLISsI "Rk\ yҸ<(xhqVa`({|5:L-дLQ`i&Q0OȺ{2ts4j)&BȘp!D:(&LRag!@j" {Rc$.x" ]' Ҳ6%%J*N)Y|ćX7wR/n_:jtUE̩;VU!zUEhk fiۖdvn%VftUU[GbA\?GB n{NDa ?mWS=s0)5#ijs;OBiR.)1 R^G?Q/lH3ǀfO;E_'9(z!%jβ1`1*-).(Fc;GQ&D@!8WNe%uHc-$YJ\E{GL6xԽaccDl~$(s;IoOw2+F{ .!0lt.v r*Tイ I{ӍR0mV5bHqk%fJ|PTsEm 7!Zj{Vj]/֎( Τn[UT v[YqжxP=5z0xz! | *z*@SPwyUrhZfy89,)Ke ,'B DD ƨ8X-N/psx |Ϋ@G[/|3 ԴPfNx&h;piSiK0RjH$|Ϣ:vJS,R( E;G {O. rޭw߿ È+@LJ;Lyd3YsE)se?E.m2Ꜫn 6jܿw[6p‡'xʗM3S;;SÆn|+7|7_Ya7`Z}6lj܁mg g Wjȡa(A! ,\\h0I8ͻ`(8hCIp,s,U|PhO:a#.\6è47VXvz}lLF@is%_zN`y{s~mpjdga[^XR_r|kuve]yLPn;OGVFJNSY-t.17Ák0 \0Zb;YdWō c=ܘ.䭏MA Q% ]I84kޤkH A t M=tիXj ׯ`Êݺ@ٳ_X˶۷n;Vܻxʥ˷ڼKoD5 Ἁ-f<㻑 N|巙n\g&d@ӘS~ڬgzegtP4n 6"j6򓣗7?|et?Wywg*_8K[nk?~uY~ٷ A5P/~_k!VM[ `T݀iY (S ! ,\\h0I8ͻ`(di%lVE,ϴL8=<0UaMId6:#PʴYv>2ꍁѫqS=?te~lm}p|^hAfXwxkmnvDu8{aK~(H$ײW3T_ݴHM>YHp"C],~)Hlɖ^œI͛8ɳϟ@sJH*]tiP*hJ*jʵVQm'-O}'e7PxlX~ `di=%N9eF! ,\\h0I8ͻ`(diYl+l[=sӕ'\"l42ISyFSdl?0歹xpWjsdn9sl:oun=kztv|{r2xC@~-) ºǾ̹̩ҨɧpG` COa=Nb:,8O_@{ZӸc;yeJ&Lh59xY}*t(ϢH*]Z,ӧPJʴԫX6ׯ`J*h>۷p@(K7ִxܺdͻa>;Ç**1J,e3z֜tgƨA^=kӰcn@ۯZs7ۧu}uW7/ut9W|=s-w]q#~~pzw̻u}?]+jfb}_eb&(V*>UՆvᇲ$! ,\\h0I8ͻ`xudhi+p γWpHC:NrijFkB: x꒬B6=5su~@9]5yb|}p{x}ZztWQOlwsejuRn;ƾ ͬ50*ڽSo :0&h0D :)te1= Kkɓ+42̕(IXC9[|ϋE;x/KMA<*b*իXjʵWŠKد̪]`۷pm]m߿N{p޽B̘1v'۷e!<˖3k.˹3ʠGցiʟS מV ҸQK7‡(^Ùvn飩O.f퉹x9^2Ha$K<ʕ:ztR KQ4k*N|JKK24cʥHUL|ȩ%^ R!X#úS8ʝKݻx˷ L +6ǐ#Gfƒ3Kue˘5&٩ϋC\ԩ!i؅Uφ\kܹe,ou']q䁕9t黩lA|Qɏ64—?f/=lv>z|4E`}VAП8~هAQH? ؇ ($h] ! ,\\h0I8ͻ`&di蹀l9B,t-7i0PM:o4\OgqZ[,1*-h`c%8xN/9pzj}1m%L|4Ty}ztwqknhbe_Y\VOSKuHP<Ǎ ʐvͿJCRiGWF.~ ͊"/{ H*\XpÇ#Jċ+FBIR$?\I$J*Yt2F3'ԼgI;!9hPC4z4RASO5RkN G#zeؕeSTZTgXk.ub\i9IdžuLÈ+^̸ǐ#K쀀˘3g\Ag -@Ϩ-Mi S;ؠ%n]6ͺ{~ S_-nϿJh*lX^;p,Y\WmRo-%9ٰ#E`…;Na1ǐ#KL˘3kPϠ=SMҨ-N=auӮMW6ζo-5oܾwnÍ׽ǖ:9s У78vW[w{㹗Wgy_wg<0~푗iWz֠l — ~6ev ( $;
    »
    Responsive ========== `Responsive` is a responsive, frameless template making use of progressive enhancement to change the way you look at API Documentation. Enough buzzwords? We might not be done yet! TODO ---- * Add function contents * Add constant contents * Hide packages if there are no documentable elements that have that package * Give each package/namespace a generated diagram showing local elements. * Introduce a switch or tabs to generate documentation using the short descriptions instead of the actual names * Improve search to do a site wide search * Long class names fall of the grid; tried fixing this with elipsis but it won't do the job as elegantly * Add sourcecode view * Improve this README by giving a better introduction and describing all options * Improve the glass graph to have a nice viewer * Make template more friendly for extendability/* ### jQuery XML to JSON Plugin v1.3 - 2013-02-18 ### * http://www.fyneworks.com/ - diego@fyneworks.com * Licensed under http://en.wikipedia.org/wiki/MIT_License ### Website: http://www.fyneworks.com/jquery/xml-to-json/ *//* # INSPIRED BY: http://www.terracoder.com/ AND: http://www.thomasfrank.se/xml_to_json.html AND: http://www.kawa.net/works/js/xml/objtree-e.html *//* This simple script converts XML (document of code) into a JSON object. It is the combination of 2 'xml to json' great parsers (see below) which allows for both 'simple' and 'extended' parsing modes. */ // Avoid collisions ;if(window.jQuery) (function($){ // Add function to jQuery namespace $.extend({ // converts xml documents and xml text to json object xml2json: function(xml, extended) { if(!xml) return {}; // quick fail //### PARSER LIBRARY // Core function function parseXML(node, simple){ if(!node) return null; var txt = '', obj = null, att = null; var nt = node.nodeType, nn = jsVar(node.localName || node.nodeName); var nv = node.text || node.nodeValue || ''; /*DBG*/ //if(window.console) console.log(['x2j',nn,nt,nv.length+' bytes']); if(node.childNodes){ if(node.childNodes.length>0){ /*DBG*/ //if(window.console) console.log(['x2j',nn,'CHILDREN',node.childNodes]); $.each(node.childNodes, function(n,cn){ var cnt = cn.nodeType, cnn = jsVar(cn.localName || cn.nodeName); var cnv = cn.text || cn.nodeValue || ''; /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>a',cnn,cnt,cnv]); if(cnt == 8){ /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>b',cnn,'COMMENT (ignore)']); return; // ignore comment node } else if(cnt == 3 || cnt == 4 || !cnn){ // ignore white-space in between tags if(cnv.match(/^\s+$/)){ /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>c',cnn,'WHITE-SPACE (ignore)']); return; }; /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>d',cnn,'TEXT']); txt += cnv.replace(/^\s+/,'').replace(/\s+$/,''); // make sure we ditch trailing spaces from markup } else{ /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>e',cnn,'OBJECT']); obj = obj || {}; if(obj[cnn]){ /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>f',cnn,'ARRAY']); // http://forum.jquery.com/topic/jquery-jquery-xml2json-problems-when-siblings-of-the-same-tagname-only-have-a-textnode-as-a-child if(!obj[cnn].length) obj[cnn] = myArr(obj[cnn]); obj[cnn] = myArr(obj[cnn]); obj[cnn][ obj[cnn].length ] = parseXML(cn, true/* simple */); obj[cnn].length = obj[cnn].length; } else{ /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>g',cnn,'dig deeper...']); obj[cnn] = parseXML(cn); }; }; }); };//node.childNodes.length>0 };//node.childNodes if(node.attributes){ if(node.attributes.length>0){ /*DBG*/ //if(window.console) console.log(['x2j',nn,'ATTRIBUTES',node.attributes]) att = {}; obj = obj || {}; $.each(node.attributes, function(a,at){ var atn = jsVar(at.name), atv = at.value; att[atn] = atv; if(obj[atn]){ /*DBG*/ //if(window.console) console.log(['x2j',nn,'attr>',atn,'ARRAY']); // http://forum.jquery.com/topic/jquery-jquery-xml2json-problems-when-siblings-of-the-same-tagname-only-have-a-textnode-as-a-child //if(!obj[atn].length) obj[atn] = myArr(obj[atn]);//[ obj[ atn ] ]; obj[cnn] = myArr(obj[cnn]); obj[atn][ obj[atn].length ] = atv; obj[atn].length = obj[atn].length; } else{ /*DBG*/ //if(window.console) console.log(['x2j',nn,'attr>',atn,'TEXT']); obj[atn] = atv; }; }); //obj['attributes'] = att; };//node.attributes.length>0 };//node.attributes if(obj){ obj = $.extend( (txt!='' ? new String(txt) : {}),/* {text:txt},*/ obj || {}/*, att || {}*/); //txt = (obj.text) ? (typeof(obj.text)=='object' ? obj.text : [obj.text || '']).concat([txt]) : txt; txt = (obj.text) ? ([obj.text || '']).concat([txt]) : txt; if(txt) obj.text = txt; txt = ''; }; var out = obj || txt; //console.log([extended, simple, out]); if(extended){ if(txt) out = {};//new String(out); txt = out.text || txt || ''; if(txt) out.text = txt; if(!simple) out = myArr(out); }; return out; };// parseXML // Core Function End // Utility functions var jsVar = function(s){ return String(s || '').replace(/-/g,"_"); }; // NEW isNum function: 01/09/2010 // Thanks to Emile Grau, GigaTecnologies S.L., www.gigatransfer.com, www.mygigamail.com function isNum(s){ // based on utility function isNum from xml2json plugin (http://www.fyneworks.com/ - diego@fyneworks.com) // few bugs corrected from original function : // - syntax error : regexp.test(string) instead of string.test(reg) // - regexp modified to accept comma as decimal mark (latin syntax : 25,24 ) // - regexp modified to reject if no number before decimal mark : ".7" is not accepted // - string is "trimmed", allowing to accept space at the beginning and end of string var regexp=/^((-)?([0-9]+)(([\.\,]{0,1})([0-9]+))?$)/ return (typeof s == "number") || regexp.test(String((s && typeof s == "string") ? jQuery.trim(s) : '')); }; // OLD isNum function: (for reference only) //var isNum = function(s){ return (typeof s == "number") || String((s && typeof s == "string") ? s : '').test(/^((-)?([0-9]*)((\.{0,1})([0-9]+))?$)/); }; var myArr = function(o){ // http://forum.jquery.com/topic/jquery-jquery-xml2json-problems-when-siblings-of-the-same-tagname-only-have-a-textnode-as-a-child //if(!o.length) o = [ o ]; o.length=o.length; if(!$.isArray(o)) o = [ o ]; o.length=o.length; // here is where you can attach additional functionality, such as searching and sorting... return o; }; // Utility functions End //### PARSER LIBRARY END // Convert plain text to xml if(typeof xml=='string') xml = $.text2xml(xml); // Quick fail if not xml (or if this is a node) if(!xml.nodeType) return; if(xml.nodeType == 3 || xml.nodeType == 4) return xml.nodeValue; // Find xml root node var root = (xml.nodeType == 9) ? xml.documentElement : xml; // Convert xml to json var out = parseXML(root, true /* simple */); // Clean-up memory xml = null; root = null; // Send output return out; }, // Convert text to XML DOM text2xml: function(str) { // NOTE: I'd like to use jQuery for this, but jQuery makes all tags uppercase //return $(xml)[0]; /* prior to jquery 1.9 */ /* var out; try{ var xml = ((!$.support.opacity && !$.support.style))?new ActiveXObject("Microsoft.XMLDOM"):new DOMParser(); xml.async = false; }catch(e){ throw new Error("XML Parser could not be instantiated") }; try{ if((!$.support.opacity && !$.support.style)) out = (xml.loadXML(str))?xml:false; else out = xml.parseFromString(str, "text/xml"); }catch(e){ throw new Error("Error parsing XML string") }; return out; */ /* jquery 1.9+ */ return $.parseXML(str); } }); // extend $ })(jQuery); !function(a){a(function(){"use strict",a.support.transition=function(){var b=document.body||document.documentElement,c=b.style,d=c.transition!==undefined||c.WebkitTransition!==undefined||c.MozTransition!==undefined||c.MsTransition!==undefined||c.OTransition!==undefined;return d&&{end:function(){var b="TransitionEnd";return a.browser.webkit?b="webkitTransitionEnd":a.browser.mozilla?b="transitionend":a.browser.opera&&(b="oTransitionEnd"),b}()}}()})}(window.jQuery),!function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype={constructor:c,close:function(b){function f(){e.remove(),e.trigger("closed")}var c=a(this),d=c.attr("data-target"),e;d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),e=a(d),e.trigger("close"),b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.on(a.support.transition.end,f):f()}},a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("alert");e||d.data("alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a(function(){a("body").on("click.alert.data-api",b,c.prototype.close)})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype={constructor:b,setState:function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a+="Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},toggle:function(){var a=this.$element.parent('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")}},a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a(function(){a("body").on("click.button.data-api","[data-toggle^=button]",function(b){a(b.target).button("toggle")})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.carousel.defaults,c),this.options.slide&&this.slide(this.options.slide)};b.prototype={cycle:function(){return this.interval=setInterval(a.proxy(this.next,this),this.options.interval),this},to:function(b){var c=this.$element.find(".active"),d=c.parent().children(),e=d.index(c),f=this;if(b>d.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){f.to(b)}):e==b?this.pause().cycle():this.slide(b>e?"next":"prev",a(d[b]))},pause:function(){return clearInterval(this.interval),this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(b,c){var d=this.$element.find(".active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this;return this.sliding=!0,f&&this.pause(),e=e.length?e:this.$element.find(".item")[h](),!a.support.transition&&this.$element.hasClass("slide")?(this.$element.trigger("slide"),d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")):(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),this.$element.trigger("slide"),this.$element.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)})),f&&this.cycle(),this}},a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("carousel"),f=typeof c=="object"&&c;e||d.data("carousel",e=new b(this,f)),typeof c=="number"?e.to(c):typeof c=="string"||(c=f.slide)?e[c]():e.cycle()})},a.fn.carousel.defaults={interval:5e3},a.fn.carousel.Constructor=b,a(function(){a("body").on("click.carousel.data-api","[data-slide]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=!e.data("modal")&&a.extend({},e.data(),c.data());e.carousel(f),b.preventDefault()})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.collapse.defaults,c),this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.prototype={constructor:b,dimension:function(){var a=this.$element.hasClass("width");return a?"width":"height"},show:function(){var b=this.dimension(),c=a.camelCase(["scroll",b].join("-")),d=this.$parent&&this.$parent.find(".in"),e;d&&d.length&&(e=d.data("collapse"),d.collapse("hide"),e||d.data("collapse",null)),this.$element[b](0),this.transition("addClass","show","shown"),this.$element[b](this.$element[0][c])},hide:function(){var a=this.dimension();this.reset(this.$element[a]()),this.transition("removeClass","hide","hidden"),this.$element[a](0)},reset:function(a){var b=this.dimension();this.$element.removeClass("collapse")[b](a||"auto")[0].offsetWidth,this.$element.addClass("collapse")},transition:function(b,c,d){var e=this,f=function(){c=="show"&&e.reset(),e.$element.trigger(d)};this.$element.trigger(c)[b]("in"),a.support.transition&&this.$element.hasClass("collapse")?this.$element.one(a.support.transition.end,f):f()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("collapse"),f=typeof c=="object"&&c;e||d.data("collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.defaults={toggle:!0},a.fn.collapse.Constructor=b,a(function(){a("body").on("click.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e).data("collapse")?"toggle":c.data();a(e).collapse(f)})})}(window.jQuery),!function(a){function d(){a(b).parent().removeClass("open")}"use strict";var b='[data-toggle="dropdown"]',c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),e=c.attr("data-target"),f,g;return e||(e=c.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,"")),f=a(e),f.length||(f=c.parent()),g=f.hasClass("open"),d(),!g&&f.toggleClass("open"),!1}},a.fn.dropdown=function(b){return this.each(function(){var d=a(this),e=d.data("dropdown");e||d.data("dropdown",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.dropdown.Constructor=c,a(function(){a("html").on("click.dropdown.data-api",d),a("body").on("click.dropdown.data-api",b,c.prototype.toggle)})}(window.jQuery),!function(a){function c(){var b=this,c=setTimeout(function(){b.$element.off(a.support.transition.end),d.call(b)},500);this.$element.one(a.support.transition.end,function(){clearTimeout(c),d.call(b)})}function d(a){this.$element.hide().trigger("hidden"),e.call(this)}function e(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('');this.target.append(az);az.height(aD);az.width(aA);az.css("top",this.eventCanvas._offsets.top);az.css("left",this.eventCanvas._offsets.left);var aC=L('
    ');az.append(aC);aC.html(this.noDataIndicator.indicator);var aB=aC.height();var ax=aC.width();aC.height(aB);aC.width(ax);aC.css("top",(aD-aB)/2+"px")})}}this.data=L.extend(true,[],ar);this.parseOptions(ay);if(this.textColor){this.target.css("color",this.textColor)}if(this.fontFamily){this.target.css("font-family",this.fontFamily)}if(this.fontSize){this.target.css("font-size",this.fontSize)}this.title.init();this.legend.init();this._sumy=0;this._sumx=0;this.computePlotData();for(var at=0;at0){for(var aq=au;aq--;){var an=this._plotData[aq][ap][av];if(aw*an>=0){this._plotData[au][ap][av]+=an;this._stackData[au][ap][av]+=an;break}}}}}else{for(var ar=0;ar0){at._prevPlotData=this.series[au-1]._plotData}at._sumy=0;at._sumx=0;for(ar=at.data.length-1;ar>-1;ar--){at._sumy+=at.data[ar][1];at._sumx+=at.data[ar][0]}}};this.populatePlotData=function(au,av){this._plotData=[];this._stackData=[];au._stackData=[];au._plotData=[];var ay={x:[],y:[]};if(this.stackSeries&&!au.disableStack){au._stack=true;var ax=(au._stackAxis==="x")?0:1;var az=L.extend(true,[],au.data);var aA=L.extend(true,[],au.data);var an,am,ao,aw,al;for(var ar=0;ar=0){aA[aq][ax]+=aw}}}for(var at=0;at0){au._prevPlotData=this.series[av-1]._plotData}au._sumy=0;au._sumx=0;for(at=au.data.length-1;at>-1;at--){au._sumy+=au.data[at][1];au._sumx+=au.data[at][0]}};this.getNextSeriesColor=(function(am){var al=0;var an=am.seriesColors;return function(){if(al=0&&an>=0){al.top+=aK;al.bottom+=aK;al.left+=an;al.right+=an}}var am=["top","bottom","left","right"];for(var aB in am){if(this._gridPadding[am[aB]]==null&&al[am[aB]]>0){this._gridPadding[am[aB]]=al[am[aB]]}else{if(this._gridPadding[am[aB]]==null){this._gridPadding[am[aB]]=this._defaultGridPadding[am[aB]]}}}var aA=this._gridPadding;if(this.legend.placement==="outsideGrid"){aA={top:this.title.getHeight(),left:0,right:0,bottom:0};if(this.legend.location==="s"){aA.left=this._gridPadding.left;aA.right=this._gridPadding.right}}ar.xaxis.pack({position:"absolute",bottom:this._gridPadding.bottom-ar.xaxis.getHeight(),left:0,width:this._width},{min:this._gridPadding.left,max:this._width-this._gridPadding.right});ar.yaxis.pack({position:"absolute",top:0,left:this._gridPadding.left-ar.yaxis.getWidth(),height:this._height},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top});ar.x2axis.pack({position:"absolute",top:this._gridPadding.top-ar.x2axis.getHeight(),left:0,width:this._width},{min:this._gridPadding.left,max:this._width-this._gridPadding.right});for(aH=8;aH>0;aH--){ar[aG[aH-1]].pack({position:"absolute",top:0,right:this._gridPadding.right-az[aH-1]},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top})}var au=(this._width-this._gridPadding.left-this._gridPadding.right)/2+this._gridPadding.left-ar.yMidAxis.getWidth()/2;ar.yMidAxis.pack({position:"absolute",top:0,left:au,zIndex:9,textAlign:"center"},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top});this.target.append(this.grid.createElement(this._gridPadding,this));this.grid.draw();var aq=this.series;var aJ=aq.length;for(aH=0,aE=aJ;aHax)?av:ax;var ar=this.series[aw];var aq=this.series[au];if(aq.renderer.smooth){var ap=aq.renderer._smoothedData.slice(0).reverse()}else{var ap=aq.gridData.slice(0).reverse()}if(ar.renderer.smooth){var at=ar.renderer._smoothedData.concat(ap)}else{var at=ar.gridData.concat(ap)}var ao=(an.color!==null)?an.color:this.series[ax].fillColor;var ay=(an.baseSeries!==null)?an.baseSeries:aw;var am=this.series[ay].renderer.shapeRenderer;var al={fillStyle:ao,fill:true,closePath:true};am.draw(ar.shadowCanvas._ctx,at,al)};this.bindCustomEvents=function(){this.eventCanvas._elem.bind("click",{plot:this},this.onClick);this.eventCanvas._elem.bind("dblclick",{plot:this},this.onDblClick);this.eventCanvas._elem.bind("mousedown",{plot:this},this.onMouseDown);this.eventCanvas._elem.bind("mousemove",{plot:this},this.onMouseMove);this.eventCanvas._elem.bind("mouseenter",{plot:this},this.onMouseEnter);this.eventCanvas._elem.bind("mouseleave",{plot:this},this.onMouseLeave);if(this.captureRightClick){this.eventCanvas._elem.bind("mouseup",{plot:this},this.onRightClick);this.eventCanvas._elem.get(0).oncontextmenu=function(){return false}}else{this.eventCanvas._elem.bind("mouseup",{plot:this},this.onMouseUp)}};function ai(av){var au=av.data.plot;var ap=au.eventCanvas._elem.offset();var at={x:av.pageX-ap.left,y:av.pageY-ap.top};var aq={xaxis:null,yaxis:null,x2axis:null,y2axis:null,y3axis:null,y4axis:null,y5axis:null,y6axis:null,y7axis:null,y8axis:null,y9axis:null,yMidAxis:null};var ar=["xaxis","yaxis","x2axis","y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis","yMidAxis"];var al=au.axes;var am,ao;for(am=11;am>0;am--){ao=ar[am-1];if(al[ao].show){aq[ao]=al[ao].series_p2u(at[ao.charAt(0)])}}return{offsets:ap,gridPos:at,dataPos:aq}}function ak(al,am){var aq=am.series;var aW,aU,aT,aO,aP,aJ,aI,aw,au,az,aA,aK;var aS,aX,aQ,ar,aH,aM,aV;var an,aN;for(aT=am.seriesStack.length-1;aT>=0;aT--){aW=am.seriesStack[aT];aO=aq[aW];aV=aO._highlightThreshold;switch(aO.renderer.constructor){case L.jqplot.BarRenderer:aJ=al.x;aI=al.y;for(aU=0;aUaH[0][0]&&aJaH[2][1]&&aIaH[0][0]+aV[0][0]&&aJaH[2][1]&&aI0&&-aI>=0){aw=2*Math.PI-Math.atan(-aI/aJ)}else{if(aJ>0&&-aI<0){aw=-Math.atan(-aI/aJ)}else{if(aJ<0){aw=Math.PI-Math.atan(-aI/aJ)}else{if(aJ==0&&-aI>0){aw=3*Math.PI/2}else{if(aJ==0&&-aI<0){aw=Math.PI/2}else{if(aJ==0&&aI==0){aw=0}}}}}}if(az){aw-=az;if(aw<0){aw+=2*Math.PI}else{if(aw>2*Math.PI){aw-=2*Math.PI}}}au=aO.sliceMargin/180*Math.PI;if(aPaO._innerRadius){for(aU=0;aU0)?aO.gridData[aU-1][1]+au:au;aK=aO.gridData[aU][1];if(aw>aA&&aw0&&-aI>=0){aw=2*Math.PI-Math.atan(-aI/aJ)}else{if(aJ>0&&-aI<0){aw=-Math.atan(-aI/aJ)}else{if(aJ<0){aw=Math.PI-Math.atan(-aI/aJ)}else{if(aJ==0&&-aI>0){aw=3*Math.PI/2}else{if(aJ==0&&-aI<0){aw=Math.PI/2}else{if(aJ==0&&aI==0){aw=0}}}}}}if(az){aw-=az;if(aw<0){aw+=2*Math.PI}else{if(aw>2*Math.PI){aw-=2*Math.PI}}}au=aO.sliceMargin/180*Math.PI;if(aP0)?aO.gridData[aU-1][1]+au:au;aK=aO.gridData[aU][1];if(aw>aA&&aw=ay[0][1]&&aI<=ay[3][1]&&aJ>=at[0]&&aJ<=aE[0]){return{seriesIndex:aO.index,pointIndex:aU,gridData:null,data:aO.data[aU]}}}break;case L.jqplot.LineRenderer:aJ=al.x;aI=al.y;aP=aO.renderer;if(aO.show){if((aO.fill||(aO.renderer.bands.show&&aO.renderer.bands.fill))&&(!am.plugins.highlighter||!am.plugins.highlighter.show)){var ax=false;if(aJ>aO._boundingBox[0][0]&&aJaO._boundingBox[1][1]&&aI=aI||aB[1]=aI){if(aC[0]+(aI-aC[1])/(aB[1]-aC[1])*(aB[0]-aC[0])0)?aN:0;for(var aU=0;aU=aQ[0]-aP._bodyWidth/2&&aJ<=aQ[0]+aP._bodyWidth/2&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{if(!aP.hlc){var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][1])&&aI<=av(aO.data[aU][2])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}else{if(aQ[0]!=null&&aQ[1]!=null){aX=Math.sqrt((aJ-aQ[0])*(aJ-aQ[0])+(aI-aQ[1])*(aI-aQ[1]));if(aX<=an&&(aX<=aS||aS==null)){aS=aX;return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}}}break;default:aJ=al.x;aI=al.y;aP=aO.renderer;if(aO.show){aN=aO.markerRenderer.size/2+aO.neighborThreshold;an=(aN>0)?aN:0;for(var aU=0;aU=aQ[0]-aP._bodyWidth/2&&aJ<=aQ[0]+aP._bodyWidth/2&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{if(!aP.hlc){var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][1])&&aI<=av(aO.data[aU][2])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}else{aX=Math.sqrt((aJ-aQ[0])*(aJ-aQ[0])+(aI-aQ[1])*(aI-aQ[1]));if(aX<=an&&(aX<=aS||aS==null)){aS=aX;return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}break}}return null}this.onClick=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotClick");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onDblClick=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotDblClick");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onMouseDown=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotMouseDown");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onMouseUp=function(an){var am=ai(an);var al=L.Event("jqplotMouseUp");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,null,an.data.plot])};this.onRightClick=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);if(ap.captureRightClick){if(an.which==3){var al=L.Event("jqplotRightClick");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])}else{var al=L.Event("jqplotMouseUp");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])}}};this.onMouseMove=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotMouseMove");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onMouseEnter=function(an){var am=ai(an);var ao=an.data.plot;var al=L.Event("jqplotMouseEnter");al.pageX=an.pageX;al.pageY=an.pageY;al.relatedTarget=an.relatedTarget;L(this).trigger(al,[am.gridPos,am.dataPos,null,ao])};this.onMouseLeave=function(an){var am=ai(an);var ao=an.data.plot;var al=L.Event("jqplotMouseLeave");al.pageX=an.pageX;al.pageY=an.pageY;al.relatedTarget=an.relatedTarget;L(this).trigger(al,[am.gridPos,am.dataPos,null,ao])};this.drawSeries=function(an,al){var ap,ao,am;al=(typeof(an)==="number"&&al==null)?an:al;an=(typeof(an)==="object")?an:{};if(al!=u){ao=this.series[al];am=ao.shadowCanvas._ctx;am.clearRect(0,0,am.canvas.width,am.canvas.height);ao.drawShadow(am,an,this);am=ao.canvas._ctx;am.clearRect(0,0,am.canvas.width,am.canvas.height);ao.draw(am,an,this);if(ao.renderer.constructor==L.jqplot.BezierCurveRenderer){if(al660)?ah[aj]*0.85:0.73*ah[aj]+90;ah[aj]=parseInt(ah[aj],10);(ah[aj]>255)?255:ah[aj]}ah[3]=0.3+0.35*al[3];ak.push("rgba("+ah[0]+","+ah[1]+","+ah[2]+","+ah[3]+")")}}else{var al=L.jqplot.getColorComponents(ai);var ah=[al[0],al[1],al[2]];var an=ah[0]+ah[1]+ah[2];for(var aj=0;aj<3;aj++){ah[aj]=(an>660)?ah[aj]*0.85:0.73*ah[aj]+90;ah[aj]=parseInt(ah[aj],10);(ah[aj]>255)?255:ah[aj]}ah[3]=0.3+0.35*al[3];ak="rgba("+ah[0]+","+ah[1]+","+ah[2]+","+ah[3]+")"}return ak};L.jqplot.ColorGenerator=function(ai){ai=ai||L.jqplot.config.defaultColors;var ah=0;this.next=function(){if(ah0){return ai[ah--]}else{ah=ai.length-1;return ai[ah]}};this.get=function(ak){var aj=ak-ai.length*Math.floor(ak/ai.length);return ai[aj]};this.setColors=function(aj){ai=aj};this.reset=function(){ah=0};this.getIndex=function(){return ah};this.setIndex=function(aj){ah=aj}};L.jqplot.hex2rgb=function(aj,ah){aj=aj.replace("#","");if(aj.length==3){aj=aj.charAt(0)+aj.charAt(0)+aj.charAt(1)+aj.charAt(1)+aj.charAt(2)+aj.charAt(2)}var ai;ai="rgba("+parseInt(aj.slice(0,2),16)+", "+parseInt(aj.slice(2,4),16)+", "+parseInt(aj.slice(4,6),16);if(ah){ai+=", "+ah}ai+=")";return ai};L.jqplot.rgb2hex=function(am){var aj=/rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *(?:, *[0-9.]*)?\)/;var ah=am.match(aj);var al="#";for(var ak=1;ak<4;ak++){var ai;if(ah[ak].search(/%/)!=-1){ai=parseInt(255*ah[ak]/100,10).toString(16);if(ai.length==1){ai="0"+ai}}else{ai=parseInt(ah[ak],10).toString(16);if(ai.length==1){ai="0"+ai}}al+=ai}return al};L.jqplot.normalize2rgb=function(ai,ah){if(ai.search(/^ *rgba?\(/)!=-1){return ai}else{if(ai.search(/^ *#?[0-9a-fA-F]?[0-9a-fA-F]/)!=-1){return L.jqplot.hex2rgb(ai,ah)}else{throw new Error("Invalid color spec")}}};L.jqplot.getColorComponents=function(am){am=L.jqplot.colorKeywordMap[am]||am;var ak=L.jqplot.normalize2rgb(am);var aj=/rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *,? *([0-9.]* *)?\)/;var ah=ak.match(aj);var ai=[];for(var al=1;al<4;al++){if(ah[al].search(/%/)!=-1){ai[al-1]=parseInt(255*ah[al]/100,10)}else{ai[al-1]=parseInt(ah[al],10)}}ai[3]=parseFloat(ah[4])?parseFloat(ah[4]):1;return ai};L.jqplot.colorKeywordMap={aliceblue:"rgb(240, 248, 255)",antiquewhite:"rgb(250, 235, 215)",aqua:"rgb( 0, 255, 255)",aquamarine:"rgb(127, 255, 212)",azure:"rgb(240, 255, 255)",beige:"rgb(245, 245, 220)",bisque:"rgb(255, 228, 196)",black:"rgb( 0, 0, 0)",blanchedalmond:"rgb(255, 235, 205)",blue:"rgb( 0, 0, 255)",blueviolet:"rgb(138, 43, 226)",brown:"rgb(165, 42, 42)",burlywood:"rgb(222, 184, 135)",cadetblue:"rgb( 95, 158, 160)",chartreuse:"rgb(127, 255, 0)",chocolate:"rgb(210, 105, 30)",coral:"rgb(255, 127, 80)",cornflowerblue:"rgb(100, 149, 237)",cornsilk:"rgb(255, 248, 220)",crimson:"rgb(220, 20, 60)",cyan:"rgb( 0, 255, 255)",darkblue:"rgb( 0, 0, 139)",darkcyan:"rgb( 0, 139, 139)",darkgoldenrod:"rgb(184, 134, 11)",darkgray:"rgb(169, 169, 169)",darkgreen:"rgb( 0, 100, 0)",darkgrey:"rgb(169, 169, 169)",darkkhaki:"rgb(189, 183, 107)",darkmagenta:"rgb(139, 0, 139)",darkolivegreen:"rgb( 85, 107, 47)",darkorange:"rgb(255, 140, 0)",darkorchid:"rgb(153, 50, 204)",darkred:"rgb(139, 0, 0)",darksalmon:"rgb(233, 150, 122)",darkseagreen:"rgb(143, 188, 143)",darkslateblue:"rgb( 72, 61, 139)",darkslategray:"rgb( 47, 79, 79)",darkslategrey:"rgb( 47, 79, 79)",darkturquoise:"rgb( 0, 206, 209)",darkviolet:"rgb(148, 0, 211)",deeppink:"rgb(255, 20, 147)",deepskyblue:"rgb( 0, 191, 255)",dimgray:"rgb(105, 105, 105)",dimgrey:"rgb(105, 105, 105)",dodgerblue:"rgb( 30, 144, 255)",firebrick:"rgb(178, 34, 34)",floralwhite:"rgb(255, 250, 240)",forestgreen:"rgb( 34, 139, 34)",fuchsia:"rgb(255, 0, 255)",gainsboro:"rgb(220, 220, 220)",ghostwhite:"rgb(248, 248, 255)",gold:"rgb(255, 215, 0)",goldenrod:"rgb(218, 165, 32)",gray:"rgb(128, 128, 128)",grey:"rgb(128, 128, 128)",green:"rgb( 0, 128, 0)",greenyellow:"rgb(173, 255, 47)",honeydew:"rgb(240, 255, 240)",hotpink:"rgb(255, 105, 180)",indianred:"rgb(205, 92, 92)",indigo:"rgb( 75, 0, 130)",ivory:"rgb(255, 255, 240)",khaki:"rgb(240, 230, 140)",lavender:"rgb(230, 230, 250)",lavenderblush:"rgb(255, 240, 245)",lawngreen:"rgb(124, 252, 0)",lemonchiffon:"rgb(255, 250, 205)",lightblue:"rgb(173, 216, 230)",lightcoral:"rgb(240, 128, 128)",lightcyan:"rgb(224, 255, 255)",lightgoldenrodyellow:"rgb(250, 250, 210)",lightgray:"rgb(211, 211, 211)",lightgreen:"rgb(144, 238, 144)",lightgrey:"rgb(211, 211, 211)",lightpink:"rgb(255, 182, 193)",lightsalmon:"rgb(255, 160, 122)",lightseagreen:"rgb( 32, 178, 170)",lightskyblue:"rgb(135, 206, 250)",lightslategray:"rgb(119, 136, 153)",lightslategrey:"rgb(119, 136, 153)",lightsteelblue:"rgb(176, 196, 222)",lightyellow:"rgb(255, 255, 224)",lime:"rgb( 0, 255, 0)",limegreen:"rgb( 50, 205, 50)",linen:"rgb(250, 240, 230)",magenta:"rgb(255, 0, 255)",maroon:"rgb(128, 0, 0)",mediumaquamarine:"rgb(102, 205, 170)",mediumblue:"rgb( 0, 0, 205)",mediumorchid:"rgb(186, 85, 211)",mediumpurple:"rgb(147, 112, 219)",mediumseagreen:"rgb( 60, 179, 113)",mediumslateblue:"rgb(123, 104, 238)",mediumspringgreen:"rgb( 0, 250, 154)",mediumturquoise:"rgb( 72, 209, 204)",mediumvioletred:"rgb(199, 21, 133)",midnightblue:"rgb( 25, 25, 112)",mintcream:"rgb(245, 255, 250)",mistyrose:"rgb(255, 228, 225)",moccasin:"rgb(255, 228, 181)",navajowhite:"rgb(255, 222, 173)",navy:"rgb( 0, 0, 128)",oldlace:"rgb(253, 245, 230)",olive:"rgb(128, 128, 0)",olivedrab:"rgb(107, 142, 35)",orange:"rgb(255, 165, 0)",orangered:"rgb(255, 69, 0)",orchid:"rgb(218, 112, 214)",palegoldenrod:"rgb(238, 232, 170)",palegreen:"rgb(152, 251, 152)",paleturquoise:"rgb(175, 238, 238)",palevioletred:"rgb(219, 112, 147)",papayawhip:"rgb(255, 239, 213)",peachpuff:"rgb(255, 218, 185)",peru:"rgb(205, 133, 63)",pink:"rgb(255, 192, 203)",plum:"rgb(221, 160, 221)",powderblue:"rgb(176, 224, 230)",purple:"rgb(128, 0, 128)",red:"rgb(255, 0, 0)",rosybrown:"rgb(188, 143, 143)",royalblue:"rgb( 65, 105, 225)",saddlebrown:"rgb(139, 69, 19)",salmon:"rgb(250, 128, 114)",sandybrown:"rgb(244, 164, 96)",seagreen:"rgb( 46, 139, 87)",seashell:"rgb(255, 245, 238)",sienna:"rgb(160, 82, 45)",silver:"rgb(192, 192, 192)",skyblue:"rgb(135, 206, 235)",slateblue:"rgb(106, 90, 205)",slategray:"rgb(112, 128, 144)",slategrey:"rgb(112, 128, 144)",snow:"rgb(255, 250, 250)",springgreen:"rgb( 0, 255, 127)",steelblue:"rgb( 70, 130, 180)",tan:"rgb(210, 180, 140)",teal:"rgb( 0, 128, 128)",thistle:"rgb(216, 191, 216)",tomato:"rgb(255, 99, 71)",turquoise:"rgb( 64, 224, 208)",violet:"rgb(238, 130, 238)",wheat:"rgb(245, 222, 179)",white:"rgb(255, 255, 255)",whitesmoke:"rgb(245, 245, 245)",yellow:"rgb(255, 255, 0)",yellowgreen:"rgb(154, 205, 50)"};L.jqplot.AxisLabelRenderer=function(ah){L.jqplot.ElemContainer.call(this);this.axis;this.show=true;this.label="";this.fontFamily=null;this.fontSize=null;this.textColor=null;this._elem;this.escapeHTML=false;L.extend(true,this,ah)};L.jqplot.AxisLabelRenderer.prototype=new L.jqplot.ElemContainer();L.jqplot.AxisLabelRenderer.prototype.constructor=L.jqplot.AxisLabelRenderer;L.jqplot.AxisLabelRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.AxisLabelRenderer.prototype.draw=function(ah,ai){if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=L('
    ');if(Number(this.label)){this._elem.css("white-space","nowrap")}if(!this.escapeHTML){this._elem.html(this.label)}else{this._elem.text(this.label)}if(this.fontFamily){this._elem.css("font-family",this.fontFamily)}if(this.fontSize){this._elem.css("font-size",this.fontSize)}if(this.textColor){this._elem.css("color",this.textColor)}return this._elem};L.jqplot.AxisLabelRenderer.prototype.pack=function(){};L.jqplot.AxisTickRenderer=function(ah){L.jqplot.ElemContainer.call(this);this.mark="outside";this.axis;this.showMark=true;this.showGridline=true;this.isMinorTick=false;this.size=4;this.markSize=6;this.show=true;this.showLabel=true;this.label=null;this.value=null;this._styles={};this.formatter=L.jqplot.DefaultTickFormatter;this.prefix="";this.suffix="";this.formatString="";this.fontFamily;this.fontSize;this.textColor;this.escapeHTML=false;this._elem;this._breakTick=false;L.extend(true,this,ah)};L.jqplot.AxisTickRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.AxisTickRenderer.prototype=new L.jqplot.ElemContainer();L.jqplot.AxisTickRenderer.prototype.constructor=L.jqplot.AxisTickRenderer;L.jqplot.AxisTickRenderer.prototype.setTick=function(ah,aj,ai){this.value=ah;this.axis=aj;if(ai){this.isMinorTick=true}return this};L.jqplot.AxisTickRenderer.prototype.draw=function(){if(this.label===null){this.label=this.prefix+this.formatter(this.formatString,this.value)+this.suffix}var ai={position:"absolute"};if(Number(this.label)){ai.whitSpace="nowrap"}if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=L(document.createElement("div"));this._elem.addClass("jqplot-"+this.axis+"-tick");if(!this.escapeHTML){this._elem.html(this.label)}else{this._elem.text(this.label)}this._elem.css(ai);for(var ah in this._styles){this._elem.css(ah,this._styles[ah])}if(this.fontFamily){this._elem.css("font-family",this.fontFamily)}if(this.fontSize){this._elem.css("font-size",this.fontSize)}if(this.textColor){this._elem.css("color",this.textColor)}if(this._breakTick){this._elem.addClass("jqplot-breakTick")}return this._elem};L.jqplot.DefaultTickFormatter=function(ah,ai){if(typeof ai=="number"){if(!ah){ah=L.jqplot.config.defaultTickFormatString}return L.jqplot.sprintf(ah,ai)}else{return String(ai)}};L.jqplot.PercentTickFormatter=function(ah,ai){if(typeof ai=="number"){ai=100*ai;if(!ah){ah=L.jqplot.config.defaultTickFormatString}return L.jqplot.sprintf(ah,ai)}else{return String(ai)}};L.jqplot.AxisTickRenderer.prototype.pack=function(){};L.jqplot.CanvasGridRenderer=function(){this.shadowRenderer=new L.jqplot.ShadowRenderer()};L.jqplot.CanvasGridRenderer.prototype.init=function(ai){this._ctx;L.extend(true,this,ai);var ah={lineJoin:"miter",lineCap:"round",fill:false,isarc:false,angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.shadowWidth,closePath:false,strokeStyle:this.shadowColor};this.renderer.shadowRenderer.init(ah)};L.jqplot.CanvasGridRenderer.prototype.createElement=function(ak){var aj;if(this._elem){if(L.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==u){aj=this._elem.get(0);window.G_vmlCanvasManager.uninitElement(aj);aj=null}this._elem.emptyForce();this._elem=null}aj=ak.canvasManager.getCanvas();var ah=this._plotDimensions.width;var ai=this._plotDimensions.height;aj.width=ah;aj.height=ai;this._elem=L(aj);this._elem.addClass("jqplot-grid-canvas");this._elem.css({position:"absolute",left:0,top:0});aj=ak.canvasManager.initCanvas(aj);this._top=this._offsets.top;this._bottom=ai-this._offsets.bottom;this._left=this._offsets.left;this._right=ah-this._offsets.right;this._width=this._right-this._left;this._height=this._bottom-this._top;aj=null;return this._elem};L.jqplot.CanvasGridRenderer.prototype.draw=function(){this._ctx=this._elem.get(0).getContext("2d");var at=this._ctx;var aw=this._axes;at.save();at.clearRect(0,0,this._plotDimensions.width,this._plotDimensions.height);at.fillStyle=this.backgroundColor||this.background;at.fillRect(this._left,this._top,this._width,this._height);at.save();at.lineJoin="miter";at.lineCap="butt";at.lineWidth=this.gridLineWidth;at.strokeStyle=this.gridLineColor;var aA,az,ap,aq;var am=["xaxis","yaxis","x2axis","y2axis"];for(var ay=4;ay>0;ay--){var aD=am[ay-1];var ah=aw[aD];var aB=ah._ticks;var ar=aB.length;if(ah.show){if(ah.drawBaseline){var aC={};if(ah.baselineWidth!==null){aC.lineWidth=ah.baselineWidth}if(ah.baselineColor!==null){aC.strokeStyle=ah.baselineColor}switch(aD){case"xaxis":ao(this._left,this._bottom,this._right,this._bottom,aC);break;case"yaxis":ao(this._left,this._bottom,this._left,this._top,aC);break;case"x2axis":ao(this._left,this._bottom,this._right,this._bottom,aC);break;case"y2axis":ao(this._right,this._bottom,this._right,this._top,aC);break}}for(var au=ar;au>0;au--){var an=aB[au-1];if(an.show){var ak=Math.round(ah.u2p(an.value))+0.5;switch(aD){case"xaxis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(ak,this._top,ak,this._bottom)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._bottom;az=this._bottom+ap;break;case"inside":aA=this._bottom-ap;az=this._bottom;break;case"cross":aA=this._bottom-ap;az=this._bottom+ap;break;default:aA=this._bottom;az=this._bottom+ap;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[ak,aA],[ak,az]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:this.gridLineWidth*0.75,depth:2,fill:false,closePath:false})}ao(ak,aA,ak,az)}break;case"yaxis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(this._right,ak,this._left,ak)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._left-ap;az=this._left;break;case"inside":aA=this._left;az=this._left+ap;break;case"cross":aA=this._left-ap;az=this._left+ap;break;default:aA=this._left-ap;az=this._left;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[aA,ak],[az,ak]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}ao(aA,ak,az,ak,{strokeStyle:ah.borderColor})}break;case"x2axis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(ak,this._bottom,ak,this._top)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._top-ap;az=this._top;break;case"inside":aA=this._top;az=this._top+ap;break;case"cross":aA=this._top-ap;az=this._top+ap;break;default:aA=this._top-ap;az=this._top;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[ak,aA],[ak,az]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:this.gridLineWidth*0.75,depth:2,fill:false,closePath:false})}ao(ak,aA,ak,az)}break;case"y2axis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(this._left,ak,this._right,ak)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._right;az=this._right+ap;break;case"inside":aA=this._right-ap;az=this._right;break;case"cross":aA=this._right-ap;az=this._right+ap;break;default:aA=this._right;az=this._right+ap;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[aA,ak],[az,ak]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}ao(aA,ak,az,ak,{strokeStyle:ah.borderColor})}break;default:break}}}an=null}ah=null;aB=null}am=["y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis","yMidAxis"];for(var ay=7;ay>0;ay--){var ah=aw[am[ay-1]];var aB=ah._ticks;if(ah.show){var ai=aB[ah.numberTicks-1];var al=aB[0];var aj=ah.getLeft();var av=[[aj,ai.getTop()+ai.getHeight()/2],[aj,al.getTop()+al.getHeight()/2+1]];if(this.shadow){this.renderer.shadowRenderer.draw(at,av,{lineCap:"butt",fill:false,closePath:false})}ao(av[0][0],av[0][1],av[1][0],av[1][1],{lineCap:"butt",strokeStyle:ah.borderColor,lineWidth:ah.borderWidth});for(var au=aB.length;au>0;au--){var an=aB[au-1];ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;if(an.showMark&&an.mark){switch(aq){case"outside":aA=aj;az=aj+ap;break;case"inside":aA=aj-ap;az=aj;break;case"cross":aA=aj-ap;az=aj+ap;break;default:aA=aj;az=aj+ap;break}av=[[aA,ak],[az,ak]];if(this.shadow){this.renderer.shadowRenderer.draw(at,av,{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}ao(aA,ak,az,ak,{strokeStyle:ah.borderColor})}an=null}al=null}ah=null;aB=null}at.restore();function ao(aH,aG,aE,ax,aF){at.save();aF=aF||{};if(aF.lineWidth==null||aF.lineWidth!=0){L.extend(true,at,aF);at.beginPath();at.moveTo(aH,aG);at.lineTo(aE,ax);at.stroke();at.restore()}}if(this.shadow){var av=[[this._left,this._bottom],[this._right,this._bottom],[this._right,this._top]];this.renderer.shadowRenderer.draw(at,av)}if(this.borderWidth!=0&&this.drawBorder){ao(this._left,this._top,this._right,this._top,{lineCap:"round",strokeStyle:aw.x2axis.borderColor,lineWidth:aw.x2axis.borderWidth});ao(this._right,this._top,this._right,this._bottom,{lineCap:"round",strokeStyle:aw.y2axis.borderColor,lineWidth:aw.y2axis.borderWidth});ao(this._right,this._bottom,this._left,this._bottom,{lineCap:"round",strokeStyle:aw.xaxis.borderColor,lineWidth:aw.xaxis.borderWidth});ao(this._left,this._bottom,this._left,this._top,{lineCap:"round",strokeStyle:aw.yaxis.borderColor,lineWidth:aw.yaxis.borderWidth})}at.restore();at=null;aw=null};L.jqplot.DivTitleRenderer=function(){};L.jqplot.DivTitleRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.DivTitleRenderer.prototype.draw=function(){if(this._elem){this._elem.emptyForce();this._elem=null}var ak=this.renderer;var aj=document.createElement("div");this._elem=L(aj);this._elem.addClass("jqplot-title");if(!this.text){this.show=false;this._elem.height(0);this._elem.width(0)}else{if(this.text){var ah;if(this.color){ah=this.color}else{if(this.textColor){ah=this.textColor}}var ai={position:"absolute",top:"0px",left:"0px"};if(this._plotWidth){ai.width=this._plotWidth+"px"}if(this.fontSize){ai.fontSize=this.fontSize}if(typeof this.textAlign==="string"){ai.textAlign=this.textAlign}else{ai.textAlign="center"}if(ah){ai.color=ah}if(this.paddingBottom){ai.paddingBottom=this.paddingBottom}if(this.fontFamily){ai.fontFamily=this.fontFamily}this._elem.css(ai);if(this.escapeHtml){this._elem.text(this.text)}else{this._elem.html(this.text)}}}aj=null;return this._elem};L.jqplot.DivTitleRenderer.prototype.pack=function(){};var r=0.1;L.jqplot.LinePattern=function(aw,aq){var ap={dotted:[r,L.jqplot.config.dotGapLength],dashed:[L.jqplot.config.dashLength,L.jqplot.config.gapLength],solid:null};if(typeof aq==="string"){if(aq[0]==="."||aq[0]==="-"){var ax=aq;aq=[];for(var ao=0,al=ax.length;ao0)&&(aC>0)){aA/=aB;az/=aB;while(true){var aD=aC*ar;if(aD=aq.length){ak=0}ar=aq[ak]}else{au=ay;at=aE;if((ak&1)==0){aw.lineTo(au,at)}else{aw.moveTo(au,at)}ar-=aB/aC;break}}}};var ai=function(){aw.beginPath()};var am=function(){aj(an,ah)};return{moveTo:av,lineTo:aj,beginPath:ai,closePath:am}};L.jqplot.LineRenderer=function(){this.shapeRenderer=new L.jqplot.ShapeRenderer();this.shadowRenderer=new L.jqplot.ShadowRenderer()};L.jqplot.LineRenderer.prototype.init=function(ai,an){ai=ai||{};this._type="line";this.renderer.animation={show:false,direction:"left",speed:2500,_supported:true};this.renderer.smooth=false;this.renderer.tension=null;this.renderer.constrainSmoothing=true;this.renderer._smoothedData=[];this.renderer._smoothedPlotData=[];this.renderer._hiBandGridData=[];this.renderer._lowBandGridData=[];this.renderer._hiBandSmoothedData=[];this.renderer._lowBandSmoothedData=[];this.renderer.bandData=[];this.renderer.bands={show:false,hiData:[],lowData:[],color:this.color,showLines:false,fill:true,fillColor:null,_min:null,_max:null,interval:"3%"};var al={highlightMouseOver:ai.highlightMouseOver,highlightMouseDown:ai.highlightMouseDown,highlightColor:ai.highlightColor};delete (ai.highlightMouseOver);delete (ai.highlightMouseDown);delete (ai.highlightColor);L.extend(true,this.renderer,ai);this.renderer.options=ai;if(this.renderer.bandData.length>1&&(!ai.bands||ai.bands.show==null)){this.renderer.bands.show=true}else{if(ai.bands&&ai.bands.show==null&&ai.bands.interval!=null){this.renderer.bands.show=true}}if(this.fill){this.renderer.bands.show=false}if(this.renderer.bands.show){this.renderer.initBands.call(this,this.renderer.options,an)}if(this._stack){this.renderer.smooth=false}var am={lineJoin:this.lineJoin,lineCap:this.lineCap,fill:this.fill,isarc:false,strokeStyle:this.color,fillStyle:this.fillColor,lineWidth:this.lineWidth,linePattern:this.linePattern,closePath:this.fill};this.renderer.shapeRenderer.init(am);var aj=ai.shadowOffset;if(aj==null){if(this.lineWidth>2.5){aj=1.25*(1+(Math.atan((this.lineWidth/2.5))/0.785398163-1)*0.6)}else{aj=1.25*Math.atan((this.lineWidth/2.5))/0.785398163}}var ah={lineJoin:this.lineJoin,lineCap:this.lineCap,fill:this.fill,isarc:false,angle:this.shadowAngle,offset:aj,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.lineWidth,linePattern:this.linePattern,closePath:this.fill};this.renderer.shadowRenderer.init(ah);this._areaPoints=[];this._boundingBox=[[],[]];if(!this.isTrendline&&this.fill||this.renderer.bands.show){this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColor=null;if(al.highlightMouseDown&&al.highlightMouseOver==null){al.highlightMouseOver=false}L.extend(true,this,{highlightMouseOver:al.highlightMouseOver,highlightMouseDown:al.highlightMouseDown,highlightColor:al.highlightColor});if(!this.highlightColor){var ak=(this.renderer.bands.show)?this.renderer.bands.fillColor:this.fillColor;this.highlightColor=L.jqplot.computeHighlightColors(ak)}if(this.highlighter){this.highlighter.show=false}}if(!this.isTrendline&&an){an.plugins.lineRenderer={};an.postInitHooks.addOnce(z);an.postDrawHooks.addOnce(af);an.eventListenerHooks.addOnce("jqplotMouseMove",h);an.eventListenerHooks.addOnce("jqplotMouseDown",e);an.eventListenerHooks.addOnce("jqplotMouseUp",ad);an.eventListenerHooks.addOnce("jqplotClick",g);an.eventListenerHooks.addOnce("jqplotRightClick",s)}};L.jqplot.LineRenderer.prototype.initBands=function(ak,av){var al=ak.bandData||[];var an=this.renderer.bands;an.hiData=[];an.lowData=[];var aB=this.data;an._max=null;an._min=null;if(al.length==2){if(L.isArray(al[0][0])){var ao;var ah=0,ar=0;for(var aw=0,at=al[0].length;awan._max)||an._max==null){an._max=ao[1]}if((ao[1]!=null&&ao[1]an._max)||an._max==null){an._max=ao[1];ar=1}if((ao[1]!=null&&ao[1]al[1][0])?0:1;var aC=(aj)?0:1;for(var aw=0,at=aB.length;aw2&&!L.isArray(al[0][0])){var aj=(al[0][0]>al[0][1])?0:1;var aC=(aj)?0:1;for(var aw=0,at=al.length;awan._max)||an._max==null){an._max=am[aw][1]}}for(var aw=0,at=ap.length;aw0){aR=Math.abs((ap[aQ][1]-ap[aQ-1][1])/(ap[aQ][0]-ap[aQ-1][0]))}am=aR/aG+aE;aM=aF*A(am)-aF*A(aE)+aS;aT=(aO+aM)/2}else{aT=aU}for(aK=0;aK2){var ao;if(this.renderer.constrainSmoothing){ao=J.call(this,this.gridData);this.renderer._smoothedData=ao[0];this.renderer._smoothedPlotData=ao[1];if(ak.show){ao=J.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ao[0];ao=J.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ao[0]}ao=null}else{ao=F.call(this,this.gridData);this.renderer._smoothedData=ao[0];this.renderer._smoothedPlotData=ao[1];if(ak.show){ao=F.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ao[0];ao=F.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ao[0]}ao=null}}};L.jqplot.LineRenderer.prototype.makeGridData=function(ao,aq){var am=this._xaxis.series_u2p;var ah=this._yaxis.series_u2p;var ar=[];var aj=[];this.renderer._smoothedData=[];this.renderer._smoothedPlotData=[];this.renderer._hiBandGridData=[];this.renderer._lowBandGridData=[];this.renderer._hiBandSmoothedData=[];this.renderer._lowBandSmoothedData=[];var al=this.renderer.bands;var ai=false;for(var an=0;an2){var ap;if(this.renderer.constrainSmoothing){ap=J.call(this,ar);this.renderer._smoothedData=ap[0];this.renderer._smoothedPlotData=ap[1];if(al.show){ap=J.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ap[0];ap=J.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ap[0]}ap=null}else{ap=F.call(this,ar);this.renderer._smoothedData=ap[0];this.renderer._smoothedPlotData=ap[1];if(al.show){ap=F.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ap[0];ap=F.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ap[0]}ap=null}}return ar};L.jqplot.LineRenderer.prototype.draw=function(ax,aI,ai,aB){var aC;var aq=L.extend(true,{},ai);var ak=(aq.shadow!=u)?aq.shadow:this.shadow;var aJ=(aq.showLine!=u)?aq.showLine:this.showLine;var aA=(aq.fill!=u)?aq.fill:this.fill;var ah=(aq.fillAndStroke!=u)?aq.fillAndStroke:this.fillAndStroke;var ar,ay,av,aE;ax.save();if(aI.length){if(aJ){if(aA){if(this.fillToZero){var aF=this.negativeColor;if(!this.useNegativeColors){aF=aq.fillStyle}var ao=false;var ap=aq.fillStyle;if(ah){var aH=aI.slice(0)}if(this.index==0||!this._stack){var aw=[];var aL=(this.renderer.smooth)?this.renderer._smoothedPlotData:this._plotData;this._areaPoints=[];var aG=this._yaxis.series_u2p(this.fillToValue);var aj=this._xaxis.series_u2p(this.fillToValue);aq.closePath=true;if(this.fillAxis=="y"){aw.push([aI[0][0],aG]);this._areaPoints.push([aI[0][0],aG]);for(var aC=0;aC0;aC--){aI.push(au[aC-1])}if(ak){this.renderer.shadowRenderer.draw(ax,aI,aq)}this._areaPoints=aI;this.renderer.shapeRenderer.draw(ax,aI,aq)}}else{if(ah){var aH=aI.slice(0)}if(this.index==0||!this._stack){var al=ax.canvas.height;aI.unshift([aI[0][0],al]);var aD=aI.length;aI.push([aI[aD-1][0],al])}else{var au=this._prevGridData;for(var aC=au.length;aC>0;aC--){aI.push(au[aC-1])}}this._areaPoints=aI;if(ak){this.renderer.shadowRenderer.draw(ax,aI,aq)}this.renderer.shapeRenderer.draw(ax,aI,aq)}if(ah){var az=L.extend(true,{},aq,{fill:false,closePath:false});this.renderer.shapeRenderer.draw(ax,aH,az);if(this.markerRenderer.show){if(this.renderer.smooth){aH=this.gridData}for(aC=0;aCat[0]||ar==null){ar=at[0]}if(aEat[1]||ay==null){ay=at[1]}}if(this.type==="line"&&this.renderer.bands.show){aE=this._yaxis.series_u2p(this.renderer.bands._min);ay=this._yaxis.series_u2p(this.renderer.bands._max)}this._boundingBox=[[ar,aE],[av,ay]];if(this.markerRenderer.show&&!aA){if(this.renderer.smooth){aI=this.gridData}for(aC=0;aCao){ao=aj}}}al=null;am=null;if(ah){ai=this._label._elem.outerWidth(true);an=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){ao=ao+an;this._elem.css({height:ao+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){ao=ao+an;this._elem.css({height:ao+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){ao=ao+ai;this._elem.css({width:ao+"px",left:"0px",top:"0px"});if(ah&&this._label.constructor==L.jqplot.AxisLabelRenderer){this._label._elem.css("width",ai+"px")}}else{ao=ao+ai;this._elem.css({width:ao+"px",right:"0px",top:"0px"});if(ah&&this._label.constructor==L.jqplot.AxisLabelRenderer){this._label._elem.css("width",ai+"px")}}}}}};L.jqplot.LinearAxisRenderer.prototype.createTicks=function(aj){var aT=this._ticks;var aK=this.ticks;var az=this.name;var aB=this._dataBounds;var ah=(this.name.charAt(0)==="x")?this._plotDimensions.width:this._plotDimensions.height;var an;var a6,aI;var ap,ao;var a4,a0;var aH=this.min;var a5=this.max;var aW=this.numberTicks;var ba=this.tickInterval;var am=30;this._scalefact=(Math.max(ah,am+1)-am)/300;if(aK.length){for(a0=0;a0this.breakPoints[0]&&aO[0]<=this.breakPoints[1]){aU.show=false;aU.showGridline=false;aU.label=aO[1]}else{aU.label=aO[1]}}}else{aU.label=aO[1]}aU.setTick(aO[0],this.name);this._ticks.push(aU)}else{if(L.isPlainObject(aO)){L.extend(true,aU,aO);aU.axis=this.name;this._ticks.push(aU)}else{aU.value=aO;if(this.breakPoints){if(aO==this.breakPoints[0]){aU.label=this.breakTickLabel;aU._breakTick=true;aU.showGridline=false;aU.showMark=false}else{if(aO>this.breakPoints[0]&&aO<=this.breakPoints[1]){aU.show=false;aU.showGridline=false}}}aU.setTick(aO,this.name);this._ticks.push(aU)}}}this.numberTicks=aK.length;this.min=this._ticks[0].value;this.max=this._ticks[this.numberTicks-1].value;this.tickInterval=(this.max-this.min)/(this.numberTicks-1)}else{if(az=="xaxis"||az=="x2axis"){ah=this._plotDimensions.width}else{ah=this._plotDimensions.height}var ax=this.numberTicks;if(this.alignTicks){if(this.name==="x2axis"&&aj.axes.xaxis.show){ax=aj.axes.xaxis.numberTicks}else{if(this.name.charAt(0)==="y"&&this.name!=="yaxis"&&this.name!=="yMidAxis"&&aj.axes.yaxis.show){ax=aj.axes.yaxis.numberTicks}}}a6=((this.min!=null)?this.min:aB.min);aI=((this.max!=null)?this.max:aB.max);var av=aI-a6;var aS,ay;var at;if(this.tickOptions==null||!this.tickOptions.formatString){this._overrideFormatString=true}if(this.min==null||this.max==null&&this.tickInterval==null&&!this.autoscale){if(this.forceTickAt0){if(a6>0){a6=0}if(aI<0){aI=0}}if(this.forceTickAt100){if(a6>100){a6=100}if(aI<100){aI=100}}var aE=false,a1=false;if(this.min!=null){aE=true}else{if(this.max!=null){a1=true}}var aP=L.jqplot.LinearTickGenerator(a6,aI,this._scalefact,ax,aE,a1);var aw=(this.min!=null)?a6:a6+av*(this.padMin-1);var aQ=(this.max!=null)?aI:aI-av*(this.padMax-1);if(a6aQ){aw=(this.min!=null)?a6:a6-av*(this.padMin-1);aQ=(this.max!=null)?aI:aI+av*(this.padMax-1);aP=L.jqplot.LinearTickGenerator(aw,aQ,this._scalefact,ax,aE,a1)}this.min=aP[0];this.max=aP[1];this.numberTicks=aP[2];this._autoFormatString=aP[3];this.tickInterval=aP[4]}else{if(a6==aI){var ai=0.05;if(a6>0){ai=Math.max(Math.log(a6)/Math.LN10,0.05)}a6-=ai;aI+=ai}if(this.autoscale&&this.min==null&&this.max==null){var ak,al,ar;var aC=false;var aN=false;var aA={min:null,max:null,average:null,stddev:null};for(var a0=0;a0a2){a2=aR[aZ]}}}var au=(a2-aG)/a2;if(aV.renderer.constructor==L.jqplot.BarRenderer){if(aG>=0&&(aV.fillToZero||au>0.1)){aC=true}else{aC=false;if(aV.fill&&aV.fillToZero&&aG<0&&a2>0){aN=true}else{aN=false}}}else{if(aV.fill){if(aG>=0&&(aV.fillToZero||au>0.1)){aC=true}else{if(aG<0&&a2>0&&aV.fillToZero){aC=false;aN=true}else{aC=false;aN=false}}}else{if(aG<0){aC=false}}}}}if(aC){this.numberTicks=2+Math.ceil((ah-(this.tickSpacing-1))/this.tickSpacing);this.min=0;aH=0;al=aI/(this.numberTicks-1);at=Math.pow(10,Math.abs(Math.floor(Math.log(al)/Math.LN10)));if(al/at==parseInt(al/at,10)){al+=at}this.tickInterval=Math.ceil(al/at)*at;this.max=this.tickInterval*(this.numberTicks-1)}else{if(aN){this.numberTicks=2+Math.ceil((ah-(this.tickSpacing-1))/this.tickSpacing);var aJ=Math.ceil(Math.abs(a6)/av*(this.numberTicks-1));var a9=this.numberTicks-1-aJ;al=Math.max(Math.abs(a6/aJ),Math.abs(aI/a9));at=Math.pow(10,Math.abs(Math.floor(Math.log(al)/Math.LN10)));this.tickInterval=Math.ceil(al/at)*at;this.max=this.tickInterval*a9;this.min=-this.tickInterval*aJ}else{if(this.numberTicks==null){if(this.tickInterval){this.numberTicks=3+Math.ceil(av/this.tickInterval)}else{this.numberTicks=2+Math.ceil((ah-(this.tickSpacing-1))/this.tickSpacing)}}if(this.tickInterval==null){al=av/(this.numberTicks-1);if(al<1){at=Math.pow(10,Math.abs(Math.floor(Math.log(al)/Math.LN10)))}else{at=1}this.tickInterval=Math.ceil(al*at*this.pad)/at}else{at=1/this.tickInterval}ak=this.tickInterval*(this.numberTicks-1);ar=(ak-av)/2;if(this.min==null){this.min=Math.floor(at*(a6-ar))/at}if(this.max==null){this.max=this.min+ak}}}var aF=L.jqplot.getSignificantFigures(this.tickInterval);var aM;if(aF.digitsLeft>=aF.significantDigits){aM="%d"}else{var at=Math.max(0,5-aF.digitsLeft);at=Math.min(at,aF.digitsRight);aM="%."+at+"f"}this._autoFormatString=aM}else{aS=(this.min!=null)?this.min:a6-av*(this.padMin-1);ay=(this.max!=null)?this.max:aI+av*(this.padMax-1);av=ay-aS;if(this.numberTicks==null){if(this.tickInterval!=null){this.numberTicks=Math.ceil((ay-aS)/this.tickInterval)+1}else{if(ah>100){this.numberTicks=parseInt(3+(ah-100)/75,10)}else{this.numberTicks=2}}}if(this.tickInterval==null){this.tickInterval=av/(this.numberTicks-1)}if(this.max==null){ay=aS+this.tickInterval*(this.numberTicks-1)}if(this.min==null){aS=ay-this.tickInterval*(this.numberTicks-1)}var aF=L.jqplot.getSignificantFigures(this.tickInterval);var aM;if(aF.digitsLeft>=aF.significantDigits){aM="%d"}else{var at=Math.max(0,5-aF.digitsLeft);at=Math.min(at,aF.digitsRight);aM="%."+at+"f"}this._autoFormatString=aM;this.min=aS;this.max=ay}if(this.renderer.constructor==L.jqplot.LinearAxisRenderer&&this._autoFormatString==""){av=this.max-this.min;var a7=new this.tickRenderer(this.tickOptions);var aL=a7.formatString||L.jqplot.config.defaultTickFormatString;var aL=aL.match(L.jqplot.sprintf.regex)[0];var a3=0;if(aL){if(aL.search(/[fFeEgGpP]/)>-1){var aY=aL.match(/\%\.(\d{0,})?[eEfFgGpP]/);if(aY){a3=parseInt(aY[1],10)}else{a3=6}}else{if(aL.search(/[di]/)>-1){a3=0}}var aq=Math.pow(10,-a3);if(this.tickIntervalthis.breakPoints[0]&&aAthis.breakPoints[0]&&aAthis.breakPoints[0]&&aA=this.breakPoints[1]){return(aA-au)*ak/al}else{return(aA+this.breakPoints[1]-this.breakPoints[0]-au)*ak/al}};this.series_p2u=function(aA){return aA*al/ak+au}}}else{this.p2u=function(aA){return(aA-am)*al/ak+at};this.u2p=function(aA){return(aA-at)*ak/al+am};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(aA){return(aA-at)*ak/al};this.series_p2u=function(aA){return aA*al/ak+at}}else{this.series_u2p=function(aA){return(aA-au)*ak/al};this.series_p2u=function(aA){return aA*al/ak+au}}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(var av=0;av0){ah=-ap._textRenderer.height*Math.cos(-ap._textRenderer.angle)/2}else{ah=-ap.getHeight()+ap._textRenderer.height*Math.cos(ap._textRenderer.angle)/2}break;case"middle":ah=-ap.getHeight()/2;break;default:ah=-ap.getHeight()/2;break}}else{ah=-ap.getHeight()/2}var az=this.u2p(ap.value)+ah+"px";ap._elem.css("top",az);ap.pack()}}if(aq){var aw=this._label._elem.outerHeight(true);this._label._elem.css("top",ao-ak/2-aw/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px")}else{this._label._elem.css("right","0px")}this._label.pack()}}}ay=null};function i(ai){var ah;ai=Math.abs(ai);if(ai>=10){ah="%d"}else{if(ai>1){if(ai===parseInt(ai,10)){ah="%d"}else{ah="%.1f"}}else{var aj=-Math.floor(Math.log(ai)/Math.LN10);ah="%."+aj+"f"}}return ah}var b=[0.1,0.2,0.3,0.4,0.5,0.8,1,2,3,4,5];var c=function(ai){var ah=b.indexOf(ai);if(ah>0){return b[ah-1]}else{return b[b.length-1]/100}};var k=function(ai){var ah=b.indexOf(ai);if(ah5){ah=10*aj}else{if(am>2){ah=5*aj}else{if(am>1){ah=2*aj}else{ah=aj}}}}else{if(am>5){ah=10*aj}else{if(am>4){ah=5*aj}else{if(am>3){ah=4*aj}else{if(am>2){ah=3*aj}else{if(am>1){ah=2*aj}else{ah=aj}}}}}}return ah}function Q(ai,ah){ah=ah||1;var ak=Math.floor(Math.log(ai)/Math.LN10);var am=Math.pow(10,ak);var al=ai/am;var aj;al=al/ah;if(al<=0.38){aj=0.1}else{if(al<=1.6){aj=0.2}else{if(al<=4){aj=0.5}else{if(al<=8){aj=1}else{if(al<=16){aj=2}else{aj=5}}}}}return aj*am}function x(aj,ai){var al=Math.floor(Math.log(aj)/Math.LN10);var an=Math.pow(10,al);var am=aj/an;var ah;var ak;am=am/ai;if(am<=0.38){ak=0.1}else{if(am<=1.6){ak=0.2}else{if(am<=4){ak=0.5}else{if(am<=8){ak=1}else{if(am<=16){ak=2}else{ak=5}}}}}ah=ak*an;return[ah,ak,an]}L.jqplot.LinearTickGenerator=function(an,aq,aj,ak,ao,ar){ao=(ao===null)?false:ao;ar=(ar===null||ao)?false:ar;if(an===aq){aq=(aq)?0:1}aj=aj||1;if(aqat){at=aB}if(ai>aA){aA=ai}})}an.width=at+Number(av);an.height=aA+Number(ax);var ak=an.getContext("2d");ak.save();ak.fillStyle=al;ak.fillRect(0,0,an.width,an.height);ak.restore();ak.translate(au,ar);ak.textAlign="left";ak.textBaseline="top";function aC(aE){var aF=parseInt(L(aE).css("line-height"),10);if(isNaN(aF)){aF=parseInt(L(aE).css("font-size"),10)*1.2}return aF}function aD(aF,aE,aS,aG,aO,aH){var aQ=aC(aF);var aK=L(aF).innerWidth();var aL=L(aF).innerHeight();var aN=aS.split(/\s+/);var aR=aN.length;var aP="";var aM=[];var aU=aO;var aT=aG;for(var aJ=0;aJaK){aM.push(aJ);aP="";aJ--}}if(aM.length===0){if(L(aF).css("textAlign")==="center"){aT=aG+(aH-aE.measureText(aP).width)/2-au}aE.fillText(aS,aT,aO)}else{aP=aN.slice(0,aM[0]).join(" ");if(L(aF).css("textAlign")==="center"){aT=aG+(aH-aE.measureText(aP).width)/2-au}aE.fillText(aP,aT,aU);aU+=aQ;for(var aJ=1,aI=aM.length;aJ0){ak.strokeRect(aI,aL,L(aG).innerWidth(),L(aG).innerHeight())}L(aG).find("div.jqplot-table-legend-swatch-outline").each(function(){var aU=L(this);ak.strokeStyle=aU.css("border-top-color");var aQ=aI+aU.position().left;var aR=aL+aU.position().top;ak.strokeRect(aQ,aR,aU.innerWidth(),aU.innerHeight());aQ+=parseInt(aU.css("padding-left"),10);aR+=parseInt(aU.css("padding-top"),10);var aT=aU.innerHeight()-2*parseInt(aU.css("padding-top"),10);var aP=aU.innerWidth()-2*parseInt(aU.css("padding-left"),10);var aS=aU.children("div.jqplot-table-legend-swatch");ak.fillStyle=aS.css("background-color");ak.fillRect(aQ,aR,aP,aT)});L(aG).find("td.jqplot-table-legend-label").each(function(){var aR=L(this);var aP=aI+aR.position().left;var aQ=aL+aR.position().top+parseInt(aR.css("padding-top"),10);ak.font=aR.jqplotGetComputedFontStyle();ak.fillStyle=aR.css("color");aD(aR,ak,aR.text(),aP,aQ,aM)});var aH=null}else{if(aN=="canvas"){ak.drawImage(aG,aI,aL)}}}}L(this).children().each(function(){aw(this,av,ax)});return an};L.fn.jqplotToImageStr=function(ai){var ah=L(this).jqplotToImageCanvas(ai);if(ah){return ah.toDataURL("image/png")}else{return null}};L.fn.jqplotToImageElem=function(ah){var ai=document.createElement("img");var aj=L(this).jqplotToImageStr(ah);ai.src=aj;return ai};L.fn.jqplotToImageElemStr=function(ah){var ai="";return ai};L.fn.jqplotSaveImage=function(){var ah=L(this).jqplotToImageStr({});if(ah){window.location.href=ah.replace("image/png","image/octet-stream")}};L.fn.jqplotViewImage=function(){var ai=L(this).jqplotToImageElemStr({});var aj=L(this).jqplotToImageStr({});if(ai){var ah=window.open("");ah.document.open("image/png");ah.document.write(ai);ah.document.close();ah=null}};var ag=function(){this.syntax=ag.config.syntax;this._type="jsDate";this.proxy=new Date();this.options={};this.locale=ag.regional.getLocale();this.formatString="";this.defaultCentury=ag.config.defaultCentury;switch(arguments.length){case 0:break;case 1:if(l(arguments[0])=="[object Object]"&&arguments[0]._type!="jsDate"){var aj=this.options=arguments[0];this.syntax=aj.syntax||this.syntax;this.defaultCentury=aj.defaultCentury||this.defaultCentury;this.proxy=ag.createDate(aj.date)}else{this.proxy=ag.createDate(arguments[0])}break;default:var ah=[];for(var ai=0;ai0?"floor":"ceil"](ak))};ag.prototype.getAbbrDayName=function(){return ag.regional[this.locale]["dayNamesShort"][this.proxy.getDay()]};ag.prototype.getAbbrMonthName=function(){return ag.regional[this.locale]["monthNamesShort"][this.proxy.getMonth()]};ag.prototype.getAMPM=function(){return this.proxy.getHours()>=12?"PM":"AM"};ag.prototype.getAmPm=function(){return this.proxy.getHours()>=12?"pm":"am"};ag.prototype.getCentury=function(){return parseInt(this.proxy.getFullYear()/100,10)};ag.prototype.getDate=function(){return this.proxy.getDate()};ag.prototype.getDay=function(){return this.proxy.getDay()};ag.prototype.getDayOfWeek=function(){var ah=this.proxy.getDay();return ah===0?7:ah};ag.prototype.getDayOfYear=function(){var ai=this.proxy;var ah=ai-new Date(""+ai.getFullYear()+"/1/1 GMT");ah+=ai.getTimezoneOffset()*60000;ai=null;return parseInt(ah/60000/60/24,10)+1};ag.prototype.getDayName=function(){return ag.regional[this.locale]["dayNames"][this.proxy.getDay()]};ag.prototype.getFullWeekOfYear=function(){var ak=this.proxy;var ah=this.getDayOfYear();var aj=6-ak.getDay();var ai=parseInt((ah+aj)/7,10);return ai};ag.prototype.getFullYear=function(){return this.proxy.getFullYear()};ag.prototype.getGmtOffset=function(){var ah=this.proxy.getTimezoneOffset()/60;var ai=ah<0?"+":"-";ah=Math.abs(ah);return ai+N(Math.floor(ah),2)+":"+N((ah%1)*60,2)};ag.prototype.getHours=function(){return this.proxy.getHours()};ag.prototype.getHours12=function(){var ah=this.proxy.getHours();return ah>12?ah-12:(ah==0?12:ah)};ag.prototype.getIsoWeek=function(){var ak=this.proxy;var aj=this.getWeekOfYear();var ah=(new Date(""+ak.getFullYear()+"/1/1")).getDay();var ai=aj+(ah>4||ah<=1?0:1);if(ai==53&&(new Date(""+ak.getFullYear()+"/12/31")).getDay()<4){ai=1}else{if(ai===0){ak=new ag(new Date(""+(ak.getFullYear()-1)+"/12/31"));ai=ak.getIsoWeek()}}ak=null;return ai};ag.prototype.getMilliseconds=function(){return this.proxy.getMilliseconds()};ag.prototype.getMinutes=function(){return this.proxy.getMinutes()};ag.prototype.getMonth=function(){return this.proxy.getMonth()};ag.prototype.getMonthName=function(){return ag.regional[this.locale]["monthNames"][this.proxy.getMonth()]};ag.prototype.getMonthNumber=function(){return this.proxy.getMonth()+1};ag.prototype.getSeconds=function(){return this.proxy.getSeconds()};ag.prototype.getShortYear=function(){return this.proxy.getYear()%100};ag.prototype.getTime=function(){return this.proxy.getTime()};ag.prototype.getTimezoneAbbr=function(){return this.proxy.toString().replace(/^.*\(([^)]+)\)$/,"$1")};ag.prototype.getTimezoneName=function(){var ah=/(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString());return ah[1]||ah[2]||"GMT"+this.getGmtOffset()};ag.prototype.getTimezoneOffset=function(){return this.proxy.getTimezoneOffset()};ag.prototype.getWeekOfYear=function(){var ah=this.getDayOfYear();var aj=7-this.getDayOfWeek();var ai=parseInt((ah+aj)/7,10);return ai};ag.prototype.getUnix=function(){return Math.round(this.proxy.getTime()/1000,0)};ag.prototype.getYear=function(){return this.proxy.getYear()};ag.prototype.next=function(ah){ah=ah||"day";return this.clone().add(1,ah)};ag.prototype.set=function(){switch(arguments.length){case 0:this.proxy=new Date();break;case 1:if(l(arguments[0])=="[object Object]"&&arguments[0]._type!="jsDate"){var aj=this.options=arguments[0];this.syntax=aj.syntax||this.syntax;this.defaultCentury=aj.defaultCentury||this.defaultCentury;this.proxy=ag.createDate(aj.date)}else{this.proxy=ag.createDate(arguments[0])}break;default:var ah=[];for(var ai=0;ai0?"floor":"ceil"](ah/12));var ai=aj.getMonth()+(ah%12);if(ai==12){ai=0;aj.setYear(aj.getFullYear()+1)}else{if(ai==-1){ai=11;aj.setYear(aj.getFullYear()-1)}}aj.setMonth(ai)},diff:function(al,aj){var ah=al.getFullYear()-aj.getFullYear();var ai=al.getMonth()-aj.getMonth()+(ah*12);var ak=al.getDate()-aj.getDate();return ai+(ak/30)}},year:{add:function(ai,ah){ai.setYear(ai.getFullYear()+Math[ah>0?"floor":"ceil"](ah))},diff:function(ai,ah){return E.month.diff(ai,ah)/12}}};for(var Y in E){if(Y.substring(Y.length-1)!="s"){E[Y+"s"]=E[Y]}}var H=function(al,ak,ai){if(ag.formats[ai]["shortcuts"][ak]){return ag.strftime(al,ag.formats[ai]["shortcuts"][ak],ai)}else{var ah=(ag.formats[ai]["codes"][ak]||"").split(".");var aj=al["get"+ah[0]]?al["get"+ah[0]]():"";if(ah[1]){aj=N(aj,ah[1])}return aj}};ag.strftime=function(an,ak,aj,ao){var ai="perl";var am=ag.regional.getLocale();if(aj&&ag.formats.hasOwnProperty(aj)){ai=aj}else{if(aj&&ag.regional.hasOwnProperty(aj)){am=aj}}if(ao&&ag.formats.hasOwnProperty(ao)){ai=ao}else{if(ao&&ag.regional.hasOwnProperty(ao)){am=ao}}if(l(an)!="[object Object]"||an._type!="jsDate"){an=new ag(an);an.locale=am}if(!ak){ak=an.formatString||ag.regional[am]["formatString"]}var ah=ak||"%Y-%m-%d",ap="",al;while(ah.length>0){if(al=ah.match(ag.formats[ai].codes.matcher)){ap+=ah.slice(0,al.index);ap+=(al[1]||"")+H(an,al[2],ai);ah=ah.slice(al.index+al[0].length)}else{ap+=ah;ah=""}}return ap};ag.formats={ISO:"%Y-%m-%dT%H:%M:%S.%N%G",SQL:"%Y-%m-%d %H:%M:%S"};ag.formats.perl={codes:{matcher:/()%(#?(%|[a-z]))/i,Y:"FullYear",y:"ShortYear.2",m:"MonthNumber.2","#m":"MonthNumber",B:"MonthName",b:"AbbrMonthName",d:"Date.2","#d":"Date",e:"Date",A:"DayName",a:"AbbrDayName",w:"Day",H:"Hours.2","#H":"Hours",I:"Hours12.2","#I":"Hours12",p:"AMPM",M:"Minutes.2","#M":"Minutes",S:"Seconds.2","#S":"Seconds",s:"Unix",N:"Milliseconds.3","#N":"Milliseconds",O:"TimezoneOffset",Z:"TimezoneName",G:"GmtOffset"},shortcuts:{F:"%Y-%m-%d",T:"%H:%M:%S",X:"%H:%M:%S",x:"%m/%d/%y",D:"%m/%d/%y","#c":"%a %b %e %H:%M:%S %Y",v:"%e-%b-%Y",R:"%H:%M",r:"%I:%M:%S %p",t:"\t",n:"\n","%":"%"}};ag.formats.php={codes:{matcher:/()%((%|[a-z]))/i,a:"AbbrDayName",A:"DayName",d:"Date.2",e:"Date",j:"DayOfYear.3",u:"DayOfWeek",w:"Day",U:"FullWeekOfYear.2",V:"IsoWeek.2",W:"WeekOfYear.2",b:"AbbrMonthName",B:"MonthName",m:"MonthNumber.2",h:"AbbrMonthName",C:"Century.2",y:"ShortYear.2",Y:"FullYear",H:"Hours.2",I:"Hours12.2",l:"Hours12",p:"AMPM",P:"AmPm",M:"Minutes.2",S:"Seconds.2",s:"Unix",O:"TimezoneOffset",z:"GmtOffset",Z:"TimezoneAbbr"},shortcuts:{D:"%m/%d/%y",F:"%Y-%m-%d",T:"%H:%M:%S",X:"%H:%M:%S",x:"%m/%d/%y",R:"%H:%M",r:"%I:%M:%S %p",t:"\t",n:"\n","%":"%"}};ag.createDate=function(aj){if(aj==null){return new Date()}if(aj instanceof Date){return aj}if(typeof aj=="number"){return new Date(aj)}var ao=String(aj).replace(/^\s*(.+)\s*$/g,"$1");ao=ao.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/,"$1/$2/$3");ao=ao.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i,"$1 $2 $3");var an=ao.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i);if(an&&an.length>3){var at=parseFloat(an[3]);var am=ag.config.defaultCentury+at;am=String(am);ao=ao.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i,an[1]+" "+an[2]+" "+am)}an=ao.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/);function ar(ax,aw){var aC=parseFloat(aw[1]);var aB=parseFloat(aw[2]);var aA=parseFloat(aw[3]);var az=ag.config.defaultCentury;var av,au,aD,ay;if(aC>31){au=aA;aD=aB;av=az+aC}else{au=aB;aD=aC;av=az+aA}ay=aD+"/"+au+"/"+av;return ax.replace(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/,ay)}if(an&&an.length>3){ao=ar(ao,an)}var an=ao.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/);if(an&&an.length>3){ao=ar(ao,an)}var al=0;var ai=ag.matchers.length;var aq,ah,ap=ao,ak;while(al31){ah=an;ai=am+ao}else{ah=ao;ai=am+an}var ap=ab(aj[2],ag.regional[ag.regional.getLocale()]["monthNamesShort"]);if(ap==-1){ap=ab(aj[2],ag.regional[ag.regional.getLocale()]["monthNames"])}ak.setFullYear(ai,ap,ah);ak.setHours(0,0,0,0);return ak}else{return al}}];function ab(aj,ak){if(ak.indexOf){return ak.indexOf(aj)}for(var ah=0,ai=ak.length;ah=ap)?"":Array(1+ap-au.length>>>0).join(aq);return at?au+ar:ar+au}function ak(ar){var aq=new String(ar);for(var ap=10;ap>0;ap--){if(aq==(aq=aq.replace(/^(\d+)(\d{3})/,"$1"+L.jqplot.sprintf.thousandsSeparator+"$2"))){break}}return aq}function aj(av,au,ax,ar,at,aq){var aw=ar-av.length;if(aw>0){var ap=" ";if(aq){ap=" "}if(ax||!at){av=an(av,ar,ap,ax)}else{av=av.slice(0,au.length)+an("",aw,"0",true)+av.slice(au.length)}}return av}function ao(ay,aq,aw,ar,ap,av,ax,au){var at=ay>>>0;aw=aw&&at&&{"2":"0b","8":"0","16":"0x"}[aq]||"";ay=aw+an(at.toString(aq),av||0,"0",false);return aj(ay,aw,ar,ap,ax,au)}function ah(au,av,ar,ap,at,aq){if(ap!=null){au=au.slice(0,ap)}return aj(au,"",av,ar,at,aq)}var ai=arguments,al=0,am=ai[al++];return am.replace(L.jqplot.sprintf.regex,function(aM,ax,ay,aB,aO,aJ,av){if(aM=="%%"){return"%"}var aD=false,az="",aA=false,aL=false,aw=false,au=false;for(var aI=0;ay&&aI-1?6:(av=="d")?0:void (0)}else{if(aJ=="*"){aJ=+ai[al++]}else{if(aJ.charAt(0)=="*"){aJ=+ai[aJ.slice(1,-1)]}else{aJ=+aJ}}}var aF=ax?ai[ax.slice(0,-1)]:ai[al++];switch(av){case"s":if(aF==null){return""}return ah(String(aF),aD,aB,aJ,aA,aw);case"c":return ah(String.fromCharCode(+aF),aD,aB,aJ,aA,aw);case"b":return ao(aF,2,aL,aD,aB,aJ,aA,aw);case"o":return ao(aF,8,aL,aD,aB,aJ,aA,aw);case"x":return ao(aF,16,aL,aD,aB,aJ,aA,aw);case"X":return ao(aF,16,aL,aD,aB,aJ,aA,aw).toUpperCase();case"u":return ao(aF,10,aL,aD,aB,aJ,aA,aw);case"i":var ar=parseInt(+aF,10);if(isNaN(ar)){return""}var aH=ar<0?"-":az;var aK=au?ak(String(Math.abs(ar))):String(Math.abs(ar));aF=aH+an(aK,aJ,"0",false);return aj(aF,aH,aD,aB,aA,aw);case"d":var ar=Math.round(+aF);if(isNaN(ar)){return""}var aH=ar<0?"-":az;var aK=au?ak(String(Math.abs(ar))):String(Math.abs(ar));aF=aH+an(aK,aJ,"0",false);return aj(aF,aH,aD,aB,aA,aw);case"e":case"E":case"f":case"F":case"g":case"G":var ar=+aF;if(isNaN(ar)){return""}var aH=ar<0?"-":az;var at=["toExponential","toFixed","toPrecision"]["efg".indexOf(av.toLowerCase())];var aN=["toString","toUpperCase"]["eEfFgG".indexOf(av)%2];var aK=Math.abs(ar)[at](aJ);var aE=aK.toString().split(".");aE[0]=au?ak(aE[0]):aE[0];aK=aE.join(L.jqplot.sprintf.decimalMark);aF=aH+aK;var aC=aj(aF,aH,aD,aB,aA,aw)[aN]();return aC;case"p":case"P":var ar=+aF;if(isNaN(ar)){return""}var aH=ar<0?"-":az;var aE=String(Number(Math.abs(ar)).toExponential()).split(/e|E/);var aq=(aE[0].indexOf(".")!=-1)?aE[0].length-1:String(ar).length;var aG=(aE[1]<0)?-aE[1]-1:0;if(Math.abs(ar)<1){if(aq+aG<=aJ){aF=aH+Math.abs(ar).toPrecision(aq)}else{if(aq<=aJ-1){aF=aH+Math.abs(ar).toExponential(aq-1)}else{aF=aH+Math.abs(ar).toExponential(aJ-1)}}}else{var ap=(aq<=aJ)?aq:aJ;aF=aH+Math.abs(ar).toPrecision(ap)}var aN=["toString","toUpperCase"]["pP".indexOf(av)%2];return aj(aF,aH,aD,aB,aA,aw)[aN]();case"n":return"";default:return aM}})};L.jqplot.sprintf.thousandsSeparator=",";L.jqplot.sprintf.decimalMark=".";L.jqplot.sprintf.regex=/%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g;L.jqplot.getSignificantFigures=function(al){var an=String(Number(Math.abs(al)).toExponential()).split(/e|E/);var am=(an[0].indexOf(".")!=-1)?an[0].length-1:an[0].length;var ai=(an[1]<0)?-an[1]-1:0;var ah=parseInt(an[1],10);var aj=(ah+1>0)?ah+1:0;var ak=(am<=aj)?0:am-ah-1;return{significantDigits:am,digitsLeft:aj,digitsRight:ak,zeros:ai,exponent:ah}};L.jqplot.getPrecision=function(ah){return L.jqplot.getSignificantFigures(ah).digitsRight};var X=L.uiBackCompat!==false;L.jqplot.effects={effect:{}};var m="jqplot.storage.";L.extend(L.jqplot.effects,{version:"1.9pre",save:function(ai,aj){for(var ah=0;ah
    ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),ah={width:ai.width(),height:ai.height()},ak=document.activeElement;ai.wrap(al);if(ai[0]===ak||L.contains(ai[0],ak)){L(ak).focus()}al=ai.parent();if(ai.css("position")==="static"){al.css({position:"relative"});ai.css({position:"relative"})}else{L.extend(aj,{position:ai.css("position"),zIndex:ai.css("z-index")});L.each(["top","left","bottom","right"],function(am,an){aj[an]=ai.css(an);if(isNaN(parseInt(aj[an],10))){aj[an]="auto"}});ai.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}ai.css(ah);return al.css(aj).show()},removeWrapper:function(ah){var ai=document.activeElement;if(ah.parent().is(".ui-effects-wrapper")){ah.parent().replaceWith(ah);if(ah[0]===ai||L.contains(ah[0],ai)){L(ai).focus()}}return ah}});function j(ai,ah,aj,ak){if(L.isPlainObject(ai)){return ai}ai={effect:ai};if(ah===u){ah={}}if(L.isFunction(ah)){ak=ah;aj=null;ah={}}if(L.type(ah)==="number"||L.fx.speeds[ah]){ak=aj;aj=ah;ah={}}if(L.isFunction(aj)){ak=aj;aj=null}if(ah){L.extend(ai,ah)}aj=aj||ah.duration;ai.duration=L.fx.off?0:typeof aj==="number"?aj:aj in L.fx.speeds?L.fx.speeds[aj]:L.fx.speeds._default;ai.complete=ak||ah.complete;return ai}function ae(ah){if(!ah||typeof ah==="number"||L.fx.speeds[ah]){return true}if(typeof ah==="string"&&!L.jqplot.effects.effect[ah]){if(X&&L.jqplot.effects[ah]){return false}return true}return false}L.fn.extend({jqplotEffect:function(ap,aq,ai,ao){var an=j.apply(this,arguments),ak=an.mode,al=an.queue,am=L.jqplot.effects.effect[an.effect],ah=!am&&X&&L.jqplot.effects[an.effect];if(L.fx.off||!(am||ah)){if(ak){return this[ak](an.duration,an.complete)}else{return this.each(function(){if(an.complete){an.complete.call(this)}})}}function aj(au){var av=L(this),at=an.complete,aw=an.mode;function ar(){if(L.isFunction(at)){at.call(av[0])}if(L.isFunction(au)){au()}}if(av.is(":hidden")?aw==="hide":aw==="show"){ar()}else{am.call(av[0],an,ar)}}if(am){return al===false?this.each(aj):this.queue(al||"fx",aj)}else{return ah.call(this,{options:an,duration:an.duration,callback:an.complete,mode:an.mode})}}});var a=/up|down|vertical/,v=/up|left|vertical|horizontal/;L.jqplot.effects.effect.blind=function(aj,ao){var ak=L(this),ar=["position","top","bottom","left","right","height","width"],ap=L.jqplot.effects.setMode(ak,aj.mode||"hide"),au=aj.direction||"up",am=a.test(au),al=am?"height":"width",aq=am?"top":"left",aw=v.test(au),an={},av=ap==="show",ai,ah,at;if(ak.parent().is(".ui-effects-wrapper")){L.jqplot.effects.save(ak.parent(),ar)}else{L.jqplot.effects.save(ak,ar)}ak.show();at=parseInt(ak.css("top"),10);ai=L.jqplot.effects.createWrapper(ak).css({overflow:"hidden"});ah=am?ai[al]()+at:ai[al]();an[al]=av?String(ah):"0";if(!aw){ak.css(am?"bottom":"right",0).css(am?"top":"left","").css({position:"absolute"});an[aq]=av?"0":String(ah)}if(av){ai.css(al,0);if(!aw){ai.css(aq,ah)}}ai.animate(an,{duration:aj.duration,easing:aj.easing,queue:false,complete:function(){if(ap==="hide"){ak.hide()}L.jqplot.effects.restore(ak,ar);L.jqplot.effects.removeWrapper(ak);ao()}})}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(a){a.jqplot.ciParser=function(g,l){var m=[],o,n,h,f,e,c;if(typeof(g)=="string"){g=a.jqplot.JSON.parse(g,d)}else{if(typeof(g)=="object"){for(e in g){for(h=0;h=0){i=/^\/Date\((-?[0-9]+)\)\/$/.exec(k);if(i){return parseInt(i[1],10)}}return k}}for(var b in g){o=[];n=g[b];switch(b){case"PriceTicks":for(h=0;h570)?o[p]*0.8:o[p]+0.3*(255-o[p]);o[p]=parseInt(o[p],10)}this.highlightColors.push("rgb("+o[0]+","+o[1]+","+o[2]+")")}}this.highlightColorGenerator=new e.jqplot.ColorGenerator(this.highlightColors);u.postParseOptionsHooks.addOnce(m);u.postInitHooks.addOnce(g);u.eventListenerHooks.addOnce("jqplotMouseMove",b);u.eventListenerHooks.addOnce("jqplotMouseDown",a);u.eventListenerHooks.addOnce("jqplotMouseUp",l);u.eventListenerHooks.addOnce("jqplotClick",f);u.eventListenerHooks.addOnce("jqplotRightClick",n);u.postDrawHooks.addOnce(i)};e.jqplot.PieRenderer.prototype.setGridData=function(t){var p=[];var u=[];var o=this.startAngle/180*Math.PI;var s=0;this._drawData=false;for(var r=0;r0){p[r]+=p[r-1]}s+=this.data[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r0){p[r]+=p[r-1]}s+=t[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r0&&s>0.01&&s<6.282){w=parseFloat(p)/2/h(q)}return w}e.jqplot.PieRenderer.prototype.drawSlice=function(B,z,y,u,w){if(this._drawData){var p=this._radius;var A=this.fill;var x=this.lineWidth;var s=this.sliceMargin;if(this.fill==false){s+=this.lineWidth}B.save();B.translate(this._center[0],this._center[1]);var D=j(z,y,this.sliceMargin,this.fill,this.lineWidth);var o=D*Math.cos((z+y)/2);var C=D*Math.sin((z+y)/2);if((y-z)<=Math.PI){p-=D}else{p+=D}B.translate(o,C);if(w){for(var v=0,t=this.shadowDepth;v6.282+this.startAngle){y=6.282+this.startAngle;if(z>y){z=6.281+this.startAngle}}if(z>=y){return}B.beginPath();B.fillStyle=u;B.strokeStyle=u;B.lineWidth=x;B.arc(0,0,r,z,y,false);B.lineTo(0,0);B.closePath();if(A){B.fill()}else{B.stroke()}}};e.jqplot.PieRenderer.prototype.draw=function(B,z,E,o){var W;var H=(E!=undefined)?E:{};var t=0;var s=0;var N=1;var L=new e.jqplot.ColorGenerator(this.seriesColors);if(E.legendInfo&&E.legendInfo.placement=="insideGrid"){var J=E.legendInfo;switch(J.location){case"nw":t=J.width+J.xoffset;break;case"w":t=J.width+J.xoffset;break;case"sw":t=J.width+J.xoffset;break;case"ne":t=J.width+J.xoffset;N=-1;break;case"e":t=J.width+J.xoffset;N=-1;break;case"se":t=J.width+J.xoffset;N=-1;break;case"n":s=J.height+J.yoffset;break;case"s":s=J.height+J.yoffset;N=-1;break;default:break}}var K=(H.shadow!=undefined)?H.shadow:this.shadow;var A=(H.fill!=undefined)?H.fill:this.fill;var C=B.canvas.width;var I=B.canvas.height;var Q=C-t-2*this.padding;var X=I-s-2*this.padding;var M=Math.min(Q,X);var Y=M;this._sliceAngles=[];var v=this.sliceMargin;if(this.fill==false){v+=this.lineWidth}var q;var G=0;var R,aa,Z,ab;var D=this.startAngle/180*Math.PI;for(var W=0,V=z.length;WMath.PI){G=Math.max(q,G)}}if(this.diameter!=null&&this.diameter>0){this._diameter=this.diameter-2*G}else{this._diameter=Y-2*G}if(this._diameter<6){e.jqplot.log("Diameter of pie too small, not rendering.");return}var S=this._radius=this._diameter/2;this._center=[(C-N*t)/2+N*t+G*Math.cos(D),(I-N*s)/2+N*s+G*Math.sin(D)];if(this.shadow){for(var W=0,V=z.length;W=this.dataLabelThreshold){var F,U=(this._sliceAngles[W][0]+this._sliceAngles[W][1])/2,T;if(this.dataLabels=="label"){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,z[W][0])}else{if(this.dataLabels=="value"){F=this.dataLabelFormatString||"%d";T=e.jqplot.sprintf(F,this.data[W][1])}else{if(this.dataLabels=="percent"){F=this.dataLabelFormatString||"%d%%";T=e.jqplot.sprintf(F,z[W][2]*100)}else{if(this.dataLabels.constructor==Array){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,this.dataLabels[W])}}}}var p=(this._radius)*this.dataLabelPositionFactor+this.sliceMargin+this.dataLabelNudge;var P=this._center[0]+Math.cos(U)*p+this.canvas._offsets.left;var O=this._center[1]+Math.sin(U)*p+this.canvas._offsets.top;var u=e('
    '+T+"
    ").insertBefore(o.eventCanvas._elem);if(this.dataLabelCenterOn){P-=u.width()/2;O-=u.height()/2}else{P-=u.width()*Math.sin(U/2);O-=u.height()/2}P=Math.round(P);O=Math.round(O);u.css({left:P,top:O})}}};e.jqplot.PieAxisRenderer=function(){e.jqplot.LinearAxisRenderer.call(this)};e.jqplot.PieAxisRenderer.prototype=new e.jqplot.LinearAxisRenderer();e.jqplot.PieAxisRenderer.prototype.constructor=e.jqplot.PieAxisRenderer;e.jqplot.PieAxisRenderer.prototype.init=function(o){this.tickRenderer=e.jqplot.PieTickRenderer;e.extend(true,this,o);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};e.jqplot.PieLegendRenderer=function(){e.jqplot.TableLegendRenderer.call(this)};e.jqplot.PieLegendRenderer.prototype=new e.jqplot.TableLegendRenderer();e.jqplot.PieLegendRenderer.prototype.constructor=e.jqplot.PieLegendRenderer;e.jqplot.PieLegendRenderer.prototype.init=function(o){this.numberRows=null;this.numberColumns=null;e.extend(true,this,o)};e.jqplot.PieLegendRenderer.prototype.draw=function(){var r=this;if(this.show){var B=this._series;this._elem=e(document.createElement("table"));this._elem.addClass("jqplot-table-legend");var E={position:"absolute"};if(this.background){E.background=this.background}if(this.border){E.border=this.border}if(this.fontSize){E.fontSize=this.fontSize}if(this.fontFamily){E.fontFamily=this.fontFamily}if(this.textColor){E.textColor=this.textColor}if(this.marginTop!=null){E.marginTop=this.marginTop}if(this.marginBottom!=null){E.marginBottom=this.marginBottom}if(this.marginLeft!=null){E.marginLeft=this.marginLeft}if(this.marginRight!=null){E.marginRight=this.marginRight}this._elem.css(E);var I=false,A=false,o,y;var C=B[0];var p=new e.jqplot.ColorGenerator(C.seriesColors);if(C.show){var J=C.data;if(this.numberRows){o=this.numberRows;if(!this.numberColumns){y=Math.ceil(J.length/o)}else{y=this.numberColumns}}else{if(this.numberColumns){y=this.numberColumns;o=Math.ceil(J.length/this.numberColumns)}else{o=J.length;y=1}}var H,G;var q,w,v;var x,z,F;var D=0;var u,t;for(H=0;H0){I=true}else{I=false}}else{if(H==o-1){I=false}else{I=true}}z=(I)?this.rowSpacing:"0";w=e(document.createElement("td"));w.addClass("jqplot-table-legend jqplot-table-legend-swatch");w.css({textAlign:"center",paddingTop:z});u=e(document.createElement("div"));u.addClass("jqplot-table-legend-swatch-outline");t=e(document.createElement("div"));t.addClass("jqplot-table-legend-swatch");t.css({backgroundColor:F,borderColor:F});w.append(u.append(t));v=e(document.createElement("td"));v.addClass("jqplot-table-legend jqplot-table-legend-label");v.css("paddingTop",z);if(this.escapeHtml){v.text(x)}else{v.html(x)}if(A){v.prependTo(q);w.prependTo(q)}else{w.appendTo(q);v.appendTo(q)}I=true}D++}}}}return this._elem};e.jqplot.PieRenderer.prototype.handleMove=function(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];r.target.trigger("jqplotDataMouseOver",o);if(r.series[o[0]].highlightMouseOver&&!(o[0]==r.plugins.pieRenderer.highlightedSeriesIndex&&o[1]==r.series[o[0]]._highlightedPoint)){r.target.trigger("jqplotDataHighlight",o);d(r,o[0],o[1])}}else{if(s==null){k(r)}}};function c(s,r,p){p=p||{};p.axesDefaults=p.axesDefaults||{};p.legend=p.legend||{};p.seriesDefaults=p.seriesDefaults||{};var o=false;if(p.seriesDefaults.renderer==e.jqplot.PieRenderer){o=true}else{if(p.series){for(var q=0;qB||s+C>m){z.remove()}z=null;f=null}}};c.jqplot.postSeriesInitHooks.push(c.jqplot.PointLabels.init);c.jqplot.postDrawSeriesHooks.push(c.jqplot.PointLabels.draw)})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(b){function a(e,d,c){this.bindCustomEvents=function(){this.eventCanvas._elem.bind("vclick",{plot:this},this.onClick);this.eventCanvas._elem.bind("dblclick",{plot:this},this.onDblClick);this.eventCanvas._elem.bind("taphold",{plot:this},this.onDblClick);this.eventCanvas._elem.bind("vmousedown",{plot:this},this.onMouseDown);this.eventCanvas._elem.bind("vmousemove",{plot:this},this.onMouseMove);this.eventCanvas._elem.bind("mouseenter",{plot:this},this.onMouseEnter);this.eventCanvas._elem.bind("mouseleave",{plot:this},this.onMouseLeave);if(this.captureRightClick){this.eventCanvas._elem.bind("vmouseup",{plot:this},this.onRightClick);this.eventCanvas._elem.get(0).oncontextmenu=function(){return false}}else{this.eventCanvas._elem.bind("vmouseup",{plot:this},this.onMouseUp)}};this.plugins.mobile=true}b.jqplot.postInitHooks.push(a)})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(f){var d=function(m){return Math.max.apply(Math,m)};var j=function(m){return Math.min.apply(Math,m)};f.jqplot.BubbleRenderer=function(){f.jqplot.LineRenderer.call(this)};f.jqplot.BubbleRenderer.prototype=new f.jqplot.LineRenderer();f.jqplot.BubbleRenderer.prototype.constructor=f.jqplot.BubbleRenderer;f.jqplot.BubbleRenderer.prototype.init=function(w,t){this.varyBubbleColors=true;this.autoscaleBubbles=true;this.autoscaleMultiplier=1;this.autoscalePointsFactor=-0.07;this.escapeHtml=true;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.bubbleAlpha=1;this.highlightAlpha=null;this.bubbleGradients=false;this.showLabels=true;this.radii=[];this.maxRadius=0;this._highlightedPoint=null;this.labels=[];this.bubbleCanvases=[];this._type="bubble";if(w.highlightMouseDown&&w.highlightMouseOver==null){w.highlightMouseOver=false}f.extend(true,this,w);if(this.highlightAlpha==null){this.highlightAlpha=this.bubbleAlpha;if(this.bubbleGradients){this.highlightAlpha=0.35}}this.autoscaleMultiplier=this.autoscaleMultiplier*Math.pow(this.data.length,this.autoscalePointsFactor);this._highlightedPoint=null;var n;for(var r=0;r570)?u[q]*0.8:u[q]+0.3*(255-u[q]);u[q]=parseInt(u[q],10)}this.highlightColors.push("rgba("+u[0]+","+u[1]+","+u[2]+", "+this.highlightAlpha+")")}}this.highlightColorGenerator=new f.jqplot.ColorGenerator(this.highlightColors);var m={fill:true,isarc:true,angle:this.shadowAngle,alpha:this.shadowAlpha,closePath:true};this.renderer.shadowRenderer.init(m);this.canvas=new f.jqplot.DivCanvas();this.canvas._plotDimensions=this._plotDimensions;t.eventListenerHooks.addOnce("jqplotMouseMove",a);t.eventListenerHooks.addOnce("jqplotMouseDown",b);t.eventListenerHooks.addOnce("jqplotMouseUp",k);t.eventListenerHooks.addOnce("jqplotClick",g);t.eventListenerHooks.addOnce("jqplotRightClick",l);t.postDrawHooks.addOnce(h)};f.jqplot.BubbleRenderer.prototype.setGridData=function(w){var q=this._xaxis.series_u2p;var m=this._yaxis.series_u2p;var t=this._plotData;this.gridData=[];var s=[];this.radii=[];var v=Math.min(w._height,w._width);for(var u=0;u');if(this.escapeHtml){p.text(z)}else{p.html(z)}this.canvas._elem.append(p);var H=f(p).outerHeight();var v=f(p).outerWidth();var B=J[1]-0.5*H;var o=J[0]-0.5*v;p.css({top:B,left:o});this.labels[C]=f(p)}}};f.jqplot.DivCanvas=function(){f.jqplot.ElemContainer.call(this);this._ctx};f.jqplot.DivCanvas.prototype=new f.jqplot.ElemContainer();f.jqplot.DivCanvas.prototype.constructor=f.jqplot.DivCanvas;f.jqplot.DivCanvas.prototype.createElement=function(s,p,n){this._offsets=s;var m="jqplot-DivCanvas";if(p!=undefined){m=p}var r;if(this._elem){r=this._elem.get(0)}else{r=document.createElement("div")}if(n!=undefined){this._plotDimensions=n}var o=this._plotDimensions.width-this._offsets.left-this._offsets.right+"px";var q=this._plotDimensions.height-this._offsets.top-this._offsets.bottom+"px";this._elem=f(r);this._elem.css({position:"absolute",width:o,height:q,left:this._offsets.left,top:this._offsets.top});this._elem.addClass(m);return this._elem};f.jqplot.DivCanvas.prototype.setContext=function(){this._ctx={canvas:{width:0,height:0},clearRect:function(){return null}};return this._ctx};f.jqplot.BubbleCanvas=function(){f.jqplot.ElemContainer.call(this);this._ctx};f.jqplot.BubbleCanvas.prototype=new f.jqplot.ElemContainer();f.jqplot.BubbleCanvas.prototype.constructor=f.jqplot.BubbleCanvas;f.jqplot.BubbleCanvas.prototype.createElement=function(n,u,s){var m="jqplot-bubble-point";var q;if(this._elem){q=this._elem.get(0)}else{q=document.createElement("canvas")}q.width=(s!=null)?2*s:q.width;q.height=(s!=null)?2*s:q.height;this._elem=f(q);var o=(n!=null&&s!=null)?n-s:this._elem.css("left");var p=(u!=null&&s!=null)?u-s:this._elem.css("top");this._elem.css({position:"absolute",left:o,top:p});this._elem.addClass(m);if(f.jqplot.use_excanvas){window.G_vmlCanvasManager.init_(document);q=window.G_vmlCanvasManager.initElement(q)}return this._elem};f.jqplot.BubbleCanvas.prototype.draw=function(m,s,v,p){var D=this._ctx;var B=D.canvas.width/2;var z=D.canvas.height/2;D.save();if(v&&!f.jqplot.use_excanvas){m=m*1.04;var o=f.jqplot.getColorComponents(s);var u="rgba("+Math.round(o[0]+0.8*(255-o[0]))+", "+Math.round(o[1]+0.8*(255-o[1]))+", "+Math.round(o[2]+0.8*(255-o[2]))+", "+o[3]+")";var t="rgba("+o[0]+", "+o[1]+", "+o[2]+", 0)";var C=0.35*m;var A=B-Math.cos(p)*0.33*m;var n=z-Math.sin(p)*0.33*m;var w=D.createRadialGradient(A,n,C,B,z,m);w.addColorStop(0,u);w.addColorStop(0.93,s);w.addColorStop(0.96,t);w.addColorStop(1,t);D.fillStyle=w;D.fillRect(0,0,D.canvas.width,D.canvas.height)}else{D.fillStyle=s;D.strokeStyle=s;D.lineWidth=1;D.beginPath();var q=2*Math.PI;D.arc(B,z,m,0,q,0);D.closePath();D.fill()}D.restore()};f.jqplot.BubbleCanvas.prototype.setContext=function(){this._ctx=this._elem.get(0).getContext("2d");return this._ctx};f.jqplot.BubbleAxisRenderer=function(){f.jqplot.LinearAxisRenderer.call(this)};f.jqplot.BubbleAxisRenderer.prototype=new f.jqplot.LinearAxisRenderer();f.jqplot.BubbleAxisRenderer.prototype.constructor=f.jqplot.BubbleAxisRenderer;f.jqplot.BubbleAxisRenderer.prototype.init=function(n){f.extend(true,this,n);var I=this._dataBounds;var H=0,v=0,m=0,y=0,q=0,r=0,D=0,t=0,F=0,z=0;for(var E=0;EI.max||I.max==null){I.max=G[B][0];m=E;y=B;q=G[B][2];t=x.maxRadius;F=x.autoscaleMultiplier}}else{if(G[B][1]I.max||I.max==null){I.max=G[B][1];m=E;y=B;q=G[B][2];t=x.maxRadius;F=x.autoscaleMultiplier}}}}var o=r/D;var w=q/t;var C=I.max-I.min;var A=Math.min(this._plotDimensions.width,this._plotDimensions.height);var p=o*z/3*C;var u=w*F/3*C;I.max+=u;I.min-=p};function e(p,v,q){p.plugins.bubbleRenderer.highlightLabelCanvas.empty();var z=p.series[v];var n=p.plugins.bubbleRenderer.highlightCanvas;var w=n._ctx;w.clearRect(0,0,w.canvas.width,w.canvas.height);z._highlightedPoint=q;p.plugins.bubbleRenderer.highlightedSeriesIndex=v;var o=z.highlightColorGenerator.get(q);var u=z.gridData[q][0],t=z.gridData[q][1],m=z.gridData[q][2];w.save();w.fillStyle=o;w.strokeStyle=o;w.lineWidth=1;w.beginPath();w.arc(u,t,m,0,2*Math.PI,0);w.closePath();w.fill();w.restore();if(z.labels[q]){p.plugins.bubbleRenderer.highlightLabel=z.labels[q].clone();p.plugins.bubbleRenderer.highlightLabel.appendTo(p.plugins.bubbleRenderer.highlightLabelCanvas);p.plugins.bubbleRenderer.highlightLabel.addClass("jqplot-bubble-label-highlight")}}function i(p){var m=p.plugins.bubbleRenderer.highlightCanvas;var o=p.plugins.bubbleRenderer.highlightedSeriesIndex;p.plugins.bubbleRenderer.highlightLabelCanvas.empty();m._ctx.clearRect(0,0,m._ctx.canvas.width,m._ctx.canvas.height);for(var n=0;n');var q=this._gridPadding.top;var p=this._gridPadding.left;var n=this._plotDimensions.width-this._gridPadding.left-this._gridPadding.right;var m=this._plotDimensions.height-this._gridPadding.top-this._gridPadding.bottom;this.plugins.bubbleRenderer.highlightLabelCanvas.css({top:q,left:p,width:n+"px",height:m+"px"});this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightCanvas.createElement(this._gridPadding,"jqplot-bubbleRenderer-highlight-canvas",this._plotDimensions,this));this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightLabelCanvas);var o=this.plugins.bubbleRenderer.highlightCanvas.setContext()}function c(q,p,n){n=n||{};n.axesDefaults=n.axesDefaults||{};n.seriesDefaults=n.seriesDefaults||{};var m=false;if(n.seriesDefaults.renderer==f.jqplot.BubbleRenderer){m=true}else{if(n.series){for(var o=0;oh.max)||h.max===null){h.max=g}}else{g=o[k][0];if((g!==null&&gh.max)||h.max===null){h.max=g}}}}};e.jqplot.PyramidAxisRenderer.prototype.draw=function(f,n){if(this.show){this.renderer.createTicks.call(this,n);var m=0;var g;if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=e(document.createElement("div"));this._elem.addClass("jqplot-axis jqplot-"+this.name);this._elem.css("position","absolute");if(this.name=="xaxis"||this.name=="x2axis"){this._elem.width(this._plotDimensions.width)}else{this._elem.height(this._plotDimensions.height)}this.labelOptions.axis=this.name;this._label=new this.labelRenderer(this.labelOptions);if(this._label.show){var l=this._label.draw(f,n);l.appendTo(this._elem);l=null}var k=this._ticks;var j;for(var h=0;hr){I=this.numberTicks-1;for(H=2;H0;H--){v=new this.tickRenderer(this.tickOptions);v.value=this._ticks[H-1].value+this.tickInterval/2;v.label="";v.showLabel=false;v.axis=this.name;this._ticks[H].showGridline=false;this._ticks[H].showMark=false;this._ticks.splice(H,0,v)}v=new this.tickRenderer(this.tickOptions);v.value=this._ticks[0].value-this.tickInterval/2;v.label="";v.showLabel=false;v.axis=this.name;this._ticks.unshift(v);v=new this.tickRenderer(this.tickOptions);v.value=this._ticks[this._ticks.length-1].value+this.tickInterval/2;v.label="";v.showLabel=false;v.axis=this.name;this._ticks.push(v);this.tickInterval=this.tickInterval/2;this.numberTicks=this._ticks.length;this.min=this._ticks[0].value;this.max=this._ticks[this._ticks.length-1].value}}else{if(this.name.charAt(0)==="x"){E=this._plotDimensions.width;var w=Math.max(M.max,Math.abs(M.min));var u=Math.min(M.min,-w);B=u;G=w;y=G-B;if(this.tickOptions==null||!this.tickOptions.formatString){this._overrideFormatString=true}m=30;g=Math.max(E,m+1);j=(g-m)/300;O=e.jqplot.LinearTickGenerator(B,G,j);A=B+y*(this.padMin-1);F=G-y*(this.padMax-1);if(BF){A=B-y*(this.padMin-1);F=G+y*(this.padMax-1);O=e.jqplot.LinearTickGenerator(A,F,j)}this.min=O[0];this.max=O[1];this.numberTicks=O[2];this._autoFormatString=O[3];this.tickInterval=O[4]}else{E=this._plotDimensions.height;B=M.min;G=M.max;x=this._series[0];this._ticks=[];y=G-B;if(d[y]){y+=1;G+=1}this.max=G;this.min=B;r=Math.round(2+E/this.tickSpacingFactor);if(y+1<=r){this.numberTicks=y+1;this.tickInterval=1}else{for(var H=r;H>1;H--){if(y/(H-1)===Math.round(y/(H-1))){this.numberTicks=H;this.tickInterval=y/(H-1);break}}}}if(this._overrideFormatString&&this._autoFormatString!=""){this.tickOptions=this.tickOptions||{};this.tickOptions.formatString=this._autoFormatString}var f;for(H=0;Ho){o=j}}}if(this.name==="yMidAxis"){for(m=0;m0){f=-q._textRenderer.height*Math.cos(-q._textRenderer.angle)/2}else{f=-q.getHeight()+q._textRenderer.height*Math.cos(q._textRenderer.angle)/2}break;case"middle":f=-q.getHeight()/2;break;default:f=-q.getHeight()/2;break}}else{f=-q.getHeight()/2}var C=this.u2p(q.value)+f+"px";q._elem.css("top",C);q.pack()}}if(r){var y=this._label._elem.outerHeight(true);if(this.name!=="yMidAxis"){this._label._elem.css("top",o-k/2-y/2+"px")}if(this.name=="yaxis"){this._label._elem.css("left","0px")}else{if(this.name!=="yMidAxis"){this._label._elem.css("right","0px")}}this._label.pack()}}}B=null}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(a){a.jqplot.OHLCRenderer=function(){a.jqplot.LineRenderer.call(this);this.candleStick=false;this.tickLength="auto";this.bodyWidth="auto";this.openColor=null;this.closeColor=null;this.wickColor=null;this.fillUpBody=false;this.fillDownBody=true;this.upBodyColor=null;this.downBodyColor=null;this.hlc=false;this.lineWidth=1.5;this._tickLength;this._bodyWidth};a.jqplot.OHLCRenderer.prototype=new a.jqplot.LineRenderer();a.jqplot.OHLCRenderer.prototype.constructor=a.jqplot.OHLCRenderer;a.jqplot.OHLCRenderer.prototype.init=function(e){e=e||{};this.lineWidth=e.lineWidth||1.5;a.jqplot.LineRenderer.prototype.init.call(this,e);this._type="ohlc";var b=this._yaxis._dataBounds;var f=this._plotData;if(f[0].length<5){this.renderer.hlc=true;for(var c=0;cb.max||b.max==null){b.max=f[c][1]}}}else{for(var c=0;cb.max||b.max==null){b.max=f[c][2]}}}};a.jqplot.OHLCRenderer.prototype.draw=function(A,N,j){var J=this.data;var v=this._xaxis.min;var z=this._xaxis.max;var l=0;var K=J.length;var p=this._xaxis.series_u2p;var G=this._yaxis.series_u2p;var D,E,f,M,F,n,O,C;var y;var u=this.renderer;var s=(j!=undefined)?j:{};var k=(s.shadow!=undefined)?s.shadow:this.shadow;var B=(s.fill!=undefined)?s.fill:this.fill;var c=(s.fillAndStroke!=undefined)?s.fillAndStroke:this.fillAndStroke;u.bodyWidth=(s.bodyWidth!=undefined)?s.bodyWidth:u.bodyWidth;u.tickLength=(s.tickLength!=undefined)?s.tickLength:u.tickLength;A.save();if(this.show){var m,q,g,Q,t;for(var D=0;Dq){if(u.wickColor){y.color=u.wickColor}else{if(u.downBodyColor){y.color=u.downBodyColor}}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,[[m,g],[m,q]],f);u.shapeRenderer.draw(A,[[m,t],[m,Q]],f);y={};M=q;F=t-q;if(u.fillDownBody){y.fillRect=true}else{y.strokeRect=true;n=n-this.lineWidth;O=m-n/2}if(u.downBodyColor){y.color=u.downBodyColor;y.fillStyle=u.downBodyColor}C=[O,M,n,F]}else{if(u.wickColor){y.color=u.wickColor}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,[[m,g],[m,Q]],f);y={};y.fillRect=false;y.strokeRect=false;O=[m-n/2,q];M=[m+n/2,t];n=null;F=null;C=[O,M]}}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,C,f)}else{E=s.color;if(u.openColor){s.color=u.openColor}if(!u.hlc){u.shapeRenderer.draw(A,[[m-u._tickLength,q],[m,q]],s)}s.color=E;if(u.wickColor){s.color=u.wickColor}u.shapeRenderer.draw(A,[[m,g],[m,Q]],s);s.color=E;if(u.closeColor){s.color=u.closeColor}u.shapeRenderer.draw(A,[[m,t],[m+u._tickLength,t]],s);s.color=E}}}A.restore()};a.jqplot.OHLCRenderer.prototype.drawShadow=function(b,d,c){};a.jqplot.OHLCRenderer.checkOptions=function(d,c,b){if(!b.highlighter){b.highlighter={showMarker:false,tooltipAxes:"y",yvalues:4,formatString:'
    date:%s
    open:%s
    hi:%s
    low:%s
    close:%s
    '}}}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(a){a.jqplot.CanvasAxisLabelRenderer=function(b){this.angle=0;this.axis;this.show=true;this.showLabel=true;this.label="";this.fontFamily='"Trebuchet MS", Arial, Helvetica, sans-serif';this.fontSize="11pt";this.fontWeight="normal";this.fontStretch=1;this.textColor="#666666";this.enableFontSupport=true;this.pt2px=null;this._elem;this._ctx;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null};a.extend(true,this,b);if(b.angle==null&&this.axis!="xaxis"&&this.axis!="x2axis"){this.angle=-90}var c={fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily};if(this.pt2px){c.pt2px=this.pt2px}if(this.enableFontSupport){if(a.jqplot.support_canvas_text()){this._textRenderer=new a.jqplot.CanvasFontRenderer(c)}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}};a.jqplot.CanvasAxisLabelRenderer.prototype.init=function(b){a.extend(true,this,b);this._textRenderer.init({fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily})};a.jqplot.CanvasAxisLabelRenderer.prototype.getWidth=function(d){if(this._elem){return this._elem.outerWidth(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.sin(f.angle)*e)+Math.abs(Math.cos(f.angle)*c);return b}};a.jqplot.CanvasAxisLabelRenderer.prototype.getHeight=function(d){if(this._elem){return this._elem.outerHeight(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.cos(f.angle)*e)+Math.abs(Math.sin(f.angle)*c);return b}};a.jqplot.CanvasAxisLabelRenderer.prototype.getAngleRad=function(){var b=this.angle*Math.PI/180;return b};a.jqplot.CanvasAxisLabelRenderer.prototype.draw=function(c,f){if(this._elem){if(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==undefined){window.G_vmlCanvasManager.uninitElement(this._elem.get(0))}this._elem.emptyForce();this._elem=null}var e=f.canvasManager.getCanvas();this._textRenderer.setText(this.label,c);var b=this.getWidth(c);var d=this.getHeight(c);e.width=b;e.height=d;e.style.width=b;e.style.height=d;e=f.canvasManager.initCanvas(e);this._elem=a(e);this._elem.css({position:"absolute"});this._elem.addClass("jqplot-"+this.axis+"-label");e=null;return this._elem};a.jqplot.CanvasAxisLabelRenderer.prototype.pack=function(){this._textRenderer.draw(this._elem.get(0).getContext("2d"),this.label)}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(e){e.jqplot.DonutRenderer=function(){e.jqplot.LineRenderer.call(this)};e.jqplot.DonutRenderer.prototype=new e.jqplot.LineRenderer();e.jqplot.DonutRenderer.prototype.constructor=e.jqplot.DonutRenderer;e.jqplot.DonutRenderer.prototype.init=function(p,t){this.diameter=null;this.innerDiameter=null;this.thickness=null;this.padding=20;this.sliceMargin=0;this.ringMargin=null;this.fill=true;this.shadowOffset=2;this.shadowAlpha=0.07;this.shadowDepth=5;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.dataLabels="percent";this.showDataLabels=false;this.dataLabelFormatString=null;this.dataLabelThreshold=3;this.dataLabelPositionFactor=0.4;this.dataLabelNudge=0;this.startAngle=0;this.tickRenderer=e.jqplot.DonutTickRenderer;this._drawData=true;this._type="donut";if(p.highlightMouseDown&&p.highlightMouseOver==null){p.highlightMouseOver=false}e.extend(true,this,p);if(this.diameter!=null){this.diameter=this.diameter-this.sliceMargin}this._diameter=null;this._innerDiameter=null;this._radius=null;this._innerRadius=null;this._thickness=null;this._previousSeries=[];this._numberSeries=1;this._sliceAngles=[];this._highlightedPoint=null;if(this.highlightColors.length==0){for(var r=0;r570)?n[o]*0.8:n[o]+0.3*(255-n[o]);n[o]=parseInt(n[o],10)}this.highlightColors.push("rgb("+n[0]+","+n[1]+","+n[2]+")")}}t.postParseOptionsHooks.addOnce(l);t.postInitHooks.addOnce(g);t.eventListenerHooks.addOnce("jqplotMouseMove",b);t.eventListenerHooks.addOnce("jqplotMouseDown",a);t.eventListenerHooks.addOnce("jqplotMouseUp",j);t.eventListenerHooks.addOnce("jqplotClick",f);t.eventListenerHooks.addOnce("jqplotRightClick",m);t.postDrawHooks.addOnce(h)};e.jqplot.DonutRenderer.prototype.setGridData=function(s){var o=[];var t=[];var n=this.startAngle/180*Math.PI;var r=0;this._drawData=false;for(var q=0;q0){o[q]+=o[q-1]}r+=this.data[q][1]}var p=Math.PI*2/o[o.length-1];for(var q=0;q0){o[q]+=o[q-1]}r+=s[q][1]}var p=Math.PI*2/o[o.length-1];for(var q=0;q6.282+this.startAngle){t=6.282+this.startAngle;if(u>t){u=6.281+this.startAngle}}if(u>=t){return}x.beginPath();x.fillStyle=p;x.strokeStyle=p;x.arc(0,0,n,u,t,false);x.lineTo(v*Math.cos(t),v*Math.sin(t));x.arc(0,0,v,t,u,true);x.closePath();if(w){x.fill()}else{x.stroke()}}if(s){for(var q=0;q1&&this.index>0)?this._previousSeries[0]._diameter:this._diameter;this._thickness=this.thickness||(M-this.innerDiameter-2*X*this._numberSeries)/this._numberSeries/2}else{this._thickness=this.thickness||v/2/(this._numberSeries+1)*0.85}var K=this._radius=this._diameter/2;this._innerRadius=this._radius-this._thickness;var o=this.startAngle/180*Math.PI;this._center=[(s-u*q)/2+u*q,(H-u*p)/2+u*p];if(this.shadow){var L="rgba(0,0,0,"+this.shadowAlpha+")";for(var Q=0;Q=this.dataLabelThreshold){var S,U=(A+z)/2,C;if(this.dataLabels=="label"){S=this.dataLabelFormatString||"%s";C=e.jqplot.sprintf(S,V[Q][0])}else{if(this.dataLabels=="value"){S=this.dataLabelFormatString||"%d";C=e.jqplot.sprintf(S,this.data[Q][1])}else{if(this.dataLabels=="percent"){S=this.dataLabelFormatString||"%d%%";C=e.jqplot.sprintf(S,V[Q][2]*100)}else{if(this.dataLabels.constructor==Array){S=this.dataLabelFormatString||"%s";C=e.jqplot.sprintf(S,this.dataLabels[Q])}}}}var n=this._innerRadius+this._thickness*this.dataLabelPositionFactor+this.sliceMargin+this.dataLabelNudge;var F=this._center[0]+Math.cos(U)*n+this.canvas._offsets.left;var E=this._center[1]+Math.sin(U)*n+this.canvas._offsets.top;var D=e(''+C+"").insertBefore(P.eventCanvas._elem);F-=D.width()/2;E-=D.height()/2;F=Math.round(F);E=Math.round(E);D.css({left:F,top:E})}}};e.jqplot.DonutAxisRenderer=function(){e.jqplot.LinearAxisRenderer.call(this)};e.jqplot.DonutAxisRenderer.prototype=new e.jqplot.LinearAxisRenderer();e.jqplot.DonutAxisRenderer.prototype.constructor=e.jqplot.DonutAxisRenderer;e.jqplot.DonutAxisRenderer.prototype.init=function(n){this.tickRenderer=e.jqplot.DonutTickRenderer;e.extend(true,this,n);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};e.jqplot.DonutLegendRenderer=function(){e.jqplot.TableLegendRenderer.call(this)};e.jqplot.DonutLegendRenderer.prototype=new e.jqplot.TableLegendRenderer();e.jqplot.DonutLegendRenderer.prototype.constructor=e.jqplot.DonutLegendRenderer;e.jqplot.DonutLegendRenderer.prototype.init=function(n){this.numberRows=null;this.numberColumns=null;e.extend(true,this,n)};e.jqplot.DonutLegendRenderer.prototype.draw=function(){var q=this;if(this.show){var y=this._series;var B="position:absolute;";B+=(this.background)?"background:"+this.background+";":"";B+=(this.border)?"border:"+this.border+";":"";B+=(this.fontSize)?"font-size:"+this.fontSize+";":"";B+=(this.fontFamily)?"font-family:"+this.fontFamily+";":"";B+=(this.textColor)?"color:"+this.textColor+";":"";B+=(this.marginTop!=null)?"margin-top:"+this.marginTop+";":"";B+=(this.marginBottom!=null)?"margin-bottom:"+this.marginBottom+";":"";B+=(this.marginLeft!=null)?"margin-left:"+this.marginLeft+";":"";B+=(this.marginRight!=null)?"margin-right:"+this.marginRight+";":"";this._elem=e('
    ');var F=false,x=false,n,v;var z=y[0];var o=new e.jqplot.ColorGenerator(z.seriesColors);if(z.show){var G=z.data;if(this.numberRows){n=this.numberRows;if(!this.numberColumns){v=Math.ceil(G.length/n)}else{v=this.numberColumns}}else{if(this.numberColumns){v=this.numberColumns;n=Math.ceil(G.length/this.numberColumns)}else{n=G.length;v=1}}var E,D,p,t,r,u,w,C;var A=0;for(E=0;E').prependTo(this._elem)}else{p=e('').appendTo(this._elem)}for(D=0;D0){F=true}else{F=false}}else{if(E==n-1){F=false}else{F=true}}w=(F)?this.rowSpacing:"0";t=e('
    ');r=e('');if(this.escapeHtml){r.text(u)}else{r.html(u)}if(x){r.prependTo(p);t.prependTo(p)}else{t.appendTo(p);r.appendTo(p)}F=true}A++}}}}return this._elem};function c(r,q,o){o=o||{};o.axesDefaults=o.axesDefaults||{};o.legend=o.legend||{};o.seriesDefaults=o.seriesDefaults||{};var n=false;if(o.seriesDefaults.renderer==e.jqplot.DonutRenderer){n=true}else{if(o.series){for(var p=0;p")}k=a.extend(true,{},this.css,k);c=a('
    ');this.canvas._elem.append(c);this.escapeHtml?c.text(p):c.html(p);delete k.position;delete k.marginRight;delete k.marginLeft;if(!k.background&&!k.backgroundColor&&!k.backgroundImage){k.background=j.next()}c.css(k);n=c.outerWidth();g=c.outerHeight();e=o[0]-n/2+"px";m=o[1]-g/2+"px";c.css({left:e,top:m});c=null}};a.jqplot.BlockCanvas=function(){a.jqplot.ElemContainer.call(this);this._ctx};a.jqplot.BlockCanvas.prototype=new a.jqplot.ElemContainer();a.jqplot.BlockCanvas.prototype.constructor=a.jqplot.BlockCanvas;a.jqplot.BlockCanvas.prototype.createElement=function(i,e,c){this._offsets=i;var b="jqplot-blockCanvas";if(e!=undefined){b=e}var g;if(this._elem){g=this._elem.get(0)}else{g=document.createElement("div")}if(c!=undefined){this._plotDimensions=c}var d=this._plotDimensions.width-this._offsets.left-this._offsets.right+"px";var f=this._plotDimensions.height-this._offsets.top-this._offsets.bottom+"px";this._elem=a(g);this._elem.css({position:"absolute",width:d,height:f,left:this._offsets.left,top:this._offsets.top});this._elem.addClass(b);return this._elem};a.jqplot.BlockCanvas.prototype.setContext=function(){this._ctx={canvas:{width:0,height:0},clearRect:function(){return null}};return this._ctx}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(a){a.jqplot.PyramidGridRenderer=function(){a.jqplot.CanvasGridRenderer.call(this)};a.jqplot.PyramidGridRenderer.prototype=new a.jqplot.CanvasGridRenderer();a.jqplot.PyramidGridRenderer.prototype.constructor=a.jqplot.PyramidGridRenderer;a.jqplot.CanvasGridRenderer.prototype.init=function(c){this._ctx;this.plotBands={show:false,color:"rgb(230, 219, 179)",axis:"y",start:null,interval:10};a.extend(true,this,c);var b={lineJoin:"miter",lineCap:"round",fill:false,isarc:false,angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.shadowWidth,closePath:false,strokeStyle:this.shadowColor};this.renderer.shadowRenderer.init(b)};a.jqplot.PyramidGridRenderer.prototype.draw=function(){this._ctx=this._elem.get(0).getContext("2d");var D=this._ctx;var G=this._axes;var q=G.xaxis.u2p;var J=G.yMidAxis.u2p;var l=G.xaxis.max/1000;var u=q(0);var f=q(l);var r=["xaxis","yaxis","x2axis","y2axis","yMidAxis"];D.save();D.clearRect(0,0,this._plotDimensions.width,this._plotDimensions.height);D.fillStyle=this.backgroundColor||this.background;D.fillRect(this._left,this._top,this._width,this._height);if(this.plotBands.show){D.save();var c=this.plotBands;D.fillStyle=c.color;var d;var o,n,p,I;if(c.axis.charAt(0)==="x"){if(G.xaxis.show){d=G.xaxis}}else{if(c.axis.charAt(0)==="y"){if(G.yaxis.show){d=G.yaxis}else{if(G.y2axis.show){d=G.y2axis}else{if(G.yMidAxis.show){d=G.yMidAxis}}}}}if(d!==undefined){var g=c.start;if(g===null){g=d.min}for(var H=g;H0;H--){var O=r[H-1];var d=G[O];var M=d._ticks;var B=M.length;if(d.show){if(d.drawBaseline){var N={};if(d.baselineWidth!==null){N.lineWidth=d.baselineWidth}if(d.baselineColor!==null){N.strokeStyle=d.baselineColor}switch(O){case"xaxis":if(G.yMidAxis.show){z(this._left,this._bottom,u,this._bottom,N);z(f,this._bottom,this._right,this._bottom,N)}else{z(this._left,this._bottom,this._right,this._bottom,N)}break;case"yaxis":z(this._left,this._bottom,this._left,this._top,N);break;case"yMidAxis":z(u,this._bottom,u,this._top,N);z(f,this._bottom,f,this._top,N);break;case"x2axis":if(G.yMidAxis.show){z(this._left,this._top,u,this._top,N);z(f,this._top,this._right,this._top,N)}else{z(this._left,this._bottom,this._right,this._bottom,N)}break;case"y2axis":z(this._right,this._bottom,this._right,this._top,N);break}}for(var E=B;E>0;E--){var v=M[E-1];if(v.show){var k=Math.round(d.u2p(v.value))+0.5;switch(O){case"xaxis":if(v.showGridline&&this.drawGridlines&&(!v.isMinorTick||d.showMinorTicks)){z(k,this._top,k,this._bottom)}if(v.showMark&&v.mark&&(!v.isMinorTick||d.showMinorTicks)){A=v.markSize;C=v.mark;var k=Math.round(d.u2p(v.value))+0.5;switch(C){case"outside":L=this._bottom;K=this._bottom+A;break;case"inside":L=this._bottom-A;K=this._bottom;break;case"cross":L=this._bottom-A;K=this._bottom+A;break;default:L=this._bottom;K=this._bottom+A;break}if(this.shadow){this.renderer.shadowRenderer.draw(D,[[k,L],[k,K]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:this.gridLineWidth*0.75,depth:2,fill:false,closePath:false})}z(k,L,k,K)}break;case"yaxis":if(v.showGridline&&this.drawGridlines&&(!v.isMinorTick||d.showMinorTicks)){z(this._right,k,this._left,k)}if(v.showMark&&v.mark&&(!v.isMinorTick||d.showMinorTicks)){A=v.markSize;C=v.mark;var k=Math.round(d.u2p(v.value))+0.5;switch(C){case"outside":L=this._left-A;K=this._left;break;case"inside":L=this._left;K=this._left+A;break;case"cross":L=this._left-A;K=this._left+A;break;default:L=this._left-A;K=this._left;break}if(this.shadow){this.renderer.shadowRenderer.draw(D,[[L,k],[K,k]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}z(L,k,K,k,{strokeStyle:d.borderColor})}break;case"yMidAxis":if(v.showGridline&&this.drawGridlines&&(!v.isMinorTick||d.showMinorTicks)){z(this._left,k,u,k);z(f,k,this._right,k)}if(v.showMark&&v.mark&&(!v.isMinorTick||d.showMinorTicks)){A=v.markSize;C=v.mark;var k=Math.round(d.u2p(v.value))+0.5;L=u;K=u+A;if(this.shadow){this.renderer.shadowRenderer.draw(D,[[L,k],[K,k]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}z(L,k,K,k,{strokeStyle:d.borderColor});L=f-A;K=f;if(this.shadow){this.renderer.shadowRenderer.draw(D,[[L,k],[K,k]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}z(L,k,K,k,{strokeStyle:d.borderColor})}break;case"x2axis":if(v.showGridline&&this.drawGridlines&&(!v.isMinorTick||d.showMinorTicks)){z(k,this._bottom,k,this._top)}if(v.showMark&&v.mark&&(!v.isMinorTick||d.showMinorTicks)){A=v.markSize;C=v.mark;var k=Math.round(d.u2p(v.value))+0.5;switch(C){case"outside":L=this._top-A;K=this._top;break;case"inside":L=this._top;K=this._top+A;break;case"cross":L=this._top-A;K=this._top+A;break;default:L=this._top-A;K=this._top;break}if(this.shadow){this.renderer.shadowRenderer.draw(D,[[k,L],[k,K]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:this.gridLineWidth*0.75,depth:2,fill:false,closePath:false})}z(k,L,k,K)}break;case"y2axis":if(v.showGridline&&this.drawGridlines&&(!v.isMinorTick||d.showMinorTicks)){z(this._left,k,this._right,k)}if(v.showMark&&v.mark&&(!v.isMinorTick||d.showMinorTicks)){A=v.markSize;C=v.mark;var k=Math.round(d.u2p(v.value))+0.5;switch(C){case"outside":L=this._right;K=this._right+A;break;case"inside":L=this._right-A;K=this._right;break;case"cross":L=this._right-A;K=this._right+A;break;default:L=this._right;K=this._right+A;break}if(this.shadow){this.renderer.shadowRenderer.draw(D,[[L,k],[K,k]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}z(L,k,K,k,{strokeStyle:d.borderColor})}break;default:break}}}v=null}d=null;M=null}D.restore();function z(j,i,e,b,h){D.save();h=h||{};if(h.lineWidth==null||h.lineWidth!=0){a.extend(true,D,h);D.beginPath();D.moveTo(j,i);D.lineTo(e,b);D.stroke()}D.restore()}if(this.shadow){if(G.yMidAxis.show){var F=[[this._left,this._bottom],[u,this._bottom]];this.renderer.shadowRenderer.draw(D,F);var F=[[f,this._bottom],[this._right,this._bottom],[this._right,this._top]];this.renderer.shadowRenderer.draw(D,F);var F=[[u,this._bottom],[u,this._top]];this.renderer.shadowRenderer.draw(D,F)}else{var F=[[this._left,this._bottom],[this._right,this._bottom],[this._right,this._top]];this.renderer.shadowRenderer.draw(D,F)}}if(this.borderWidth!=0&&this.drawBorder){if(G.yMidAxis.show){z(this._left,this._top,u,this._top,{lineCap:"round",strokeStyle:G.x2axis.borderColor,lineWidth:G.x2axis.borderWidth});z(f,this._top,this._right,this._top,{lineCap:"round",strokeStyle:G.x2axis.borderColor,lineWidth:G.x2axis.borderWidth});z(this._right,this._top,this._right,this._bottom,{lineCap:"round",strokeStyle:G.y2axis.borderColor,lineWidth:G.y2axis.borderWidth});z(this._right,this._bottom,f,this._bottom,{lineCap:"round",strokeStyle:G.xaxis.borderColor,lineWidth:G.xaxis.borderWidth});z(u,this._bottom,this._left,this._bottom,{lineCap:"round",strokeStyle:G.xaxis.borderColor,lineWidth:G.xaxis.borderWidth});z(this._left,this._bottom,this._left,this._top,{lineCap:"round",strokeStyle:G.yaxis.borderColor,lineWidth:G.yaxis.borderWidth});z(u,this._bottom,u,this._top,{lineCap:"round",strokeStyle:G.yaxis.borderColor,lineWidth:G.yaxis.borderWidth});z(f,this._bottom,f,this._top,{lineCap:"round",strokeStyle:G.yaxis.borderColor,lineWidth:G.yaxis.borderWidth})}else{z(this._left,this._top,this._right,this._top,{lineCap:"round",strokeStyle:G.x2axis.borderColor,lineWidth:G.x2axis.borderWidth});z(this._right,this._top,this._right,this._bottom,{lineCap:"round",strokeStyle:G.y2axis.borderColor,lineWidth:G.y2axis.borderWidth});z(this._right,this._bottom,this._left,this._bottom,{lineCap:"round",strokeStyle:G.xaxis.borderColor,lineWidth:G.xaxis.borderWidth});z(this._left,this._bottom,this._left,this._top,{lineCap:"round",strokeStyle:G.yaxis.borderColor,lineWidth:G.yaxis.borderWidth})}}D.restore();D=null;G=null}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(c){if(c.jqplot.PyramidAxisRenderer===undefined){c.ajax({url:c.jqplot.pluginLocation+"jqplot.pyramidAxisRenderer.js",dataType:"script",async:false})}if(c.jqplot.PyramidGridRenderer===undefined){c.ajax({url:c.jqplot.pluginLocation+"jqplot.pyramidGridRenderer.js",dataType:"script",async:false})}c.jqplot.PyramidRenderer=function(){c.jqplot.LineRenderer.call(this)};c.jqplot.PyramidRenderer.prototype=new c.jqplot.LineRenderer();c.jqplot.PyramidRenderer.prototype.constructor=c.jqplot.PyramidRenderer;c.jqplot.PyramidRenderer.prototype.init=function(j,o){j=j||{};this._type="pyramid";this.barPadding=10;this.barWidth=null;this.fill=true;this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColors=[];this.highlightThreshold=2;this.synchronizeHighlight=false;this.offsetBars=false;if(j.highlightMouseDown&&j.highlightMouseOver==null){j.highlightMouseOver=false}this.side="right";c.extend(true,this,j);if(this.side==="left"){this._highlightThreshold=[[-this.highlightThreshold,0],[-this.highlightThreshold,0],[0,0],[0,0]]}else{this._highlightThreshold=[[0,0],[0,0],[this.highlightThreshold,0],[this.highlightThreshold,0]]}this.renderer.options=j;this._highlightedPoint=null;this._dataColors=[];this._barPoints=[];this.fillAxis="y";this._primaryAxis="_yaxis";this._xnudge=0;var n={lineJoin:"miter",lineCap:"butt",fill:this.fill,fillRect:this.fill,isarc:false,strokeStyle:this.color,fillStyle:this.color,closePath:this.fill,lineWidth:this.lineWidth};this.renderer.shapeRenderer.init(n);var m=j.shadowOffset;if(m==null){if(this.lineWidth>2.5){m=1.25*(1+(Math.atan((this.lineWidth/2.5))/0.785398163-1)*0.6)}else{m=1.25*Math.atan((this.lineWidth/2.5))/0.785398163}}var h={lineJoin:"miter",lineCap:"butt",fill:this.fill,fillRect:this.fill,isarc:false,angle:this.shadowAngle,offset:m,alpha:this.shadowAlpha,depth:this.shadowDepth,closePath:this.fill,lineWidth:this.lineWidth};this.renderer.shadowRenderer.init(h);o.postDrawHooks.addOnce(f);o.eventListenerHooks.addOnce("jqplotMouseMove",e);if(this.side==="left"){for(var k=0,g=this.data.length;k=0){s=I[E][0]-L;F=this.barWidth;D=[L,n-y-r,s,F]}else{s=L-I[E][0];F=this.barWidth;D=[I[E][0],n-y-r,s,F]}this._barPoints.push([[D[0],D[1]+F],[D[0],D[1]],[D[0]+s,D[1]],[D[0]+s,D[1]+F]]);if(p){this.renderer.shadowRenderer.draw(B,D)}var g=u.fillStyle||this.color;this._dataColors.push(g);this.renderer.shapeRenderer.draw(B,D,u)}else{if(E===0){D=[[L,j],[I[E][0],j],[I[E][0],I[E][1]-y-r]]}else{if(E=h.synchronizeHighlight&&h.synchronizeHighlight!==l){h=m.series[h.synchronizeHighlight];k={fillStyle:h.highlightColors[j],fillRect:false};h.renderer.shapeRenderer.draw(g._ctx,h._barPoints[j],k)}g=null}function d(j){var g=j.plugins.pyramidRenderer.highlightCanvas;g._ctx.clearRect(0,0,g._ctx.canvas.width,g._ctx.canvas.height);for(var h=0;hb.max||b.max==null){b.max=h[c][0]}}else{if(h[c][1]b.max||b.max==null){b.max=h[c][1]}}}}if(this.groupLabels.length){this.groups=this.groupLabels.length}};a.jqplot.CategoryAxisRenderer.prototype.createTicks=function(){var D=this._ticks;var z=this.ticks;var F=this.name;var C=this._dataBounds;var v,A;var q,w;var d,c;var b,x;if(z.length){if(this.groups>1&&!this._grouped){var r=z.length;var p=parseInt(r/this.groups,10);var e=0;for(var x=p;x1&&!this._grouped){var r=y.length;var p=parseInt(r/this.groups,10);var e=0;for(var x=p;x0&&o');if(this.name=="xaxis"||this.name=="x2axis"){this._elem.width(this._plotDimensions.width)}else{this._elem.height(this._plotDimensions.height)}this.labelOptions.axis=this.name;this._label=new this.labelRenderer(this.labelOptions);if(this._label.show){var g=this._label.draw(b,j);g.appendTo(this._elem)}var f=this._ticks;for(var e=0;e');g.html(this.groupLabels[e]);this._groupLabels.push(g);g.appendTo(this._elem)}}return this._elem};a.jqplot.CategoryAxisRenderer.prototype.set=function(){var e=0;var m;var k=0;var f=0;var d=(this._label==null)?false:this._label.show;if(this.show){var n=this._ticks;for(var c=0;ce){e=m}}}var j=0;for(var c=0;cj){j=m}}if(d){k=this._label._elem.outerWidth(true);f=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){e+=j+f;this._elem.css({height:e+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){e+=j+f;this._elem.css({height:e+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){e+=j+k;this._elem.css({width:e+"px",left:"0px",top:"0px"});if(d&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",k+"px")}}else{e+=j+k;this._elem.css({width:e+"px",right:"0px",top:"0px"});if(d&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",k+"px")}}}}}};a.jqplot.CategoryAxisRenderer.prototype.pack=function(e,c){var C=this._ticks;var v=this.max;var s=this.min;var n=c.max;var l=c.min;var q=(this._label==null)?false:this._label.show;var x;for(var r in e){this._elem.css(r,e[r])}this._offsets=c;var g=n-l;var k=v-s;if(!this.reverse){this.u2p=function(h){return(h-s)*g/k+l};this.p2u=function(h){return(h-l)*k/g+s};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(h){return(h-s)*g/k};this.series_p2u=function(h){return h*k/g+s}}else{this.series_u2p=function(h){return(h-v)*g/k};this.series_p2u=function(h){return h*k/g+v}}}else{this.u2p=function(h){return l+(v-h)*g/k};this.p2u=function(h){return s+(h-l)*k/g};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(h){return(v-h)*g/k};this.series_p2u=function(h){return h*k/g+v}}else{this.series_u2p=function(h){return(s-h)*g/k};this.series_p2u=function(h){return h*k/g+s}}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(x=0;x=this._ticks.length-1){continue}if(this._ticks[u]._elem&&this._ticks[u].label!=" "){var o=this._ticks[u]._elem;var r=o.position();B+=r.left+o.outerWidth(true)/2;f++}}B=B/f;this._groupLabels[x].css({left:(B-this._groupLabels[x].outerWidth(true)/2)});this._groupLabels[x].css(z[0],z[1])}}else{for(x=0;x0){b=-o._textRenderer.height*Math.cos(-o._textRenderer.angle)/2}else{b=-o.getHeight()+o._textRenderer.height*Math.cos(o._textRenderer.angle)/2}break;case"middle":b=-o.getHeight()/2;break;default:b=-o.getHeight()/2;break}}else{b=-o.getHeight()/2}var D=this.u2p(o.value)+b+"px";o._elem.css("top",D);o.pack()}}var z=["left",0];if(q){var y=this._label._elem.outerHeight(true);this._label._elem.css("top",n-g/2-y/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px");z=["left",this._label._elem.outerWidth(true)]}else{this._label._elem.css("right","0px");z=["right",this._label._elem.outerWidth(true)]}this._label.pack()}var d=parseInt(this._ticks.length/this.groups,10)+1;for(x=0;x=this._ticks.length-1){continue}if(this._ticks[u]._elem&&this._ticks[u].label!=" "){var o=this._ticks[u]._elem;var r=o.position();B+=r.top+o.outerHeight()/2;f++}}B=B/f;this._groupLabels[x].css({top:B-this._groupLabels[x].outerHeight()/2});this._groupLabels[x].css(z[0],z[1])}}}}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(h){h.jqplot.DateAxisRenderer=function(){h.jqplot.LinearAxisRenderer.call(this);this.date=new h.jsDate()};var c=1000;var e=60*c;var f=60*e;var l=24*f;var b=7*l;var j=30.4368499*l;var k=365.242199*l;var g=[31,28,31,30,31,30,31,30,31,30,31,30];var i=["%M:%S.%#N","%M:%S.%#N","%M:%S.%#N","%M:%S","%M:%S","%M:%S","%M:%S","%H:%M:%S","%H:%M:%S","%H:%M","%H:%M","%H:%M","%H:%M","%H:%M","%H:%M","%a %H:%M","%a %H:%M","%b %e %H:%M","%b %e %H:%M","%b %e %H:%M","%b %e %H:%M","%v","%v","%v","%v","%v","%v","%v"];var m=[0.1*c,0.2*c,0.5*c,c,2*c,5*c,10*c,15*c,30*c,e,2*e,5*e,10*e,15*e,30*e,f,2*f,4*f,6*f,8*f,12*f,l,2*l,3*l,4*l,5*l,b,2*b];var d=[];function a(p,s,t){var o=Number.MAX_VALUE;var u,r,v;for(var q=0,n=m.length;qC.max)||C.max==null){C.max=y[r][0]}if(r>0){o=Math.abs(y[r][0]-y[r-1][0]);u.intervals.push(o);if(u.frequencies.hasOwnProperty(o)){u.frequencies[o]+=1}else{u.frequencies[o]=1}}x+=o}else{y[r][1]=new h.jsDate(y[r][1]).getTime();A[r][1]=new h.jsDate(y[r][1]).getTime();z[r][1]=new h.jsDate(y[r][1]).getTime();if((y[r][1]!=null&&y[r][1]C.max)||C.max==null){C.max=y[r][1]}if(r>0){o=Math.abs(y[r][1]-y[r-1][1]);u.intervals.push(o);if(u.frequencies.hasOwnProperty(o)){u.frequencies[o]+=1}else{u.frequencies[o]=1}}}x+=o}if(D.renderer.bands){if(D.renderer.bands.hiData.length){var w=D.renderer.bands.hiData;for(var r=0,q=w.length;rC.max)||C.max==null){C.max=w[r][0]}}else{w[r][1]=new h.jsDate(w[r][1]).getTime();if((w[r][1]!=null&&w[r][1]>C.max)||C.max==null){C.max=w[r][1]}}}}if(D.renderer.bands.lowData.length){var w=D.renderer.bands.lowData;for(var r=0,q=w.length;r6){D=6}}var V=new h.jsDate(ae).setDate(1).setHours(0,0,0,0);var q=new h.jsDate(J);var z=new h.jsDate(J).setDate(1).setHours(0,0,0,0);if(q.getTime()!==z.getTime()){z=z.add(1,"month")}var S=z.diff(V,"month");ab=Math.ceil(S/D)+1;this.min=V.getTime();this.max=V.clone().add((ab-1)*D,"month").getTime();this.numberTicks=ab;for(var aa=0;aa200){this.numberTicks=parseInt(3+(n-200)/100,10)}else{this.numberTicks=2}}}O=B/(this.numberTicks-1)/1000;if(this.daTickInterval==null){this.daTickInterval=[O,"seconds"]}for(var aa=0;aat){y=w;w=t;t=y}if(v>s){y=v;v=s;s=y}var u=(o>=w&&o<=t&&n>=v&&n<=s);return u}function a(z,w,r,A,x){var y=x.plugins.canvasOverlay;var v=y.objects;var s=v.length;var u,o=false;var q;for(var t=0;t');if(this.seriesToggle){this._elem.css("z-index","3")}var C=false,q=false,d,o;if(this.numberRows){d=this.numberRows;if(!this.numberColumns){o=Math.ceil(r.length/d)}else{o=this.numberColumns}}else{if(this.numberColumns){o=this.numberColumns;d=Math.ceil(r.length/this.numberColumns)}else{d=r.length;o=1}}var B,z,e,l,k,n,p,t,h,g;var v=0;for(B=r.length-1;B>=0;B--){if(o==1&&r[B]._stack||r[B].renderer.constructor==c.jqplot.BezierCurveRenderer){q=true}}for(B=0;B0){C=true}else{C=false}}else{if(B==d-1){C=false}else{C=true}}p=(C)?this.rowSpacing:"0";l=c(document.createElement("td"));l.addClass("jqplot-table-legend jqplot-table-legend-swatch");l.css({textAlign:"center",paddingTop:p});h=c(document.createElement("div"));h.addClass("jqplot-table-legend-swatch-outline");g=c(document.createElement("div"));g.addClass("jqplot-table-legend-swatch");g.css({backgroundColor:x,borderColor:x});l.append(h.append(g));k=c(document.createElement("td"));k.addClass("jqplot-table-legend jqplot-table-legend-label");k.css("paddingTop",p);if(this.escapeHtml){k.text(n)}else{k.html(n)}if(q){if(this.showLabels){k.prependTo(e)}if(this.showSwatches){l.prependTo(e)}}else{if(this.showSwatches){l.appendTo(e)}if(this.showLabels){k.appendTo(e)}}if(this.seriesToggle){var A;if(typeof(this.seriesToggle)==="string"||typeof(this.seriesToggle)==="number"){if(!c.jqplot.use_excanvas||!this.disableIEFading){A=this.seriesToggle}}if(this.showSwatches){l.bind("click",{series:u,speed:A,plot:y,replot:this.seriesToggleReplot},a);l.addClass("jqplot-seriesToggle")}if(this.showLabels){k.bind("click",{series:u,speed:A,plot:y,replot:this.seriesToggleReplot},a);k.addClass("jqplot-seriesToggle")}if(!u.show&&u.showLabel){l.addClass("jqplot-series-hidden");k.addClass("jqplot-series-hidden")}}C=true}}v++}l=k=h=g=null}}return this._elem};var a=function(j){var i=j.data,m=i.series,k=i.replot,h=i.plot,f=i.speed,l=m.index,g=false;if(m.canvas._elem.is(":hidden")||!m.show){g=true}var e=function(){if(k){var n={};if(c.isPlainObject(k)){c.extend(true,n,k)}h.replot(n);if(g&&f){var d=h.series[l];if(d.shadowCanvas._elem){d.shadowCanvas._elem.hide().fadeIn(f)}d.canvas._elem.hide().fadeIn(f);d.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+d.index).hide().fadeIn(f)}}else{var d=h.series[l];if(d.canvas._elem.is(":hidden")||!d.show){if(typeof h.options.legend.showSwatches==="undefined"||h.options.legend.showSwatches===true){h.legend._elem.find("td").eq(l*2).addClass("jqplot-series-hidden")}if(typeof h.options.legend.showLabels==="undefined"||h.options.legend.showLabels===true){h.legend._elem.find("td").eq((l*2)+1).addClass("jqplot-series-hidden")}}else{if(typeof h.options.legend.showSwatches==="undefined"||h.options.legend.showSwatches===true){h.legend._elem.find("td").eq(l*2).removeClass("jqplot-series-hidden")}if(typeof h.options.legend.showLabels==="undefined"||h.options.legend.showLabels===true){h.legend._elem.find("td").eq((l*2)+1).removeClass("jqplot-series-hidden")}}}};m.toggleDisplay(j,e)};var b=function(){if(this.legend.renderer.constructor==c.jqplot.EnhancedLegendRenderer&&this.legend.seriesToggle){var d=this.legend._elem.detach();this.eventCanvas._elem.after(d)}}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(a){a.jqplot.MekkoAxisRenderer=function(){};a.jqplot.MekkoAxisRenderer.prototype.init=function(c){this.tickMode;this.barLabelRenderer=a.jqplot.AxisLabelRenderer;this.barLabels=this.barLabels||[];this.barLabelOptions={};this.tickOptions=a.extend(true,{showGridline:false},this.tickOptions);this._barLabels=[];a.extend(true,this,c);if(this.name=="yaxis"){this.tickOptions.formatString=this.tickOptions.formatString||"%d%"}var b=this._dataBounds;b.min=0;if(this.name=="yaxis"||this.name=="y2axis"){b.max=100;this.tickMode="even"}else{if(this.name=="xaxis"){this.tickMode=(this.tickMode==null)?"bar":this.tickMode;for(var d=0;dk){k=d}}}if(b){c=this._label._elem.outerWidth(true);j=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){k=k+j;this._elem.css({height:k+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){k=k+j;this._elem.css({height:k+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){k=k+c;this._elem.css({width:k+"px",left:"0px",top:"0px"});if(b&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",c+"px")}}else{k=k+c;this._elem.css({width:k+"px",right:"0px",top:"0px"});if(b&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",c+"px")}}}}}};a.jqplot.MekkoAxisRenderer.prototype.createTicks=function(){var z=this._ticks;var w=this.ticks;var B=this.name;var y=this._dataBounds;var p,x;var n,r;var d,c;var h,b,s,q;if(w.length){for(s=0;s0){g=Math.max(Math.log(n)/Math.LN10,0.05)}n-=g;r+=g}var k=r-n;var m,o;var v,l,u;var f=[3,5,6,11,21];if(this.name=="yaxis"||this.name=="y2axis"){this.min=0;this.max=100;if(!this.numberTicks){if(this.tickInterval){this.numberTicks=3+Math.ceil(k/this.tickInterval)}else{v=2+Math.ceil((p-(this.tickSpacing-1))/this.tickSpacing);for(s=0;s1){l=u;continue}else{if(u<1){if(Math.abs(l-1)v){h=new this.tickRenderer(this.tickOptions);if(!this.showTicks){h.showLabel=false;h.showMark=false}else{if(!this.showTickMarks){h.showMark=false}}h.setTick(this.max,this.name);this._ticks.push(h)}}else{if(this.tickMode=="even"){this.min=0;this.max=this.max||y.max;var A=2+Math.ceil((p-(this.tickSpacing-1))/this.tickSpacing);k=this.max-this.min;this.numberTicks=A;this.tickInterval=k/(this.numberTicks-1);for(s=0;s0){c=-n._textRenderer.height*Math.cos(-n._textRenderer.angle)/2}else{c=-n.getHeight()+n._textRenderer.height*Math.cos(n._textRenderer.angle)/2}break;case"middle":c=-n.getHeight()/2;break;default:c=-n.getHeight()/2;break}}else{c=-n.getHeight()/2}var D=this.u2p(n.value)+c+"px";n._elem.css("top",D);n.pack()}}if(o){var z=this._label._elem.outerHeight(true);this._label._elem.css("top",m-f/2-z/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px")}else{this._label._elem.css("right","0px")}this._label.pack()}}}}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(j){j.jqplot.Cursor=function(q){this.style="crosshair";this.previousCursor="auto";this.show=j.jqplot.config.enablePlugins;this.showTooltip=true;this.followMouse=false;this.tooltipLocation="se";this.tooltipOffset=6;this.showTooltipGridPosition=false;this.showTooltipUnitPosition=true;this.showTooltipDataPosition=false;this.tooltipFormatString="%.4P, %.4P";this.useAxesFormatters=true;this.tooltipAxisGroups=[];this.zoom=false;this.zoomProxy=false;this.zoomTarget=false;this.looseZoom=true;this.clickReset=false;this.dblClickReset=true;this.showVerticalLine=false;this.showHorizontalLine=false;this.constrainZoomTo="none";this.shapeRenderer=new j.jqplot.ShapeRenderer();this._zoom={start:[],end:[],started:false,zooming:false,isZoomed:false,axes:{start:{},end:{}},gridpos:{},datapos:{}};this._tooltipElem;this.zoomCanvas;this.cursorCanvas;this.intersectionThreshold=2;this.showCursorLegend=false;this.cursorLegendFormatString=j.jqplot.Cursor.cursorLegendFormatString;this._oldHandlers={onselectstart:null,ondrag:null,onmousedown:null};this.constrainOutsideZoom=true;this.showTooltipOutsideZoom=false;this.onGrid=false;j.extend(true,this,q)};j.jqplot.Cursor.cursorLegendFormatString="%s x:%s, y:%s";j.jqplot.Cursor.init=function(t,s,r){var q=r||{};this.plugins.cursor=new j.jqplot.Cursor(q.cursor);var u=this.plugins.cursor;if(u.show){j.jqplot.eventListenerHooks.push(["jqplotMouseEnter",b]);j.jqplot.eventListenerHooks.push(["jqplotMouseLeave",f]);j.jqplot.eventListenerHooks.push(["jqplotMouseMove",i]);if(u.showCursorLegend){r.legend=r.legend||{};r.legend.renderer=j.jqplot.CursorLegendRenderer;r.legend.formatString=this.plugins.cursor.cursorLegendFormatString;r.legend.show=true}if(u.zoom){j.jqplot.eventListenerHooks.push(["jqplotMouseDown",a]);if(u.clickReset){j.jqplot.eventListenerHooks.push(["jqplotClick",k])}if(u.dblClickReset){j.jqplot.eventListenerHooks.push(["jqplotDblClick",c])}}this.resetZoom=function(){var x=this.axes;if(!u.zoomProxy){for(var w in x){x[w].reset();x[w]._ticks=[];if(u._zoom.axes[w]!==undefined){x[w]._autoFormatString=u._zoom.axes[w].tickFormatString}}this.redraw()}else{var v=this.plugins.cursor.zoomCanvas._ctx;v.clearRect(0,0,v.canvas.width,v.canvas.height);v=null}this.plugins.cursor._zoom.isZoomed=false;this.target.trigger("jqplotResetZoom",[this,this.plugins.cursor])};if(u.showTooltipDataPosition){u.showTooltipUnitPosition=false;u.showTooltipGridPosition=false;if(q.cursor.tooltipFormatString==undefined){u.tooltipFormatString=j.jqplot.Cursor.cursorLegendFormatString}}}};j.jqplot.Cursor.postDraw=function(){var x=this.plugins.cursor;if(x.zoomCanvas){x.zoomCanvas.resetCanvas();x.zoomCanvas=null}if(x.cursorCanvas){x.cursorCanvas.resetCanvas();x.cursorCanvas=null}if(x._tooltipElem){x._tooltipElem.emptyForce();x._tooltipElem=null}if(x.zoom){x.zoomCanvas=new j.jqplot.GenericCanvas();this.eventCanvas._elem.before(x.zoomCanvas.createElement(this._gridPadding,"jqplot-zoom-canvas",this._plotDimensions,this));x.zoomCanvas.setContext()}var v=document.createElement("div");x._tooltipElem=j(v);v=null;x._tooltipElem.addClass("jqplot-cursor-tooltip");x._tooltipElem.css({position:"absolute",display:"none"});if(x.zoomCanvas){x.zoomCanvas._elem.before(x._tooltipElem)}else{this.eventCanvas._elem.before(x._tooltipElem)}if(x.showVerticalLine||x.showHorizontalLine){x.cursorCanvas=new j.jqplot.GenericCanvas();this.eventCanvas._elem.before(x.cursorCanvas.createElement(this._gridPadding,"jqplot-cursor-canvas",this._plotDimensions,this));x.cursorCanvas.setContext()}if(x.showTooltipUnitPosition){if(x.tooltipAxisGroups.length===0){var t=this.series;var u;var q=[];for(var r=0;r6&&Math.abs(G.y-I._zoom.start[1])>6)||(I.constrainZoomTo=="x"&&Math.abs(G.x-I._zoom.start[0])>6)||(I.constrainZoomTo=="y"&&Math.abs(G.y-I._zoom.start[1])>6)){if(!C.plugins.cursor.zoomProxy){for(var y in t){if(I._zoom.axes[y]==undefined){I._zoom.axes[y]={};I._zoom.axes[y].numberTicks=F[y].numberTicks;I._zoom.axes[y].tickInterval=F[y].tickInterval;I._zoom.axes[y].daTickInterval=F[y].daTickInterval;I._zoom.axes[y].min=F[y].min;I._zoom.axes[y].max=F[y].max;I._zoom.axes[y].tickFormatString=(F[y].tickOptions!=null)?F[y].tickOptions.formatString:""}if((I.constrainZoomTo=="none")||(I.constrainZoomTo=="x"&&y.charAt(0)=="x")||(I.constrainZoomTo=="y"&&y.charAt(0)=="y")){z=t[y];if(z!=null){if(z>w[y]){v=w[y];x=z}else{D=w[y]-z;v=z;x=w[y]}q=F[y];H=null;if(q.alignTicks){if(q.name==="x2axis"&&C.axes.xaxis.show){H=C.axes.xaxis.numberTicks}else{if(q.name.charAt(0)==="y"&&q.name!=="yaxis"&&q.name!=="yMidAxis"&&C.axes.yaxis.show){H=C.axes.yaxis.numberTicks}}}if(this.looseZoom&&(F[y].renderer.constructor===j.jqplot.LinearAxisRenderer||F[y].renderer.constructor===j.jqplot.LogAxisRenderer)){J=j.jqplot.LinearTickGenerator(v,x,q._scalefact,H);if(F[y].tickInset&&J[0]F[y].max-F[y].tickInset*F[y].tickInterval){J[1]-=J[4];J[2]-=1}if(F[y].renderer.constructor===j.jqplot.LogAxisRenderer&&J[0]"}if(J.useAxesFormatters){for(var D=0;D"}w+=j.jqplot.sprintf(J.tooltipFormatString,t,z,x);N=true}}}}J._tooltipElem.html(w)}function g(C,A){var E=A.plugins.cursor;var z=E.cursorCanvas._ctx;z.clearRect(0,0,z.canvas.width,z.canvas.height);if(E.showVerticalLine){E.shapeRenderer.draw(z,[[C.x,0],[C.x,z.canvas.height]])}if(E.showHorizontalLine){E.shapeRenderer.draw(z,[[0,C.y],[z.canvas.width,C.y]])}var G=d(A,C.x,C.y);if(E.showCursorLegend){var r=j(A.targetId+" td.jqplot-cursor-legend-label");for(var B=0;B0;r--){s=v[r-1];if(q[s].show){u[s]=q[s].series_p2u(w[s.charAt(0)])}}return{offsets:t,gridPos:w,dataPos:u}}function h(z){var x=z.data.plot;var y=x.plugins.cursor;if(y.show&&y.zoom&&y._zoom.started&&!y.zoomTarget){z.preventDefault();var B=y.zoomCanvas._ctx;var v=o(z);var w=v.gridPos;var t=v.dataPos;y._zoom.gridpos=w;y._zoom.datapos=t;y._zoom.zooming=true;var u=w.x;var s=w.y;var A=B.canvas.height;var q=B.canvas.width;if(y.showTooltip&&!y.onGrid&&y.showTooltipOutsideZoom){e(w,t,x);if(y.followMouse){n(w,x)}}if(y.constrainZoomTo=="x"){y._zoom.end=[u,A]}else{if(y.constrainZoomTo=="y"){y._zoom.end=[q,s]}else{y._zoom.end=[u,s]}}var r=window.getSelection;if(document.selection&&document.selection.empty){document.selection.empty()}else{if(r&&!r().isCollapsed){r().collapse()}}l.call(y);B=null}}function a(w,s,r,x,t){var v=t.plugins.cursor;if(t.plugins.mobile){j(document).one("vmouseup.jqplot_cursor",{plot:t},p)}else{j(document).one("mouseup.jqplot_cursor",{plot:t},p)}var u=t.axes;if(document.onselectstart!=undefined){v._oldHandlers.onselectstart=document.onselectstart;document.onselectstart=function(){return false}}if(document.ondrag!=undefined){v._oldHandlers.ondrag=document.ondrag;document.ondrag=function(){return false}}if(document.onmousedown!=undefined){v._oldHandlers.onmousedown=document.onmousedown;document.onmousedown=function(){return false}}if(v.zoom){if(!v.zoomProxy){var y=v.zoomCanvas._ctx;y.clearRect(0,0,y.canvas.width,y.canvas.height);y=null}if(v.constrainZoomTo=="x"){v._zoom.start=[s.x,0]}else{if(v.constrainZoomTo=="y"){v._zoom.start=[0,s.y]}else{v._zoom.start=[s.x,s.y]}}v._zoom.started=true;for(var q in r){v._zoom.axes.start[q]=r[q]}if(t.plugins.mobile){j(document).bind("vmousemove.jqplotCursor",{plot:t},h)}else{j(document).bind("mousemove.jqplotCursor",{plot:t},h)}}}function p(y){var v=y.data.plot;var x=v.plugins.cursor;if(x.zoom&&x._zoom.zooming&&!x.zoomTarget){var u=x._zoom.gridpos.x;var r=x._zoom.gridpos.y;var t=x._zoom.datapos;var z=x.zoomCanvas._ctx.canvas.height;var q=x.zoomCanvas._ctx.canvas.width;var w=v.axes;if(x.constrainOutsideZoom&&!x.onGrid){if(u<0){u=0}else{if(u>q){u=q}}if(r<0){r=0}else{if(r>z){r=z}}for(var s in t){if(t[s]){if(s.charAt(0)=="x"){t[s]=w[s].series_p2u(u)}else{t[s]=w[s].series_p2u(r)}}}}if(x.constrainZoomTo=="x"){r=z}else{if(x.constrainZoomTo=="y"){u=q}}x._zoom.end=[u,r];x._zoom.gridpos={x:u,y:r};x.doZoom(x._zoom.gridpos,t,v,x)}x._zoom.started=false;x._zoom.zooming=false;j(document).unbind("mousemove.jqplotCursor",h);if(document.onselectstart!=undefined&&x._oldHandlers.onselectstart!=null){document.onselectstart=x._oldHandlers.onselectstart;x._oldHandlers.onselectstart=null}if(document.ondrag!=undefined&&x._oldHandlers.ondrag!=null){document.ondrag=x._oldHandlers.ondrag;x._oldHandlers.ondrag=null}if(document.onmousedown!=undefined&&x._oldHandlers.onmousedown!=null){document.onmousedown=x._oldHandlers.onmousedown;x._oldHandlers.onmousedown=null}}function l(){var y=this._zoom.start;var u=this._zoom.end;var s=this.zoomCanvas._ctx;var r,v,x,q;if(u[0]>y[0]){r=y[0];q=u[0]-y[0]}else{r=u[0];q=y[0]-u[0]}if(u[1]>y[1]){v=y[1];x=u[1]-y[1]}else{v=u[1];x=y[1]-u[1]}s.fillStyle="rgba(0,0,0,0.2)";s.strokeStyle="#999999";s.lineWidth=1;s.clearRect(0,0,s.canvas.width,s.canvas.height);s.fillRect(0,0,s.canvas.width,s.canvas.height);s.clearRect(r,v,q,x);s.strokeRect(r,v,q,x);s=null}j.jqplot.CursorLegendRenderer=function(q){j.jqplot.TableLegendRenderer.call(this,q);this.formatString="%s"};j.jqplot.CursorLegendRenderer.prototype=new j.jqplot.TableLegendRenderer();j.jqplot.CursorLegendRenderer.prototype.constructor=j.jqplot.CursorLegendRenderer;j.jqplot.CursorLegendRenderer.prototype.draw=function(){if(this._elem){this._elem.emptyForce();this._elem=null}if(this.show){var w=this._series,A;var r=document.createElement("table");this._elem=j(r);r=null;this._elem.addClass("jqplot-legend jqplot-cursor-legend");this._elem.css("position","absolute");var q=false;for(var x=0;x').appendTo(this._elem);E.data("seriesIndex",s);j('
    ').appendTo(E);var G=j('');G.appendTo(E);G.data("seriesIndex",s);if(this.escapeHtml){G.text(D)}else{G.html(D)}E=null;G=null}return this._elem}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(b){b.jqplot.BezierCurveRenderer=function(){b.jqplot.LineRenderer.call(this)};b.jqplot.BezierCurveRenderer.prototype=new b.jqplot.LineRenderer();b.jqplot.BezierCurveRenderer.prototype.constructor=b.jqplot.BezierCurveRenderer;b.jqplot.BezierCurveRenderer.prototype.setGridData=function(h){var e=this._xaxis.series_u2p;var g=this._yaxis.series_u2p;var f=this.data;this.gridData=[];this._prevGridData=[];var d=this.index;if(f.length==2){if(d==0){this.gridData=[[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,f[0][1])],[e.call(this._xaxis,f[1][0]),g.call(this._yaxis,f[1][1]),e.call(this._xaxis,f[1][2]),g.call(this._yaxis,f[1][3]),e.call(this._xaxis,f[1][4]),g.call(this._yaxis,f[1][5])],[e.call(this._xaxis,f[1][4]),g.call(this._yaxis,this._yaxis.min)],[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,this._yaxis.min)]]}else{var c=h.series[d-1].data;this.gridData=[[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,f[0][1])],[e.call(this._xaxis,f[1][0]),g.call(this._yaxis,f[1][1]),e.call(this._xaxis,f[1][2]),g.call(this._yaxis,f[1][3]),e.call(this._xaxis,f[1][4]),g.call(this._yaxis,f[1][5])],[e.call(this._xaxis,c[1][4]),g.call(this._yaxis,c[1][5])],[e.call(this._xaxis,c[1][2]),g.call(this._yaxis,c[1][3]),e.call(this._xaxis,c[1][0]),g.call(this._yaxis,c[1][1]),e.call(this._xaxis,c[0][0]),g.call(this._yaxis,c[0][1])]]}}else{if(d==0){this.gridData=[[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,f[0][1])],[e.call(this._xaxis,f[1][0]),g.call(this._yaxis,f[1][1]),e.call(this._xaxis,f[2][0]),g.call(this._yaxis,f[2][1]),e.call(this._xaxis,f[3][0]),g.call(this._yaxis,f[3][1])],[e.call(this._xaxis,f[3][1]),g.call(this._yaxis,this._yaxis.min)],[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,this._yaxis.min)]]}else{var c=h.series[d-1].data;this.gridData=[[e.call(this._xaxis,f[0][0]),g.call(this._yaxis,f[0][1])],[e.call(this._xaxis,f[1][0]),g.call(this._yaxis,f[1][1]),e.call(this._xaxis,f[2][0]),g.call(this._yaxis,f[2][1]),e.call(this._xaxis,f[3][0]),g.call(this._yaxis,f[3][1])],[e.call(this._xaxis,c[3][0]),g.call(this._yaxis,c[3][1])],[e.call(this._xaxis,c[2][0]),g.call(this._yaxis,c[2][1]),e.call(this._xaxis,c[1][0]),g.call(this._yaxis,c[1][1]),e.call(this._xaxis,c[0][0]),g.call(this._yaxis,c[0][1])]]}}};b.jqplot.BezierCurveRenderer.prototype.makeGridData=function(g,i){var f=this._xaxis.series_u2p;var h=this._yaxis.series_u2p;var e=[];var j=[];var d=this.index;if(g.length==2){if(d==0){e=[[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,g[0][1])],[f.call(this._xaxis,g[1][0]),h.call(this._yaxis,g[1][1]),f.call(this._xaxis,g[1][2]),h.call(this._yaxis,g[1][3]),f.call(this._xaxis,g[1][4]),h.call(this._yaxis,g[1][5])],[f.call(this._xaxis,g[1][4]),h.call(this._yaxis,this._yaxis.min)],[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,this._yaxis.min)]]}else{var c=i.series[d-1].data;e=[[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,g[0][1])],[f.call(this._xaxis,g[1][0]),h.call(this._yaxis,g[1][1]),f.call(this._xaxis,g[1][2]),h.call(this._yaxis,g[1][3]),f.call(this._xaxis,g[1][4]),h.call(this._yaxis,g[1][5])],[f.call(this._xaxis,c[1][4]),h.call(this._yaxis,c[1][5])],[f.call(this._xaxis,c[1][2]),h.call(this._yaxis,c[1][3]),f.call(this._xaxis,c[1][0]),h.call(this._yaxis,c[1][1]),f.call(this._xaxis,c[0][0]),h.call(this._yaxis,c[0][1])]]}}else{if(d==0){e=[[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,g[0][1])],[f.call(this._xaxis,g[1][0]),h.call(this._yaxis,g[1][1]),f.call(this._xaxis,g[2][0]),h.call(this._yaxis,g[2][1]),f.call(this._xaxis,g[3][0]),h.call(this._yaxis,g[3][1])],[f.call(this._xaxis,g[3][1]),h.call(this._yaxis,this._yaxis.min)],[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,this._yaxis.min)]]}else{var c=i.series[d-1].data;e=[[f.call(this._xaxis,g[0][0]),h.call(this._yaxis,g[0][1])],[f.call(this._xaxis,g[1][0]),h.call(this._yaxis,g[1][1]),f.call(this._xaxis,g[2][0]),h.call(this._yaxis,g[2][1]),f.call(this._xaxis,g[3][0]),h.call(this._yaxis,g[3][1])],[f.call(this._xaxis,c[3][0]),h.call(this._yaxis,c[3][1])],[f.call(this._xaxis,c[2][0]),h.call(this._yaxis,c[2][1]),f.call(this._xaxis,c[1][0]),h.call(this._yaxis,c[1][1]),f.call(this._xaxis,c[0][0]),h.call(this._yaxis,c[0][1])]]}}return e};b.jqplot.BezierCurveRenderer.prototype.draw=function(c,g,d){var e;c.save();if(g.length){if(this.showLine){c.save();var f=(d!=null)?d:{};c.fillStyle=f.fillStyle||this.color;c.beginPath();c.moveTo(g[0][0],g[0][1]);c.bezierCurveTo(g[1][0],g[1][1],g[1][2],g[1][3],g[1][4],g[1][5]);c.lineTo(g[2][0],g[2][1]);if(g[3].length==2){c.lineTo(g[3][0],g[3][1])}else{c.bezierCurveTo(g[3][0],g[3][1],g[3][2],g[3][3],g[3][4],g[3][5])}c.closePath();c.fill();c.restore()}}c.restore()};b.jqplot.BezierCurveRenderer.prototype.drawShadow=function(c,e,d){};b.jqplot.BezierAxisRenderer=function(){b.jqplot.LinearAxisRenderer.call(this)};b.jqplot.BezierAxisRenderer.prototype=new b.jqplot.LinearAxisRenderer();b.jqplot.BezierAxisRenderer.prototype.constructor=b.jqplot.BezierAxisRenderer;b.jqplot.BezierAxisRenderer.prototype.init=function(f){b.extend(true,this,f);var c=this._dataBounds;for(var g=0;gc.max||c.max==null){c.max=k[e][0]}}else{if(k[e][1]c.max||c.max==null){c.max=k[e][1]}}}}else{if(this.name=="xaxis"||this.name=="x2axis"){if(k[0][0]c.max||c.max==null){c.max=k[0][0]}for(var e=0;e<5;e+=2){if(k[1][e]c.max||c.max==null){c.max=k[1][e]}}}else{if(k[0][1]c.max||c.max==null){c.max=k[0][1]}for(var e=1;e<6;e+=2){if(k[1][e]c.max||c.max==null){c.max=k[1][e]}}}}}};function a(g,f,d){d=d||{};d.axesDefaults=b.extend(true,{pad:0},d.axesDefaults);d.seriesDefaults=d.seriesDefaults||{};d.legend=b.extend(true,{placement:"outside"},d.legend);var c=false;if(d.seriesDefaults.renderer==b.jqplot.BezierCurveRenderer){c=true}else{if(d.series){for(var e=0;e=this.data[0][1]){this.max=this.intervals[this.intervals.length-1][0];this.setmax=false}}else{this.setmax=false}}else{this.min=(this.min==null)?0:this.min;this.setmin=false;if(this.max==null){this.max=this.data[0][1]*1.25;this.setmax=true}else{this.setmax=false}}}};c.jqplot.MeterGaugeRenderer.prototype.setGridData=function(j){var f=[];var k=[];var e=this.startAngle;for(var h=0;h0){f[h]+=f[h-1]}}var g=Math.PI*2/f[f.length-1];for(var h=0;h0){f[h]+=f[h-1]}}var g=Math.PI*2/f[f.length-1];for(var h=0;h=0;h--){e=f/(j[h]*Math.pow(10,g));if(e==4||e==5){return e-1}}return null}c.jqplot.MeterGaugeRenderer.prototype.draw=function(X,aC,ap){var aa;var aM=(ap!=undefined)?ap:{};var ai=0;var ah=0;var at=1;if(ap.legendInfo&&ap.legendInfo.placement=="inside"){var aI=ap.legendInfo;switch(aI.location){case"nw":ai=aI.width+aI.xoffset;break;case"w":ai=aI.width+aI.xoffset;break;case"sw":ai=aI.width+aI.xoffset;break;case"ne":ai=aI.width+aI.xoffset;at=-1;break;case"e":ai=aI.width+aI.xoffset;at=-1;break;case"se":ai=aI.width+aI.xoffset;at=-1;break;case"n":ah=aI.height+aI.yoffset;break;case"s":ah=aI.height+aI.yoffset;at=-1;break;default:break}}if(this.label){this._labelElem=c('
    '+this.label+"
    ");this.canvas._elem.after(this._labelElem)}var m=(aM.shadow!=undefined)?aM.shadow:this.shadow;var N=(aM.showLine!=undefined)?aM.showLine:this.showLine;var I=(aM.fill!=undefined)?aM.fill:this.fill;var K=X.canvas.width;var S=X.canvas.height;if(this.padding==null){this.padding=Math.round(Math.min(K,S)/30)}var Q=K-ai-2*this.padding;var ab=S-ah-2*this.padding;if(this.labelPosition=="bottom"&&this.label){ab-=this._labelElem.outerHeight(true)}var L=Math.min(Q,ab);var ad=L;if(!this.diameter){if(this.semiCircular){if(Q>=2*ab){if(!this.ringWidth){this.ringWidth=2*ab/35}this.needleThickness=this.needleThickness||2+Math.pow(this.ringWidth,0.8);this.innerPad=this.ringWidth/2+this.needleThickness/2+this.needlePad;this.diameter=2*(ab-2*this.innerPad)}else{if(!this.ringWidth){this.ringWidth=Q/35}this.needleThickness=this.needleThickness||2+Math.pow(this.ringWidth,0.8);this.innerPad=this.ringWidth/2+this.needleThickness/2+this.needlePad;this.diameter=Q-2*this.innerPad-this.ringWidth-this.padding}this._center=[(K-at*ai)/2+at*ai,(S+at*ah-this.padding-this.ringWidth-this.innerPad)]}else{if(!this.ringWidth){this.ringWidth=ad/35}this.needleThickness=this.needleThickness||2+Math.pow(this.ringWidth,0.8);this.innerPad=0;this.diameter=ad-this.ringWidth;this._center=[(K-at*ai)/2+at*ai,(S-at*ah)/2+at*ah]}if(this._labelElem&&this.labelPosition=="bottom"){this._center[1]-=this._labelElem.outerHeight(true)}}this._radius=this.diameter/2;this.tickSpacing=6000/this.diameter;if(!this.hubRadius){this.hubRadius=this.diameter/18}this.shadowOffset=0.5+this.ringWidth/9;this.shadowWidth=this.ringWidth*1;this.tickPadding=3+Math.pow(this.diameter/20,0.7);this.tickOuterRadius=this._radius-this.ringWidth/2-this.tickPadding;this.tickLength=(this.showTicks)?this._radius/13:0;if(this.ticks.length==0){var A=this.max,aL=this.min,q=this.setmax,aG=this.setmin,au=(A-aL)*this.tickSpacing/this.span;var aw=Math.floor(parseFloat((Math.log(au)/Math.log(10)).toFixed(11)));var an=(au/Math.pow(10,aw));(an>2&&an<=2.5)?an=2.5:an=Math.ceil(an);var T=this.tickPositions;var aA,ak;for(aa=0;aa0)?aL-aL%au:aL-aL%au-au;if(!this.forceZero){var D=Math.min(aL-aP,0.8*au);var o=Math.floor(D/T[aA]);if(o>1){aP=aP+T[aA]*(o-1);if(parseInt(aP,10)!=aP&&parseInt(aP-T[aA],10)==aP-T[aA]){aP=aP-T[aA]}}}if(aL==aP){aL-=au}else{if(aL-aP>0.23*au){aL=aP}else{aL=aP-au;ak+=1}}ak+=1;var E=aL+(ak-1)*au;if(A>=E){E+=au;ak+=1}if(E-A<0.23*au){E+=au;ak+=1}this.max=A=E;this.min=aL;this.tickInterval=au;this.numberTicks=ak;var O;for(aa=0;aa=E){A=E+au;ak+=1}else{A=E}this.tickInterval=this.tickInterval||au;this.numberTicks=this.numberTicks||ak;var O;for(aa=0;aa1){var aJ=String(P);if(aJ.search(/\./)==-1){var aF=aJ.search(/0+$/);av=(aF>0)?aJ.length-aF-1:0}}M=P/Math.pow(10,av);for(aa=0;aa'+this.ticks[aa][1]+"");this.canvas._elem.after(J);aO=J.outerWidth(true);g=J.outerHeight(true);W=this._tickPoints[aa][0]-aO*(this._tickPoints[aa][2]-Math.PI)/Math.PI-an*Math.cos(this._tickPoints[aa][2]);T=this._tickPoints[aa][1]-g/2+g/2*Math.pow(Math.abs((Math.sin(this._tickPoints[aa][2]))),0.5)+an/3*Math.pow(Math.abs((Math.sin(this._tickPoints[aa][2]))),0.5);J.css({left:W,top:T,color:this.tickColor});G=aO*Math.cos(this._tickPoints[aa][2])+g*Math.sin(Math.PI/2+this._tickPoints[aa][2]/2);n=(G>n)?G:n}}if(this.label&&this.labelPosition=="inside"){var W=this._center[0]+this.canvas._offsets.left;var an=this.tickPadding*(1-1/(this.diameter/80+1));var T=0.5*(this._center[1]+this.canvas._offsets.top-this.hubRadius)+0.5*(this._center[1]+this.canvas._offsets.top-this.tickOuterRadius+this.tickLength+an)+this.labelHeightAdjust;W-=this._labelElem.outerWidth(true)/2;T-=this._labelElem.outerHeight(true)/2;this._labelElem.css({left:W,top:T})}else{if(this.label&&this.labelPosition=="bottom"){var W=this._center[0]+this.canvas._offsets.left-this._labelElem.outerWidth(true)/2;var T=this._center[1]+this.canvas._offsets.top+this.innerPad+this.ringWidth+this.padding+this.labelHeightAdjust;this._labelElem.css({left:W,top:T})}}X.save();var ax=this.intervalInnerRadius||this.hubRadius*1.5;if(this.intervalOuterRadius==null){if(this.showTickLabels){var ag=(this.tickOuterRadius-this.tickLength-this.tickPadding-this.diameter/8)}else{var ag=(this.tickOuterRadius-this.tickLength-this.diameter/16)}}else{var ag=this.intervalOuterRadius}var P=this.max-this.min;var aD=this.intervals[this.intervals.length-1]-this.min;var y,Z,u=this.span*Math.PI/180;for(aa=0;aathis.max+R*3/this.span){ay=this.max+R*3/this.span}if(this.data[0][1]');var f=false,q=false,u,o;var w=p[0];if(w.show){var t=w.data;if(this.numberRows){u=this.numberRows;if(!this.numberColumns){o=Math.ceil(t.length/u)}else{o=this.numberColumns}}else{if(this.numberColumns){o=this.numberColumns;u=Math.ceil(t.length/this.numberColumns)}else{u=t.length;o=1}}var n,m,r,g,e,l,k,h;var v=0;for(n=0;n').prependTo(this._elem)}else{r=c('').appendTo(this._elem)}for(m=0;m0){f=true}else{f=false}}else{if(n==u-1){f=false}else{f=true}}k=(f)?this.rowSpacing:"0";g=c('
    ');e=c('');if(this.escapeHtml){e.text(l)}else{e.html(l)}if(q){e.prependTo(r);g.prependTo(r)}else{g.appendTo(r);e.appendTo(r)}f=true}v++}}}}return this._elem};function a(j,h,f){f=f||{};f.axesDefaults=f.axesDefaults||{};f.legend=f.legend||{};f.seriesDefaults=f.seriesDefaults||{};f.grid=f.grid||{};var e=false;if(f.seriesDefaults.renderer==c.jqplot.MeterGaugeRenderer){e=true}else{if(f.series){for(var g=0;g570)?m[n]*0.8:m[n]+0.4*(255-m[n]);m[n]=parseInt(m[n],10)}this.highlightColors.push("rgb("+m[0]+","+m[1]+","+m[2]+")")}}t.postParseOptionsHooks.addOnce(k);t.postInitHooks.addOnce(g);t.eventListenerHooks.addOnce("jqplotMouseMove",a);t.eventListenerHooks.addOnce("jqplotMouseDown",b);t.eventListenerHooks.addOnce("jqplotMouseUp",j);t.eventListenerHooks.addOnce("jqplotClick",f);t.eventListenerHooks.addOnce("jqplotRightClick",l);t.postDrawHooks.addOnce(h)};e.jqplot.FunnelRenderer.prototype.setGridData=function(o){var n=0;var p=[];for(var m=0;mthis._lengths[Y]*n&&W<100){this._lengths[Y]=this._areas[Y]/(this._bases[Y]-this._lengths[Y]*Math.tan(this._angle));aa=Math.abs(this._lengths[Y]-E);this._bases[Y+1]=this._bases[Y]-(2*this._lengths[Y]*Math.tan(this._angle));E=this._lengths[Y];W++}Q+=this._lengths[Y]}this._vertices=new Array(B.length);var ae=[t,F],ad=[t+this._bases[0],F],ac=[t+(this._bases[0]-this._bases[this._bases.length-1])/2,F+this._length],ab=[ac[0]+this._bases[this._bases.length-1],ac[1]];function V(ag){var x=(ae[1]-ac[1])/(ae[0]-ac[0]);var v=ae[1]-x*ae[0];var ah=ag+ae[1];return[(ah-v)/x,ah]}function D(ag){var x=(ad[1]-ab[1])/(ad[0]-ab[0]);var v=ad[1]-x*ad[0];var ah=ag+ad[1];return[(ah-v)/x,ah]}var T=w,S=u;var Z=0,m=0;for(Y=0;Y0&&Y0&&Y=this.dataLabelThreshold){var K,X;if(this.dataLabels=="label"){K=this.dataLabelFormatString||"%s";X=e.jqplot.sprintf(K,B[Y][0])}else{if(this.dataLabels=="value"){K=this.dataLabelFormatString||"%d";X=e.jqplot.sprintf(K,this.data[Y][1])}else{if(this.dataLabels=="percent"){K=this.dataLabelFormatString||"%d%%";X=e.jqplot.sprintf(K,B[Y][1]*100)}else{if(this.dataLabels.constructor==Array){K=this.dataLabelFormatString||"%s";X=e.jqplot.sprintf(K,this.dataLabels[this._dataIndices[Y]])}}}}var s=(this._radius)*this.dataLabelPositionFactor+this.sliceMargin+this.dataLabelNudge;var T=(U[0][0]+U[1][0])/2+this.canvas._offsets.left;var S=(U[1][1]+U[2][1])/2+this.canvas._offsets.top;var z=e(''+X+"").insertBefore(p.eventCanvas._elem);T-=z.width()/2;S-=z.height()/2;T=Math.round(T);S=Math.round(S);z.css({left:T,top:S})}}};e.jqplot.FunnelAxisRenderer=function(){e.jqplot.LinearAxisRenderer.call(this)};e.jqplot.FunnelAxisRenderer.prototype=new e.jqplot.LinearAxisRenderer();e.jqplot.FunnelAxisRenderer.prototype.constructor=e.jqplot.FunnelAxisRenderer;e.jqplot.FunnelAxisRenderer.prototype.init=function(m){this.tickRenderer=e.jqplot.FunnelTickRenderer;e.extend(true,this,m);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};e.jqplot.FunnelLegendRenderer=function(){e.jqplot.TableLegendRenderer.call(this)};e.jqplot.FunnelLegendRenderer.prototype=new e.jqplot.TableLegendRenderer();e.jqplot.FunnelLegendRenderer.prototype.constructor=e.jqplot.FunnelLegendRenderer;e.jqplot.FunnelLegendRenderer.prototype.init=function(m){this.numberRows=null;this.numberColumns=null;e.extend(true,this,m)};e.jqplot.FunnelLegendRenderer.prototype.draw=function(){var p=this;if(this.show){var x=this._series;var A="position:absolute;";A+=(this.background)?"background:"+this.background+";":"";A+=(this.border)?"border:"+this.border+";":"";A+=(this.fontSize)?"font-size:"+this.fontSize+";":"";A+=(this.fontFamily)?"font-family:"+this.fontFamily+";":"";A+=(this.textColor)?"color:"+this.textColor+";":"";A+=(this.marginTop!=null)?"margin-top:"+this.marginTop+";":"";A+=(this.marginBottom!=null)?"margin-bottom:"+this.marginBottom+";":"";A+=(this.marginLeft!=null)?"margin-left:"+this.marginLeft+";":"";A+=(this.marginRight!=null)?"margin-right:"+this.marginRight+";":"";this._elem=e('
    ');var E=false,w=false,m,u;var y=x[0];var n=new e.jqplot.ColorGenerator(y.seriesColors);if(y.show){var F=y.data;if(this.numberRows){m=this.numberRows;if(!this.numberColumns){u=Math.ceil(F.length/m)}else{u=this.numberColumns}}else{if(this.numberColumns){u=this.numberColumns;m=Math.ceil(F.length/this.numberColumns)}else{m=F.length;u=1}}var D,C,o,r,q,t,v,B;var z=0;for(D=0;D').prependTo(this._elem)}else{o=e('').appendTo(this._elem)}for(C=0;C0){E=true}else{E=false}}else{if(D==m-1){E=false}else{E=true}}v=(E)?this.rowSpacing:"0";r=e('
    ');q=e('');if(this.escapeHtml){q.text(t)}else{q.html(t)}if(w){q.prependTo(o);r.prependTo(o)}else{r.appendTo(o);q.appendTo(o)}E=true}z++}}}}return this._elem};function c(q,p,n){n=n||{};n.axesDefaults=n.axesDefaults||{};n.legend=n.legend||{};n.seriesDefaults=n.seriesDefaults||{};var m=false;if(n.seriesDefaults.renderer==e.jqplot.FunnelRenderer){m=true}else{if(n.series){for(var o=0;o0){this._xstart=h.series[this.index-1]._xstart+h.series[this.index-1]._xwidth}var l=this.canvas.getHeight();var d=0;var k;var j;for(var f=0;f');var w=false,n=true,c,l;var p=o[0];var d=new b.jqplot.ColorGenerator(p.seriesColors);if(p.show){var x=p.data;if(this.numberRows){c=this.numberRows;if(!this.numberColumns){l=Math.ceil(x.length/c)}else{l=this.numberColumns}}else{if(this.numberColumns){l=this.numberColumns;c=Math.ceil(x.length/this.numberColumns)}else{c=x.length;l=1}}var v,u,e,h,g,k,m,t;var q=0;for(v=0;v').prependTo(this._elem)}else{e=b('').appendTo(this._elem)}for(u=0;u0){w=true}else{w=false}}else{if(v==c-1){w=false}else{w=true}}m=(w)?this.rowSpacing:"0";h=b('
    ');g=b('');if(this.escapeHtml){g.text(k)}else{g.html(k)}if(n){g.prependTo(e);h.prependTo(e)}else{h.appendTo(e);g.appendTo(e)}w=true}q++}}e=null;h=null;g=null}}return this._elem};b.jqplot.MekkoLegendRenderer.prototype.pack=function(f){if(this.show){var e={_top:f.top,_left:f.left,_right:f.right,_bottom:this._plotDimensions.height-f.bottom};if(this.placement=="insideGrid"){switch(this.location){case"nw":var d=e._left+this.xoffset;var c=e._top+this.yoffset;this._elem.css("left",d);this._elem.css("top",c);break;case"n":var d=(f.left+(this._plotDimensions.width-f.right))/2-this.getWidth()/2;var c=e._top+this.yoffset;this._elem.css("left",d);this._elem.css("top",c);break;case"ne":var d=f.right+this.xoffset;var c=e._top+this.yoffset;this._elem.css({right:d,top:c});break;case"e":var d=f.right+this.xoffset;var c=(f.top+(this._plotDimensions.height-f.bottom))/2-this.getHeight()/2;this._elem.css({right:d,top:c});break;case"se":var d=f.right+this.xoffset;var c=f.bottom+this.yoffset;this._elem.css({right:d,bottom:c});break;case"s":var d=(f.left+(this._plotDimensions.width-f.right))/2-this.getWidth()/2;var c=f.bottom+this.yoffset;this._elem.css({left:d,bottom:c});break;case"sw":var d=e._left+this.xoffset;var c=f.bottom+this.yoffset;this._elem.css({left:d,bottom:c});break;case"w":var d=e._left+this.xoffset;var c=(f.top+(this._plotDimensions.height-f.bottom))/2-this.getHeight()/2;this._elem.css({left:d,top:c});break;default:var d=e._right-this.xoffset;var c=e._bottom+this.yoffset;this._elem.css({right:d,bottom:c});break}}else{switch(this.location){case"nw":var d=this._plotDimensions.width-e._left+this.xoffset;var c=e._top+this.yoffset;this._elem.css("right",d);this._elem.css("top",c);break;case"n":var d=(f.left+(this._plotDimensions.width-f.right))/2-this.getWidth()/2;var c=this._plotDimensions.height-e._top+this.yoffset;this._elem.css("left",d);this._elem.css("bottom",c);break;case"ne":var d=this._plotDimensions.width-f.right+this.xoffset;var c=e._top+this.yoffset;this._elem.css({left:d,top:c});break;case"e":var d=this._plotDimensions.width-f.right+this.xoffset;var c=(f.top+(this._plotDimensions.height-f.bottom))/2-this.getHeight()/2;this._elem.css({left:d,top:c});break;case"se":var d=this._plotDimensions.width-f.right+this.xoffset;var c=f.bottom+this.yoffset;this._elem.css({left:d,bottom:c});break;case"s":var d=(f.left+(this._plotDimensions.width-f.right))/2-this.getWidth()/2;var c=this._plotDimensions.height-f.bottom+this.yoffset;this._elem.css({left:d,top:c});break;case"sw":var d=this._plotDimensions.width-e._left+this.xoffset;var c=f.bottom+this.yoffset;this._elem.css({right:d,bottom:c});break;case"w":var d=this._plotDimensions.width-e._left+this.xoffset;var c=(f.top+(this._plotDimensions.height-f.bottom))/2-this.getHeight()/2;this._elem.css({right:d,top:c});break;default:var d=e._right-this.xoffset;var c=e._bottom+this.yoffset;this._elem.css({right:d,bottom:c});break}}}};function a(g,f,d){d=d||{};d.axesDefaults=d.axesDefaults||{};d.legend=d.legend||{};d.seriesDefaults=d.seriesDefaults||{};var c=false;if(d.seriesDefaults.renderer==b.jqplot.MekkoRenderer){c=true}else{if(d.series){for(var e=0;e=0.6)?l[3]*0.6:l[3]*(2-l[3]);i.color="rgba("+n[0]+","+n[1]+","+n[2]+","+k+")";i.init();i.draw(p.gridData[o.pointIndex][0],p.gridData[o.pointIndex][1],j.highlightCanvas._ctx)}function g(A,q,m){var k=A.plugins.highlighter;var D=k._tooltipElem;var r=q.highlighter||{};var t=d.extend(true,{},k,r);if(t.useAxesFormatters){var w=q._xaxis._ticks[0].formatter;var h=q._yaxis._ticks[0].formatter;var E=q._xaxis._ticks[0].formatString;var s=q._yaxis._ticks[0].formatString;var z;var u=w(E,m.data[0]);var l=[];for(var B=1;B=0.6)?l[3]*0.6:l[3]*(2-l[3]);m.color="rgba("+o[0]+","+o[1]+","+o[2]+","+k+")"}i.color=m.color;i.init();var g=(p.pointIndex>0)?p.pointIndex-1:0;var j=p.pointIndex+2;m._gridData=q.gridData.slice(g,j)}function e(o,l,h,t,m){if(m.plugins.dragable.dragCanvas.isDragging){var u=m.plugins.dragable.dragCanvas;var i=u._neighbor;var w=m.series[i.seriesIndex];var k=w.plugins.dragable;var r=w.gridData;var p=(k.constrainTo=="y")?i.gridData[0]:l.x;var n=(k.constrainTo=="x")?i.gridData[1]:l.y;var g=w._xaxis.series_p2u(p);var q=w._yaxis.series_p2u(n);var v=u._ctx;v.clearRect(0,0,v.canvas.width,v.canvas.height);if(i.pointIndex>0){k._gridData[1]=[p,n]}else{k._gridData[0]=[p,n]}m.series[i.seriesIndex].draw(u._ctx,{gridData:k._gridData,shadow:false,preventJqPlotSeriesDrawTrigger:true,color:k.color,markerOptions:{color:k.color,shadow:false},trendline:{show:false}});m.target.trigger("jqplotSeriesPointChange",[i.seriesIndex,i.pointIndex,[g,q],[p,n]])}else{if(t!=null){var j=m.series[t.seriesIndex];if(j.isDragable){var u=m.plugins.dragable.dragCanvas;if(!u.isOver){u._cursors.push(o.target.style.cursor);o.target.style.cursor="pointer"}u.isOver=true}}else{if(t==null){var u=m.plugins.dragable.dragCanvas;if(u.isOver){o.target.style.cursor=u._cursors.pop();u.isOver=false}}}}}function c(k,i,g,l,j){var m=j.plugins.dragable.dragCanvas;m._cursors.push(k.target.style.cursor);if(l!=null){var o=j.series[l.seriesIndex];var h=o.plugins.dragable;if(o.isDragable&&!m.isDragging){m._neighbor=l;m.isDragging=true;f(j,l);h.markerRenderer.draw(o.gridData[l.pointIndex][0],o.gridData[l.pointIndex][1],m._ctx);k.target.style.cursor="move";j.target.trigger("jqplotDragStart",[l.seriesIndex,l.pointIndex,i,g])}}else{var n=m._ctx;n.clearRect(0,0,n.canvas.width,n.canvas.height);m.isDragging=false}}function a(m,j,g,o,k){if(k.plugins.dragable.dragCanvas.isDragging){var p=k.plugins.dragable.dragCanvas;var q=p._ctx;q.clearRect(0,0,q.canvas.width,q.canvas.height);p.isDragging=false;var h=p._neighbor;var r=k.series[h.seriesIndex];var i=r.plugins.dragable;var n=(i.constrainTo=="y")?h.data[0]:g[r.xaxis];var l=(i.constrainTo=="x")?h.data[1]:g[r.yaxis];r.data[h.pointIndex][0]=n;r.data[h.pointIndex][1]=l;k.drawSeries({preventJqPlotSeriesDrawTrigger:true},h.seriesIndex);p._neighbor=null;m.target.style.cursor=p._cursors.pop();k.target.trigger("jqplotDragStop",[j,g])}}})(jQuery);/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com jsDate | (c) 2010-2013 Chris Leonello */(function(a){a.jqplot.CanvasTextRenderer=function(b){this.fontStyle="normal";this.fontVariant="normal";this.fontWeight="normal";this.fontSize="10px";this.fontFamily="sans-serif";this.fontStretch=1;this.fillStyle="#666666";this.angle=0;this.textAlign="start";this.textBaseline="alphabetic";this.text;this.width;this.height;this.pt2px=1.28;a.extend(true,this,b);this.normalizedFontSize=this.normalizeFontSize(this.fontSize);this.setHeight()};a.jqplot.CanvasTextRenderer.prototype.init=function(b){a.extend(true,this,b);this.normalizedFontSize=this.normalizeFontSize(this.fontSize);this.setHeight()};a.jqplot.CanvasTextRenderer.prototype.normalizeFontSize=function(b){b=String(b);var c=parseFloat(b);if(b.indexOf("px")>-1){return c/this.pt2px}else{if(b.indexOf("pt")>-1){return c}else{if(b.indexOf("em")>-1){return c*12}else{if(b.indexOf("%")>-1){return c*12/100}else{return c/this.pt2px}}}}};a.jqplot.CanvasTextRenderer.prototype.fontWeight2Float=function(b){if(Number(b)){return b/400}else{switch(b){case"normal":return 1;break;case"bold":return 1.75;break;case"bolder":return 2.25;break;case"lighter":return 0.75;break;default:return 1;break}}};a.jqplot.CanvasTextRenderer.prototype.getText=function(){return this.text};a.jqplot.CanvasTextRenderer.prototype.setText=function(c,b){this.text=c;this.setWidth(b);return this};a.jqplot.CanvasTextRenderer.prototype.getWidth=function(b){return this.width};a.jqplot.CanvasTextRenderer.prototype.setWidth=function(c,b){if(!b){this.width=this.measure(c,this.text)}else{this.width=b}return this};a.jqplot.CanvasTextRenderer.prototype.getHeight=function(b){return this.height};a.jqplot.CanvasTextRenderer.prototype.setHeight=function(b){if(!b){this.height=this.normalizedFontSize*this.pt2px}else{this.height=b}return this};a.jqplot.CanvasTextRenderer.prototype.letter=function(b){return this.letters[b]};a.jqplot.CanvasTextRenderer.prototype.ascent=function(){return this.normalizedFontSize};a.jqplot.CanvasTextRenderer.prototype.descent=function(){return 7*this.normalizedFontSize/25};a.jqplot.CanvasTextRenderer.prototype.measure=function(d,g){var f=0;var b=g.length;for(var e=0;e30)?2:2+(30-this.normalizedFontSize)/20;s.lineWidth=t*k*this.fontWeight2Float(this.fontWeight);for(var g=0;g":{width:24,points:[[4,18],[20,9],[4,0]]},"?":{width:18,points:[[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]]},"@":{width:27,points:[[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]]},A:{width:18,points:[[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]]},B:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]]},C:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]]},D:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]]},E:{width:19,points:[[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]]},F:{width:18,points:[[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]]},G:{width:21,points:[[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]]},H:{width:22,points:[[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]]},I:{width:8,points:[[4,21],[4,0]]},J:{width:16,points:[[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]]},K:{width:21,points:[[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]]},L:{width:17,points:[[4,21],[4,0],[-1,-1],[4,0],[16,0]]},M:{width:24,points:[[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]]},N:{width:22,points:[[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]]},O:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]]},P:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]]},Q:{width:22,points:[[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]]},R:{width:21,points:[[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]]},S:{width:20,points:[[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]]},T:{width:16,points:[[8,21],[8,0],[-1,-1],[1,21],[15,21]]},U:{width:22,points:[[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]]},V:{width:18,points:[[1,21],[9,0],[-1,-1],[17,21],[9,0]]},W:{width:24,points:[[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]]},X:{width:20,points:[[3,21],[17,0],[-1,-1],[17,21],[3,0]]},Y:{width:18,points:[[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]]},Z:{width:20,points:[[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]]},"[":{width:14,points:[[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]]},"\\":{width:14,points:[[0,21],[14,-3]]},"]":{width:14,points:[[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]]},"^":{width:16,points:[[6,15],[8,18],[10,15],[-1,-1],[3,12],[8,17],[13,12],[-1,-1],[8,17],[8,0]]},_:{width:16,points:[[0,-2],[16,-2]]},"`":{width:10,points:[[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]]},a:{width:19,points:[[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},b:{width:19,points:[[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},c:{width:18,points:[[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},d:{width:19,points:[[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},e:{width:18,points:[[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},f:{width:12,points:[[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]]},g:{width:19,points:[[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},h:{width:19,points:[[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},i:{width:8,points:[[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]]},j:{width:10,points:[[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]]},k:{width:17,points:[[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]]},l:{width:8,points:[[4,21],[4,0]]},m:{width:30,points:[[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]]},n:{width:19,points:[[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]]},o:{width:19,points:[[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]]},p:{width:19,points:[[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]]},q:{width:19,points:[[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]]},r:{width:13,points:[[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]]},s:{width:17,points:[[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]]},t:{width:12,points:[[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]]},u:{width:19,points:[[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]]},v:{width:16,points:[[2,14],[8,0],[-1,-1],[14,14],[8,0]]},w:{width:22,points:[[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]]},x:{width:17,points:[[3,14],[14,0],[-1,-1],[14,14],[3,0]]},y:{width:16,points:[[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]]},z:{width:17,points:[[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]]},"{":{width:14,points:[[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]]},"|":{width:8,points:[[4,25],[4,-7]]},"}":{width:14,points:[[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]]},"~":{width:24,points:[[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]]}};a.jqplot.CanvasFontRenderer=function(b){b=b||{};if(!b.pt2px){b.pt2px=1.5}a.jqplot.CanvasTextRenderer.call(this,b)};a.jqplot.CanvasFontRenderer.prototype=new a.jqplot.CanvasTextRenderer({});a.jqplot.CanvasFontRenderer.prototype.constructor=a.jqplot.CanvasFontRenderer;a.jqplot.CanvasFontRenderer.prototype.measure=function(c,e){var d=this.fontSize+" "+this.fontFamily;c.save();c.font=d;var b=c.measureText(e).width;c.restore();return b};a.jqplot.CanvasFontRenderer.prototype.draw=function(e,g){var c=0;var h=this.height*0.72;e.save();var d,b;if((-Math.PI/2<=this.angle&&this.angle<=0)||(Math.PI*3/2<=this.angle&&this.angle<=Math.PI*2)){d=0;b=-Math.sin(this.angle)*this.width}else{if((00){this.data[q][u]+=this.data[q-1][u]}}this.data[this.data.length]=(u==1)?[this.data.length+1,s]:[s,this.data.length+1];this._data[this._data.length]=(u==1)?[this._data.length+1,s]:[s,this._data.length+1]}if(this.rendererOptions.groups>1){this.breakOnNull=true;var n=this.data.length;var v=parseInt(n/this.rendererOptions.groups,10);var r=0;for(var q=v;q570)?n[p]*0.8:n[p]+0.3*(255-n[p]);n[p]=parseInt(n[p],10)}q.push("rgb("+n[0]+","+n[1]+","+n[2]+")")}return q}function i(v,u,s,t,o){var q=v,w=v-1,n,p,r=(o==="x")?0:1;if(q>0){p=t.series[w]._plotData[u][r];if((s*p)<0){n=i(w,u,s,t,o)}else{n=t.series[w].gridData[u][r]}}else{n=(r===0)?t.series[q]._xaxis.series_u2p(0):t.series[q]._yaxis.series_u2p(0)}return n}d.jqplot.BarRenderer.prototype.draw=function(E,L,q,G){var I;var A=d.extend({},q);var w=(A.shadow!=undefined)?A.shadow:this.shadow;var O=(A.showLine!=undefined)?A.showLine:this.showLine;var F=(A.fill!=undefined)?A.fill:this.fill;var p=this.xaxis;var J=this.yaxis;var y=this._xaxis.series_u2p;var K=this._yaxis.series_u2p;var D,C;this._dataColors=[];this._barPoints=[];if(this.barWidth==null){this.renderer.setBarWidth.call(this)}var N=this._plotSeriesInfo=this.renderer.calcSeriesNumbers.call(this);var x=N[0];var v=N[1];var s=N[2];var H=[];if(this._stack){this._barNudge=0}else{this._barNudge=(-Math.abs(v/2-0.5)+s)*(this.barWidth+this.barPadding)}if(O){var u=new d.jqplot.ColorGenerator(this.negativeSeriesColors);var B=new d.jqplot.ColorGenerator(this.seriesColors);var M=u.get(this.index);if(!this.useNegativeColors){M=A.fillStyle}var t=A.fillStyle;var r;var P;var o;if(this.barDirection=="vertical"){for(var I=0;I0&&I=0){o=this._yaxis.series_u2p(0)}else{if(this._yaxis.min>0){o=E.canvas.height}else{o=0}}}else{if(this.waterfall&&I==this.gridData.length-1){if(this._yaxis.min<=0&&this._yaxis.max>=0){o=this._yaxis.series_u2p(0)}else{if(this._yaxis.min>0){o=E.canvas.height}else{o=0}}}else{o=E.canvas.height}}}}}if((this.fillToZero&&this._plotData[I][1]<0)||(this.waterfall&&this._data[I][1]<0)){if(this.varyBarColor&&!this._stack){if(this.useNegativeColors){A.fillStyle=u.next()}else{A.fillStyle=B.next()}}else{A.fillStyle=M}}else{if(this.varyBarColor&&!this._stack){A.fillStyle=B.next()}else{A.fillStyle=t}}if(!this.fillToZero||this._plotData[I][1]>=0){H.push([r-this.barWidth/2,o]);H.push([r-this.barWidth/2,L[I][1]]);H.push([r+this.barWidth/2,L[I][1]]);H.push([r+this.barWidth/2,o])}else{H.push([r-this.barWidth/2,L[I][1]]);H.push([r-this.barWidth/2,o]);H.push([r+this.barWidth/2,o]);H.push([r+this.barWidth/2,L[I][1]])}this._barPoints.push(H);if(w&&!this._stack){var z=d.extend(true,{},A);delete z.fillStyle;this.renderer.shadowRenderer.draw(E,H,z)}var n=A.fillStyle||this.color;this._dataColors.push(n);this.renderer.shapeRenderer.draw(E,H,A)}}else{if(this.barDirection=="horizontal"){for(var I=0;I0&&I=0){P=this._xaxis.series_u2p(0)}else{if(this._xaxis.min>0){P=0}else{P=0}}}else{if(this.waterfall&&I==this.gridData.length-1){if(this._xaxis.min<=0&&this._xaxis.max>=0){P=this._xaxis.series_u2p(0)}else{if(this._xaxis.min>0){P=0}else{P=E.canvas.width}}}else{P=0}}}}}if((this.fillToZero&&this._plotData[I][0]<0)||(this.waterfall&&this._data[I][0]<0)){if(this.varyBarColor&&!this._stack){if(this.useNegativeColors){A.fillStyle=u.next()}else{A.fillStyle=B.next()}}else{A.fillStyle=M}}else{if(this.varyBarColor&&!this._stack){A.fillStyle=B.next()}else{A.fillStyle=t}}if(!this.fillToZero||this._plotData[I][0]>=0){H.push([P,r+this.barWidth/2]);H.push([P,r-this.barWidth/2]);H.push([L[I][0],r-this.barWidth/2]);H.push([L[I][0],r+this.barWidth/2])}else{H.push([L[I][0],r+this.barWidth/2]);H.push([L[I][0],r-this.barWidth/2]);H.push([P,r-this.barWidth/2]);H.push([P,r+this.barWidth/2])}this._barPoints.push(H);if(w&&!this._stack){var z=d.extend(true,{},A);delete z.fillStyle;this.renderer.shadowRenderer.draw(E,H,z)}var n=A.fillStyle||this.color;this._dataColors.push(n);this.renderer.shapeRenderer.draw(E,H,A)}}}}if(this.highlightColors.length==0){this.highlightColors=d.jqplot.computeHighlightColors(this._dataColors)}else{if(typeof(this.highlightColors)=="string"){var N=this.highlightColors;this.highlightColors=[];for(var I=0;I140){h=Math.round(Math.log(this.max/this.min)/Math.log(this.base)+1);if(h<2){h=2}if(C===0){var o=b/(h-1);if(o<100){C=0}else{if(o<190){C=1}else{if(o<250){C=3}else{if(o<600){C=4}else{C=9}}}}}}else{h=2;if(C===0){C=1}C=0}}else{h=this.numberTicks}if(E>=0&&C!==3){this._autoFormatString="%d"}else{if(E<=0&&C===3){var o=-(E-1);this._autoFormatString="%."+Math.abs(E-1)+"f"}else{if(E<0){var o=-E;this._autoFormatString="%."+Math.abs(E)+"f"}else{this._autoFormatString="%d"}}}var O,H,z,p,n,k;for(var K=0;K=0;J--){z=p-k*(J+1);H=new this.tickRenderer(this.tickOptions);if(this._overrideFormatString&&this._autoFormatString!=""){H.formatString=this._autoFormatString}if(!this.showTicks){H.showLabel=false;H.showMark=false}else{if(!this.showTickMarks){H.showMark=false}}H.setTick(z,this.name);this._ticks.push(H)}}}}else{if(this.min!=null&&this.max!=null){var y=a.extend(true,{},this.tickOptions,{name:this.name,value:null});var I,e;if(this.numberTicks==null&&this.tickInterval==null){var D=Math.max(b,g+1);var L=Math.ceil((D-g)/35+1);var B=a.jqplot.LinearTickGenerator.bestConstrainedInterval(this.min,this.max,L);this._autoFormatString=B[3];I=B[2];e=B[4];for(var K=0;K0){c=-n._textRenderer.height*Math.cos(-n._textRenderer.angle)/2}else{c=-n.getHeight()+n._textRenderer.height*Math.cos(n._textRenderer.angle)/2}break;case"middle":c=-n.getHeight()/2;break;default:c=-n.getHeight()/2;break}}else{c=-n.getHeight()/2}var z=this.u2p(n.value)+c+"px";n._elem.css("top",z);n.pack()}}if(o){var x=this._label._elem.outerHeight(true);this._label._elem.css("top",m-g/2-x/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px")}else{this._label._elem.css("right","0px")}this._label.pack()}}}}})(jQuery);/** * jqPlot * Pure JavaScript plotting plugin using jQuery * * Version: @VERSION * * Copyright (c) 2009-2013 Chris Leonello * jqPlot is currently available for use in all personal or commercial projects * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can * choose the license that best suits your project and use it accordingly. * * Although not required, the author would appreciate an email letting him * know of any substantial use of jqPlot. You can reach the author at: * chris at jqplot dot com or see http://www.jqplot.com/info.php . * * If you are feeling kind and generous, consider supporting the project by * making a donation at: http://www.jqplot.com/donate.php . * * sprintf functions contained in jqplot.sprintf.js by Ash Searle: * * version 2007.04.27 * author Ash Searle * http://hexmen.com/blog/2007/03/printf-sprintf/ * http://hexmen.com/js/sprintf.js * The author (Ash Searle) has placed this code in the public domain: * "This code is unrestricted: you are free to use it however you like." * * included jsDate library by Chris Leonello: * * Copyright (c) 2010-2013 Chris Leonello * * jsDate is currently available for use in all personal or commercial projects * under both the MIT and GPL version 2.0 licenses. This means that you can * choose the license that best suits your project and use it accordingly. * * jsDate borrows many concepts and ideas from the Date Instance * Methods by Ken Snyder along with some parts of Ken's actual code. * * Ken's origianl Date Instance Methods and copyright notice: * * Ken Snyder (ken d snyder at gmail dot com) * 2008-09-10 * version 2.0.2 (http://kendsnyder.com/sandbox/date/) * Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/) * * jqplotToImage function based on Larry Siden's export-jqplot-to-png.js. * Larry has generously given permission to adapt his code for inclusion * into jqPlot. * * Larry's original code can be found here: * * https://github.com/lsiden/export-jqplot-to-png * * */ Title: GPL Version 2 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.Title: Change Log 1.0.8: * Issue #375: sortMergedLabels does not sort string labels * Issue #279: Groups > 3 Causes Alignment Issues * Issue #439: IE can't display a customized legend in Quirks mode * Issue #482: "Undefined" error message when plotting a chart with no data * Issue #116: Don't mix spaces and tabs for indentation * Issue #564: Metergauge renderer not resizable when replotting * Issue #409: MeterGaugeRenderer replot/redraw offsets center * Issue #523: Adding rectangles to Canvas Overlay plugin * Issue #756: jqplot.min files contain non-UTF-8 characters * Issue #223: fillToZero does not color negative values when crossover point is 0 * Pull Request #23: Adding rectangles to Canvas Overlay plugin * Pull Request #28: Cross-over points of 0 will actually change colors * Pull Request #35: Don't highlight hidden bars or show tooltips for them * Pull Request #41: Add dutch(nl) and svenska(sv) translations for dates * Add tooltip support for Pie Charts * Update to latest YUI compressor 1.0.7: * Issue #726: Bug in sprintf %p, sometimes it outputs exponential form rather than decimal * Issue #717: Plot's preDrawHooks not called * Issue #707: Browser hangs with LogAxisRenderer when value is 0 * Issue #695: Horizontal Bar Chart Negative Series Colors Not Working * Issue #670: Examples IE7, IE8 and IE9 multipleBarColors.html failure and fix * Issue #636: X Axis Date Renderer Single Day Not plotting * Issue #607: Integration issue * Issue #571: Decimal numbers not properly formatted * Issue #552: jqPlot crashes when interval too small * Issue #536: DateAxisRenderer invalid scaling * Issue #534: "decimalMark" in the "jqplot.sprintf.js" * Issue #529: Scientific notation on label values ending in 0 * Issue #521: invalid JS in meterGaugeRenderer.js * Issue #516: Including BezierCurveRenderer plugin and initializing jqplot with no options give error * Issue #500: DateAxisRenderer has timezone related issues * Issue #452: Including ALL jqPlot plugins causes an Error * Issue #494: No point when use LogAxisRenderer and a point has a zero value * Issue #430: getIsoWeek: invalid method call * Issue #280: jqplot Options * Issue #179: Spelling/grammar * Pull Request #18: Implement getTop in CanvasAxisTickRenderer * Pull Request #21: Performance issue when drawing pointlabels with zeros/null values * Pull Request #24: Added suggested fix in comment #8 for issue #536 * Pull Request #29: Removed unbalanced addition of UTC offset * Pull Request #33: Documentation fixes (issue #179, other changes) * Pull Request #34: Start of updating jqPlotOptions.txt * Pull Request #37: Example and suggested fix for issues #552 and issue #536 * Pull Request #39: Fixed trailing comma which caused issues with IE7 1.0.6: * Add left sidebar navigation to examples * Update examples for jquery 1.9.1 and jquery ui 1.10.0 * Add colorpicker.js to distribution * Fix some problems with examples when viewing with local file system * Add "minified" copyright notice for minified files, similar to jquery's notice. * Pull Request #25: jqplot.sprintf.js is no longer the last file in the concatenated jquery.jqplot.js * Pull Request #17: Fixed bug causing custom pointLabels passed with plot data to be ignored for horizontal bar graphs. * Pull Request #10: Build error by invalid encoding. * Issue #714: handle tickColor in meterGaugeRenderer * Issue #519: jsDate Polish Localization 1.0.5: * Updated to jQuery 1.9 1.0.0b2: * Major improvements in memory usage: ** Merged in changes from Timo Besenruether to reuse canvas elements and improve memory performance. ** Fixed all identifiable DOM leaks. ** Mergged in changes from cguillot for memory improvements in IE < 9. * Added vertical and dashed vertical line support for canvas overlay. * Fixed bug where initially hidden plots would not display. * Fixed bug with point labels and null data points. * Updated to jQuery 1.6.1. * Improved pie slice margin calculation and fixed slice margin and pie positioning with small slices. * Improved bar renderer so bars always start at 0 if: ** The axis is a linear axis (not log/date). ** There are no other line types besides bars attached to the axis. ** The data on the axis is all >= 0. ** The user has not specified a pad, padMin or forceTickAt0 = true option. * Modified tick prefix behavious so prefix no added to all ticks, even if format string is specified. * Fix to ensure original tick formats are applied when zooming and resetting zoom. * Updated auto tick format string so format adjusted when zooming. * Modified auto tick computation to put less ticks on small plots and more ticks on large plots. * Update bubble render to support gradients in IE 9. 1.0.0b1: * Much improved tick generation algorithm to get precise rounded tick values (Thanks Scott Prahl!). * Auto compute tick format string if none is provided. * Much better "slicing" of pie charts when using "sliceMargin" option to set a gap between the slices. * Expanded canvasOverlay plugin to create arbitrary dashed and solid horizontal and vertical lines on top of plot. * Added defaultColors and defaultNegativeColors options to $.jqplot.config. * Fixed issue #318, highlighter & bar renderer incompatability. * Improve highlighter tooltip positioning with negative bars. * Fixed #305, mispelling of jqlotDragStart and jqlotDragStop. MUST NOW BIND TO jqplotDragStart and jqplotDragStop. * Fixed #290, some variables left in global scope. * Fixed #289, OHLC line widths hard coded at 1.5. Now set by lineWidth option. * Fixed #296 for determining databounds on log axes. * Updated to jQuery 1.5.1 * Fixed waterfall plot to ensure first and last bars always fill to zero. * Added lineJoin and lineCap option to series lines. * Bar widths now based on width of grid, not plot target for better scaling. * Added looseZoom option to cursor so zooming can produce well rounded ticks. * Added forceTickAt0 and forceTickAt100 options to ensure there will always be a tick at 0 or 100 in the plot. * Fixed bug where cursor legend didn't honor series showLabel option. 1.0.0a: * Series can now be moved forward or backward in stack to e.g. bring a line forward when mousing over a point. * Can now move outside of grid area while zooming. Can have zoom constrained to grid area or allow zooming outside. * Fixed issue #142 with tooltip drawn on top of event canvas, hiding mouse events. * Fixed #147 where pie slices with 0 value not rendering properly in IE. * Fixed #130 where stack data not sorted properly. * Fixed bug with null values not handled properly in category axes. * Fixed #156 where pie charts not rendering on QTWebKit. * Now using feature detection for canvas and canvas text capability rather than browser version. * Added enahncedLegendRenderer plugin to allow multi row/column legends and clickable labels to show/hide series. * Added fillToValue option to allow filled line plot to fill to an arbitrary value. * Added block plot plugin. * Added funnel type charts. * Added meter gauge type charts. * Added plot theming support. * $.jqplot.config.enablePlugins now false by default. * Implemented highlighting on bar, pie, donut, funnel, etc. charts. * Fix to pointlabels plugin to align labels properly on multi series plots. * Added custom error handling to display error message in plot area. * Fixed issue where would call to draw grid border of 0 width would result in a default border being drawn. * Added options to place legend outside of grid and shrink grid so everything stays within plot div. * Fixed bug in color generator so now calls to get() continually cycle through colors just like next(). * Added defaultAxisStart option. * Added gradient fills to bubbles. * Added bubble charts. * Added showLabels option to bubble charts. * Pass bubble radius to event callback in bubble charts. * Fixed #207, typo in docs. * Fixed #206 where "value" pie slice data labels were displaying wrong value. * Fixed #147 with 0 value slices in IE6. * Fixed issue #241, disabled varyBarColor option in stacked charts. * Added dataRenderer option to allow custom processors for JSON, AJAX and anywhere else you might want to get data. * Fixed null value handling so plot now properly skip or join over nulls. * Fixed showTicks and showTickMarks option conflicts. * Fixed issue #185 where pointLabels plugin incompatibility could crash pie, donut and other plots. * Fixed #23 and #143 to obey gridPadding option. * Fixed #233 with highlighter tooltip separator. * Fixed #224 where type checking failing on GWT. * Fixed #272 with pie highlighting not working on replot. * Memory performance improvements. * Changes to build script so everything should build when pulled from repo. * Fixed issue #275, IE 6/7 don't support array indexing of strings. * Added event listener hooks for mouseUp, mouseDown, etc. to all line plots. * Fixed bug with highlighter not working when null in data. * Updated to jQuery 1.4.4 * Fixed bug where donut plots showed value of radians of slice instead of actual data. * Reverted to excanvas r3 so IE8 no longer has to emulate IE7. * Added tooltipContentEditor option to highlighter, allowing callback to manipulate tooltip content at run time (thanks Tim Bunce!). * Fixed bug where axes scale not resetting. * Fixed bug with date axes where data bounds not properly set. * Fixed issue where tick marks disappear if grid lines turned off. * Updated replot method to allow passing in axes options for more control. * Added experimental support for "broken" axes. * Fixed bug with pies where pies with 0 valued slices did not draw correctly. * Added canvasOverlay plugin to allow drawing of arbitrary shapes on a canvas over the plot. * Added option to display arbitrary text/html (message, animated gif, etc.) if plot is constructed without data. Allow a "data loading" indicator to be shown. * Added resetAxisValues method to manually update axis ticks without redrawing the plot. * Fix to labels on negative bars so label postiion of 'n' will be below a negative bar, just as it is above a positive bar (thanks guigod!). * Added thousands separator character (') to sprintf formatting (thanks yuichi1004!). * Re-factored date parsing/formatting to use new jsDate module which does not extend the Date prototype. 0.9.7: * Added Mekko chart plot type with enhanced legend and axes support. * Implemented vertical waterfall charts. Can create waterfall plot as option to bar chart. See examples folder of distribution. * Enhanced plot labels for waterfall style. * Enhanced bar plots so you can now color each bar of a series independently with the "varyBarColor" option. * Re-factored series drawing so that each series and series shadow drawn on its own canvas. Allows series to be redrawn independently of each other. * Added additional default series colors. * Added useNegativeColors option to turn off negative color array and use only seriesColors array to define all bar/filled line colors. * Fix css for cursor legend. * Modified shape renderer so rectangles can be stroked and filled. * Re-factored date methods out of dateAxisRenderer so that date formatter and methods can be accesses outside of dateAxisRenderer plugin. * Fixed #132, now trigger series change event on plot target instead of drag canvas. * Fixes issue #116 where some source files had mix of tabs and spaces for indentation. Should have been all spaces. * Fixed issue #126, some links broken in docs section of web site. * Fixed issue #90, trendline plugin incompatibility with pie renderer. * Updated samples in examples folder of distribution to include navigation links if web server is set up to process .html files with php. 0.9.6: * New, easier to use, replot() method for placing plots in tabs, accordions, resizable containers or for changing plot parameters programmatically. * Updated legend renderer for pie charts to draw swatches which will print correctly. * Fixed issue #118 with patch from taum so autoscale option will honor tickInterval and numberTicks options * Fix to plot diameter calculation for initially hidden plots. * Added examples for making plots in jQuery UI tabs and accordions. * Fixed issue #120 where pie chart with single slice not displaying correctly in IE and Chrome 0.9.5.2: * Fixed #102 where double clicking on plot that has zoom enabled, but has not been zoomed resulted in error. * Fixed bug where candlestick coloring options not working. * Added option to turn individual series labels off in the legend. 0.9.5.1: * Fixed bug where tooltip not working with OHLC and candlestick charts. * Added additional marker styles: plus, X and dash. 0.9.5: * Implemented "zoomProxy". zoomProxy allows zooming one plot from another such as an overview plot. * Zooming can now be constrained to just x or y axis. * Enhanced cursor plugin with vertical "dataTracking" line. This is a line at the cursor location with a readout of data points at the line location which are displayed in the chart legend. * Changed cursor tooltip format string. Now one format string is used for entire tooltip. * Added mechanisms to specify plot size when plot target is hidden or plot height/width otherwise cannot be determined from markup. * Added $.jqplot.config object to specify jqplot wide configuration options. These include enablePlugins to globally set the default plugin state on/off and defaultHeight/defaultWidth to specify default plot height/width. * Added fillToZero option which forces filled charts to fill to zero as opposed to axis minimum. Thus negative filled bar/line values will fill upwards to zero axis value. * Added option to disable stacking on individual lines. * Changed targetId property of the plot object so it now includes a "#" before the id string. * Improved tick and body sizing of Open Hi Low Close and candlestick charts. * Removed lots of web site related files from the repository. This means that, if working from the sources, user's won't be able to build the jqplot web site and the docs/tests that are hosted on that site. The minified and compressed distribution packages will build fine. * Lots of examples were added to a separate examples directory to better show functionality of jqPlot for local testing with the distribution. * Many various bug fixes and other minor enhancements. 0.9.4: * Implemented axis labels. Labels can be rendered in div tags or as canvas elements supporting rotated text. * Improved rotated axis label positioning so labels will start or end at a tick position. * Fixed bug where an empty data series would hang plot rendering. * completed issue #66 for misc. improvements to documentation. * Fixed issue #64 where the same ID's were assigned to cursor and highlighter elements. * Added option to legend to encode special HTML characters. * Fixed undesirable behavior where point labels for points off the plot were being rendered. * Added edgeTolerance option to point label renderer to control rendering of labels near plot edges. 0.9.3: * Preliminary support for axis labels. Currently rendered into DIV tags, so no rotated label support. This feature is currently experimental. * Fixed bug #52, needed space in tick div tag between style and class declarations or plot failed in certain application doctypes. * Fixed issue #54, miter style line join for chart lines causing spikes at steep changes in slope. Changed miter style to round. * Added examples for new autoscaling algorithm. * Fixed bug #57, category axis labels disappear on redraw() * Improved algorithm which controlled maximum number of labels that would display on a category axis. * Fixed bug #45 where null values causing errors in plotData and gridData. * Fixed issue #60 where seriesColors option was not working. 0.9.2: * Fixed bug #45 where a plot could crash if series had different numbers of points. * Fixed issue #50, added option to turn off sorting of series data. * Fixed issue #31, implemented a better axis autoscaling algorithm and added an autoscale option. 0.9.1: * Fixed bug #40, when axis pad, padMax, padMin set to 0, graph would fail to render. * Fixed bug #41 where pie and bar charts not rendered correctly on redraw(). * Fixed bug #11, filled stacked line plots not rendering correctly in IE. * Fixed bug #42 where stacked charts not rendering with string date axis ticks. * Fixed bug in redraw() method where axes ticks were not reset. * Fixed "jqplotPreRedrawEvent" that should have been named "jqplotPostRedraw" event. 0.9.0: * Added Open Hi Low Close charts, Candlestick charts and Hi Low Close charts. * Added support for arbitrary labels on the data points. * Enhanced highlighter plugin to allow custom formatting control of entire tooltip. * Enhanced highlighter to support multiple y values in a data point. * Fixed bug #38 where series with a single point with a negative value would fail. * Improvements to examples to show what plugins to include. * Expanded documentation for some of the plugins. 0.8.5: * Added zooming ability with double click or single click options to reset zoom. * Modified default tick spacing algorithm for date axes to give more space to ticks. * Fixed bug #2 where tickInterval wasn't working properly. * Added neighborThreshold option to control how close mouse must be to point to trigger neighbor detection. * Added double click event handler on plot. 0.8.0: * Support for up to 9 y axes. * Added option to control padding at max/min bounds of axes separately. * Closed issue #21, added options to control grid line color and width. * Closed issue #20, added options to filled line charts to stoke above fill and customize fill color and transparency. * Improved structure of on line documentation to make usage and options docs default. * Added much documentation on options and css styling. 0.7.1: * Bug fix release * Fixed bug #6, missing semi-colons messing up some javascript compressors. * Fixed bug #13 where 2D ticks array of [values, labels] would fail to renderer with DateAxisRenderer. * Fixes bug #16 where pie renderer overwriting options for all plot types and crashing non pie plots. * Fixes bug #17 constrainTo dragable option mispelled as "contstrainTo". Fixed dragable color issue when used with trend lines. 0.7.0: * Pie chart support * Enabled tooltipLocation option in highlighter. * Highlighter Tooltip will account for mark size and highlight size when positioning itself. * Added ability to show just x, y or both axes in highlighter tooltip. * Added customization of separator between axes values in highlighter tooltip. * Modified how shadows are drawn for lines, bars and markers. Now drawn first, so they are always behind the object. * Adjustments to shadow parameters on lines to account for new shadow positioning. * Added a ColorGenerator class to robustly return next available color for a plot with wrap around to first color at end. * Udates to docs about css file. * Fixed bug with String x values in series and IE error on sorting (Category Axis). * Added cursor changes in dragable plugin when cursor near dragable point. 0.6.6b: * Added excanvas.js and excanvas.min.js to compressed distributions. * Added example/test html pages I had locally into repository and to compressed distributions. 0.6.6a: * Removed absolute positioning from dom element and put back into css file. * Duplicate of 0.6.6 with a suffix to unambiguously differentiate between previously posted 0.6.6 release. 0.6.6: * Fixed bug #5, trend line plugin failing when no trend line options specified. * Added absolute position css spec to axis tick dom element. * Enhancement to category axes, more intuitive handling of series with missing data values. 0.6.5: * Fixed bug #4, series of unequal data length not rendering correctly. This is a bugfix release only. 0.6.4: * Fixed bug (issue #1 in tracker) where flat line data series (all x and/or y values are euqal) or single value data series would crash. 0.6.3: * Support for stacked line (a.k.a. area) and stacked bar (horizontal and vertical) charts. * Refactored barRenderer to use default shape and shadow renderers. * Added info (contacts & support information) page to web site. 0.6.2: * This is a minor upgrade to docs and build only. No functionality has changed. * Ant build script generates entire site, examples, tests and distribution. * Improvements to documentation. 0.6.1: * New sprintf implementation from Ash Searle that implements %g. * Fix to sprintf e/f formats. * Created new format specifier, %p and %P to preserve significance. * Modified p/P format to better display larger numbers. * Fixed and simplified significant digits calculation for sprintf. * Added option to have cursor tooltip follow the mouse or not. * Added options to change size of highlight. * Updates to handle dates like '6-May-09'. * Mods to improve look of web site. * Updates to documentation. * Added license and copyright statement to source files. 0.6.0: * Added rotated text support. Uses native canvas text functionality in browsers that support it or draws text on canvas with Hershey font * metrics for non-supporting browsers. * Removed lots of lint in js code. * Moved tick css from js code into css file. * Fix to tick positioning css. y axis ticks were positioned to wrong side of axis div. * Re-factored axis tick renderer instantiation into the axes renderers themselves. For changes prior to 0.6.0 release, please see change log at http://bitbucket.org/cleonello/jqplot/changesets/ /*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) * Licensed under the MIT License (LICENSE.txt). * * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. * Thanks to: Seamus Leahy for adding deltaX and deltaY * * Version: 3.0.6 * * Requires: 1.2.2+ */ (function(d){function e(a){var b=a||window.event,c=[].slice.call(arguments,1),f=0,e=0,g=0,a=d.event.fix(b);a.type="mousewheel";b.wheelDelta&&(f=b.wheelDelta/120);b.detail&&(f=-b.detail/3);g=f;b.axis!==void 0&&b.axis===b.HORIZONTAL_AXIS&&(g=0,e=-1*f);b.wheelDeltaY!==void 0&&(g=b.wheelDeltaY/120);b.wheelDeltaX!==void 0&&(e=-1*b.wheelDeltaX/120);c.unshift(a,f,e,g);return(d.event.dispatch||d.event.handle).apply(this,c)}var c=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks)for(var h=c.length;h;)d.event.fixHooks[c[--h]]= d.event.mouseHooks;d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,false);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,false);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);/*! * jQuery JavaScript Library v1.4.2 * http://jquery.com/ * * Copyright 2010, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2010, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Sat Feb 13 22:33:48 2010 -0500 */ (function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& (d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== "find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
    a"; var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, "_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== "="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

    ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); (function(){var g=s.createElement("div");g.innerHTML="
    ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= {},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== "string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== 1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
    ","
    "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, ""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", ""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, "border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== "string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
    ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? "&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== 1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== "json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== "number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
    "; a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": "pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); phpDocumentor

    displayXHProfReport(object $xhprof_runs_impl, array $url_params, string $source, string $run, string $wts, string $symbol, $sort, string $run1, string $run2) : void

    Generate a XHProf Display View given the various URL parameters as arguments. The first argument is an object that implements the iXHProfRuns interface.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non neque id mauris pharetra imperdiet. Mauris auctor, lectus id posuere fringilla, ligula eros iaculis odio, quis ornare augue erat id eros. Sed lorem lectus, luctus ullamcorper varius quis, viverra ut lacus. Aenean vitae leo massa, a ullamcorper velit. Nulla commodo velit id enim elementum eu tempor ipsum semper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Proin sed arcu quam, bibendum vulputate nulla.
    « More »
    template.xml ============ Generates an XML representation of the project's structure Zend Framework: API Documentation
    ]>

    API Documentation