From b5968939dcbdc6d56be7fc3c13dc74267bf94acb Mon Sep 17 00:00:00 2001 From: Rob Aiken Date: Mon, 8 Apr 2019 11:09:24 +0100 Subject: [PATCH 1/7] merged master --- .gitignore | 5 - .travis.yml | 7 - LICENSE | 13 - README.md | 42 - bin/BuildBootstrapConfigs.php | 63 -- bin/buildJsonConfig.php | 19 - composer.json | 28 - .../Annotation/AnnotationConfigProvider.php | 18 - .../Annotation/AnnotationConfigurator.php | 203 ----- lib/Weasel/Annotation/AnnotationReader.php | 251 ------ .../Annotation/AnnotationReaderFactory.php | 63 -- .../ArrayCachingAnnotationConfigurator.php | 29 - lib/Weasel/Annotation/Config/Annotation.php | 223 ----- .../Annotation/Config/AnnotationConfig.php | 49 -- .../Config/Annotations/Annotation.php | 42 - .../Config/Annotations/AnnotationCreator.php | 40 - .../Annotation/Config/Annotations/Enum.php | 36 - .../Config/Annotations/Parameter.php | 50 -- .../Config/Annotations/Property.php | 41 - .../Annotation/Config/BuiltInsProvider.php | 62 -- lib/Weasel/Annotation/Config/Enum.php | 48 -- lib/Weasel/Annotation/Config/Param.php | 62 -- lib/Weasel/Annotation/Config/Property.php | 47 - lib/Weasel/Annotation/DocblockLexer.php | 263 ------ lib/Weasel/Annotation/DocblockParser.php | 471 ---------- lib/Weasel/Annotation/PhpParser.php | 255 ------ .../WeaslDefaultAnnotationDrivenContext.xml | 38 - .../BuildJsonMapperJsonConfigCommand.php | 104 --- .../BuildXmlMapperJsonConfigCommand.php | 104 --- .../Common/Annotation/IAnnotationReader.php | 72 -- .../Annotation/IAnnotationReaderFactory.php | 24 - lib/Weasel/Common/Cache/ApcCache.php | 53 -- lib/Weasel/Common/Cache/ArrayCache.php | 50 -- lib/Weasel/Common/Cache/Cache.php | 80 -- .../Common/Cache/CacheAwareInterface.php | 12 - lib/Weasel/Common/Cache/CacheException.php | 22 - .../Common/Cache/Exception/BackingFailure.php | 14 - lib/Weasel/Common/Logger/FileLogger.php | 55 -- lib/Weasel/Common/Logger/Logger.php | 22 - .../Common/Utils/NoUndeclaredProperties.php | 33 - lib/Weasel/Common/Utils/ReflectionUtils.php | 70 -- .../DoctrineAnnotationReaderAdapter.php | 157 ---- .../DoctrineAnnotationReaderFactory.php | 45 - .../DoctrineAnnotation/WeaselCacheAdapter.php | 114 --- .../Config/AnnotationDriver.php | 96 --- .../Config/Annotations/JsonAnyGetter.php | 20 - .../Config/Annotations/JsonAnySetter.php | 20 - .../Config/Annotations/JsonCreator.php | 44 - .../Annotations/JsonIgnoreProperties.php | 53 -- .../Config/Annotations/JsonInclude.php | 55 -- .../Config/Annotations/JsonProperty.php | 58 -- .../Config/Annotations/JsonSubTypes.php | 45 - .../Config/Annotations/JsonSubTypes/Type.php | 57 -- .../Config/Annotations/JsonTypeInfo.php | 123 --- .../Config/Annotations/JsonTypeName.php | 39 - .../Config/ArrayCachingAnnotationDriver.php | 27 - .../Config/ClassAnnotationDriver.php | 620 -------------- .../JsonMarshaller/Config/ClassMarshaller.php | 42 - .../Deserialization/ClassDeserialization.php | 79 -- .../Config/Deserialization/Creator.php | 36 - .../Deserialization/DelegateCreator.php | 24 - .../Deserialization/DirectDeserialization.php | 34 - .../Config/Deserialization/Feature.php | 31 - .../Config/Deserialization/Param.php | 30 - .../Deserialization/PropertyCreator.php | 29 - .../PropertyDeserialization.php | 69 -- .../Deserialization/SetterDeserialization.php | 36 - .../Config/Deserialization/TypeInfo.php | 65 -- .../DoctrineAnnotations/JsonAnyGetter.php | 21 - .../DoctrineAnnotations/JsonAnySetter.php | 21 - .../DoctrineAnnotations/JsonCreator.php | 51 -- .../JsonIgnoreProperties.php | 68 -- .../DoctrineAnnotations/JsonInclude.php | 38 - .../DoctrineAnnotations/JsonProperty.php | 77 -- .../DoctrineAnnotations/JsonSubTypes.php | 35 - .../DoctrineAnnotations/JsonSubTypes/Type.php | 49 -- .../DoctrineAnnotations/JsonTypeInfo.php | 81 -- .../DoctrineAnnotations/JsonTypeName.php | 35 - .../Config/IAnnotations/IJsonAnyGetter.php | 18 - .../Config/IAnnotations/IJsonAnySetter.php | 18 - .../Config/IAnnotations/IJsonCreator.php | 20 - .../IAnnotations/IJsonIgnoreProperties.php | 25 - .../Config/IAnnotations/IJsonInclude.php | 25 - .../Config/IAnnotations/IJsonProperty.php | 36 - .../Config/IAnnotations/IJsonSubTypes.php | 21 - .../Config/IAnnotations/IJsonTypeInfo.php | 63 -- .../Config/IAnnotations/IJsonTypeName.php | 21 - .../IAnnotations/JsonSubTypes/IType.php | 26 - .../Config/JsonConfigProvider.php | 22 - .../Config/MultiConfigProvider.php | 46 - .../Config/PropertyConfigProvider.php | 45 - .../Serialization/ClassSerialization.php | 51 -- .../Serialization/DirectSerialization.php | 35 - .../Serialization/GetterSerialization.php | 40 - .../Serialization/PropertySerialization.php | 68 -- .../Config/Serialization/TypeInfo.php | 53 -- .../Config/SerializedConfigProvider.php | 45 - .../JsonMarshaller/Config/Type/ListType.php | 23 - .../JsonMarshaller/Config/Type/MapType.php | 36 - .../JsonMarshaller/Config/Type/ScalarType.php | 28 - .../JsonMarshaller/Config/Type/Type.php | 25 - .../JsonMarshaller/Config/Type/TypeParser.php | 45 - .../JsonMarshaller/Config/bootstrap.cnf | 1 - .../Exception/BadConfigurationException.php | 13 - .../Exception/InvalidTypeException.php | 66 -- .../Exception/JsonMarshallerException.php | 13 - .../Exception/UnknownPropertyException.php | 8 - lib/Weasel/JsonMarshaller/JsonMapper.php | 694 --------------- lib/Weasel/JsonMarshaller/Types/BoolType.php | 36 - .../JsonMarshaller/Types/DateTimeType.php | 53 -- lib/Weasel/JsonMarshaller/Types/FloatType.php | 37 - lib/Weasel/JsonMarshaller/Types/IntType.php | 41 - lib/Weasel/JsonMarshaller/Types/JsonType.php | 30 - .../JsonMarshaller/Types/OldTypeWrapper.php | 29 - .../JsonMarshaller/Types/StringType.php | 32 - lib/Weasel/JsonMarshaller/Types/Type.php | 34 - .../WeaselDefaultAnnotationDrivenFactory.php | 181 ---- .../WeaselDoctrineAnnotationDrivenFactory.php | 197 ----- lib/Weasel/WeaselFactory.php | 30 - lib/Weasel/WeaselJsonConfigDrivenFactory.php | 161 ---- .../XmlMarshaller/Config/AnnotationDriver.php | 93 -- .../Config/Annotations/XmlAttribute.php | 65 -- .../Config/Annotations/XmlDiscriminator.php | 45 - .../Annotations/XmlDiscriminatorValue.php | 45 - .../Config/Annotations/XmlElement.php | 74 -- .../Config/Annotations/XmlElementRef.php | 56 -- .../Config/Annotations/XmlElementRefs.php | 46 - .../Config/Annotations/XmlElementWrapper.php | 65 -- .../Config/Annotations/XmlRootElement.php | 46 - .../Config/Annotations/XmlSeeAlso.php | 42 - .../Config/Annotations/XmlType.php | 105 --- .../Config/ClassAnnotationDriver.php | 448 ---------- .../XmlMarshaller/Config/ClassMarshaller.php | 26 - .../XmlMarshaller/Config/ConfigProvider.php | 18 - .../AttributeDeserialization.php | 20 - .../Deserialization/ClassDeserialization.php | 85 -- .../Deserialization/DirectDeserialization.php | 25 - .../ElementDeserialization.php | 49 -- .../Config/Deserialization/ElementWrapper.php | 38 - .../Config/Deserialization/Param.php | 25 - .../PropertyDeserialization.php | 37 - .../Deserialization/SetterDeserialization.php | 25 - .../Config/Deserialization/TypeInfo.php | 58 -- .../DoctrineAnnotations/XmlAttribute.php | 61 -- .../DoctrineAnnotations/XmlDiscriminator.php | 35 - .../XmlDiscriminatorValue.php | 35 - .../Config/DoctrineAnnotations/XmlElement.php | 71 -- .../DoctrineAnnotations/XmlElementRef.php | 51 -- .../DoctrineAnnotations/XmlElementRefs.php | 41 - .../DoctrineAnnotations/XmlElementWrapper.php | 62 -- .../DoctrineAnnotations/XmlRootElement.php | 41 - .../Config/DoctrineAnnotations/XmlSeeAlso.php | 35 - .../Config/DoctrineAnnotations/XmlType.php | 83 -- .../Config/IAnnotations/IXmlAttribute.php | 19 - .../Config/IAnnotations/IXmlDiscriminator.php | 15 - .../IAnnotations/IXmlDiscriminatorValue.php | 18 - .../Config/IAnnotations/IXmlElement.php | 23 - .../Config/IAnnotations/IXmlElementRef.php | 19 - .../Config/IAnnotations/IXmlElementRefs.php | 20 - .../IAnnotations/IXmlElementWrapper.php | 21 - .../Config/IAnnotations/IXmlRootElement.php | 17 - .../Config/IAnnotations/IXmlSeeAlso.php | 18 - .../Config/IAnnotations/XmlType.php | 35 - .../Config/PropertyConfigProvider.php | 45 - .../Serialization/ClassSerialization.php | 35 - .../Serialization/DirectSerialization.php | 25 - .../Serialization/GetterSerialization.php | 25 - .../Serialization/PropertySerialization.php | 41 - .../Config/Serialization/TypeInfo.php | 47 - lib/Weasel/XmlMarshaller/XmlMapper.php | 476 ----------- lib/WeaselAutoloader.php | 31 - .../Annotation/AnnotationConfiguratorTest.php | 667 --------------- .../Annotation/AnnotationReaderTest.php | 33 - tests/Weasel/Annotation/DocblockLexerTest.php | 255 ------ .../Weasel/Annotation/DocblockParserTest.php | 612 ------------- tests/Weasel/Annotation/PHPParserTest.php | 80 -- tests/Weasel/Annotation/TestDocblock.txt | 9 - .../Annotation/resources/AnnotatedClass.php | 8 - .../resources/MultipleNamespace.php | 30 - .../resources/NamespacedShorthand.php | 16 - .../Annotation/resources/NoDocBlock.php | 5 - .../Annotation/resources/NoNamespace.php | 11 - .../Annotation/resources/PHPGolfNamespace.php | 19 - .../Annotation/resources/SimpleNamespaced.php | 24 - .../resources/SimpleNamespacedExtends.php | 22 - .../DoctrineAnnotationReaderFactoryTest.php | 76 -- .../Config/Annotations/JsonCreatorTest.php | 101 --- .../Annotations/JsonIgnorePropertiesTest.php | 103 --- .../Config/Annotations/JsonIncludeTest.php | 106 --- .../Config/Annotations/JsonPropertyTest.php | 112 --- .../Annotations/JsonSubTypes/TypeTest.php | 103 --- .../Config/Annotations/JsonSubTypesTest.php | 100 --- .../Config/Annotations/JsonTypeInfoTest.php | 126 --- .../Config/Annotations/JsonTypeNameTest.php | 96 --- .../Config/ClassAnnotationDriverTest.php | 106 --- .../DoctrineAnnotations/JsonAnyGetterTest.php | 45 - .../DoctrineAnnotations/JsonAnySetterTest.php | 45 - .../DoctrineAnnotations/JsonCreatorTest.php | 106 --- .../JsonIgnorePropertiesTest.php | 114 --- .../DoctrineAnnotations/JsonIncludeTest.php | 38 - .../Weasel/JsonMarshaller/JsonMapperTest.php | 802 ------------------ .../JsonMarshaller/Types/BoolTypeTest.php | 139 --- .../JsonMarshaller/Types/DateTimeTypeTest.php | 138 --- .../JsonMarshaller/Types/FloatTypeTest.php | 132 --- .../JsonMarshaller/Types/IntTypeTest.php | 138 --- .../Types/OldTypeWrapperTest.php | 150 ---- .../JsonMarshaller/Types/StringTypeTest.php | 110 --- tests/benchmark.php | 21 - tests/bootstrap.php | 12 - 209 files changed, 15989 deletions(-) delete mode 100644 .gitignore delete mode 100644 .travis.yml delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 bin/BuildBootstrapConfigs.php delete mode 100644 bin/buildJsonConfig.php delete mode 100644 composer.json delete mode 100644 lib/Weasel/Annotation/AnnotationConfigProvider.php delete mode 100644 lib/Weasel/Annotation/AnnotationConfigurator.php delete mode 100644 lib/Weasel/Annotation/AnnotationReader.php delete mode 100644 lib/Weasel/Annotation/AnnotationReaderFactory.php delete mode 100644 lib/Weasel/Annotation/ArrayCachingAnnotationConfigurator.php delete mode 100644 lib/Weasel/Annotation/Config/Annotation.php delete mode 100644 lib/Weasel/Annotation/Config/AnnotationConfig.php delete mode 100644 lib/Weasel/Annotation/Config/Annotations/Annotation.php delete mode 100644 lib/Weasel/Annotation/Config/Annotations/AnnotationCreator.php delete mode 100644 lib/Weasel/Annotation/Config/Annotations/Enum.php delete mode 100644 lib/Weasel/Annotation/Config/Annotations/Parameter.php delete mode 100644 lib/Weasel/Annotation/Config/Annotations/Property.php delete mode 100644 lib/Weasel/Annotation/Config/BuiltInsProvider.php delete mode 100644 lib/Weasel/Annotation/Config/Enum.php delete mode 100644 lib/Weasel/Annotation/Config/Param.php delete mode 100644 lib/Weasel/Annotation/Config/Property.php delete mode 100644 lib/Weasel/Annotation/DocblockLexer.php delete mode 100644 lib/Weasel/Annotation/DocblockParser.php delete mode 100644 lib/Weasel/Annotation/PhpParser.php delete mode 100644 lib/Weasel/BounceContexts/WeaslDefaultAnnotationDrivenContext.xml delete mode 100644 lib/Weasel/Command/BuildJsonMapperJsonConfigCommand.php delete mode 100644 lib/Weasel/Command/BuildXmlMapperJsonConfigCommand.php delete mode 100644 lib/Weasel/Common/Annotation/IAnnotationReader.php delete mode 100644 lib/Weasel/Common/Annotation/IAnnotationReaderFactory.php delete mode 100644 lib/Weasel/Common/Cache/ApcCache.php delete mode 100644 lib/Weasel/Common/Cache/ArrayCache.php delete mode 100644 lib/Weasel/Common/Cache/Cache.php delete mode 100644 lib/Weasel/Common/Cache/CacheAwareInterface.php delete mode 100644 lib/Weasel/Common/Cache/CacheException.php delete mode 100644 lib/Weasel/Common/Cache/Exception/BackingFailure.php delete mode 100644 lib/Weasel/Common/Logger/FileLogger.php delete mode 100644 lib/Weasel/Common/Logger/Logger.php delete mode 100644 lib/Weasel/Common/Utils/NoUndeclaredProperties.php delete mode 100644 lib/Weasel/Common/Utils/ReflectionUtils.php delete mode 100644 lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderAdapter.php delete mode 100644 lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactory.php delete mode 100644 lib/Weasel/DoctrineAnnotation/WeaselCacheAdapter.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/AnnotationDriver.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnyGetter.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnySetter.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonCreator.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonIgnoreProperties.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonInclude.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonProperty.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/Type.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfo.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeName.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/ArrayCachingAnnotationDriver.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/ClassAnnotationDriver.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/ClassMarshaller.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/ClassDeserialization.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/Creator.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/DelegateCreator.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/DirectDeserialization.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/Feature.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/Param.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyCreator.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyDeserialization.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/SetterDeserialization.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/TypeInfo.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetter.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetter.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonInclude.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes/Type.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeInfo.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeName.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnyGetter.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnySetter.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonCreator.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonIgnoreProperties.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonInclude.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonProperty.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonSubTypes.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeInfo.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeName.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/JsonSubTypes/IType.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/JsonConfigProvider.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/MultiConfigProvider.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/PropertyConfigProvider.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Serialization/ClassSerialization.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Serialization/DirectSerialization.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Serialization/GetterSerialization.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Serialization/PropertySerialization.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Serialization/TypeInfo.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/SerializedConfigProvider.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Type/ListType.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Type/MapType.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Type/ScalarType.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Type/Type.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/Type/TypeParser.php delete mode 100644 lib/Weasel/JsonMarshaller/Config/bootstrap.cnf delete mode 100644 lib/Weasel/JsonMarshaller/Exception/BadConfigurationException.php delete mode 100644 lib/Weasel/JsonMarshaller/Exception/InvalidTypeException.php delete mode 100644 lib/Weasel/JsonMarshaller/Exception/JsonMarshallerException.php delete mode 100644 lib/Weasel/JsonMarshaller/Exception/UnknownPropertyException.php delete mode 100644 lib/Weasel/JsonMarshaller/JsonMapper.php delete mode 100644 lib/Weasel/JsonMarshaller/Types/BoolType.php delete mode 100644 lib/Weasel/JsonMarshaller/Types/DateTimeType.php delete mode 100644 lib/Weasel/JsonMarshaller/Types/FloatType.php delete mode 100644 lib/Weasel/JsonMarshaller/Types/IntType.php delete mode 100644 lib/Weasel/JsonMarshaller/Types/JsonType.php delete mode 100644 lib/Weasel/JsonMarshaller/Types/OldTypeWrapper.php delete mode 100644 lib/Weasel/JsonMarshaller/Types/StringType.php delete mode 100644 lib/Weasel/JsonMarshaller/Types/Type.php delete mode 100644 lib/Weasel/WeaselDefaultAnnotationDrivenFactory.php delete mode 100644 lib/Weasel/WeaselDoctrineAnnotationDrivenFactory.php delete mode 100644 lib/Weasel/WeaselFactory.php delete mode 100644 lib/Weasel/WeaselJsonConfigDrivenFactory.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/AnnotationDriver.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlAttribute.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminator.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminatorValue.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlElement.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRef.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRefs.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementWrapper.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlRootElement.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlSeeAlso.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlType.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/ClassAnnotationDriver.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/ClassMarshaller.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/ConfigProvider.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/AttributeDeserialization.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/ClassDeserialization.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/DirectDeserialization.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/ElementDeserialization.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/ElementWrapper.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/Param.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/PropertyDeserialization.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/SetterDeserialization.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/TypeInfo.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlAttribute.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminator.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminatorValue.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElement.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRef.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRefs.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementWrapper.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlRootElement.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlSeeAlso.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlType.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlAttribute.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminator.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminatorValue.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElement.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRef.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRefs.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementWrapper.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlRootElement.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlSeeAlso.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/XmlType.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/PropertyConfigProvider.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Serialization/ClassSerialization.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Serialization/DirectSerialization.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Serialization/GetterSerialization.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Serialization/PropertySerialization.php delete mode 100644 lib/Weasel/XmlMarshaller/Config/Serialization/TypeInfo.php delete mode 100644 lib/Weasel/XmlMarshaller/XmlMapper.php delete mode 100644 lib/WeaselAutoloader.php delete mode 100644 tests/Weasel/Annotation/AnnotationConfiguratorTest.php delete mode 100644 tests/Weasel/Annotation/AnnotationReaderTest.php delete mode 100644 tests/Weasel/Annotation/DocblockLexerTest.php delete mode 100644 tests/Weasel/Annotation/DocblockParserTest.php delete mode 100644 tests/Weasel/Annotation/PHPParserTest.php delete mode 100644 tests/Weasel/Annotation/TestDocblock.txt delete mode 100644 tests/Weasel/Annotation/resources/AnnotatedClass.php delete mode 100644 tests/Weasel/Annotation/resources/MultipleNamespace.php delete mode 100644 tests/Weasel/Annotation/resources/NamespacedShorthand.php delete mode 100644 tests/Weasel/Annotation/resources/NoDocBlock.php delete mode 100644 tests/Weasel/Annotation/resources/NoNamespace.php delete mode 100644 tests/Weasel/Annotation/resources/PHPGolfNamespace.php delete mode 100644 tests/Weasel/Annotation/resources/SimpleNamespaced.php delete mode 100644 tests/Weasel/Annotation/resources/SimpleNamespacedExtends.php delete mode 100644 tests/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactoryTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetterTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetterTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreatorTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnorePropertiesTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIncludeTest.php delete mode 100644 tests/Weasel/JsonMarshaller/JsonMapperTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Types/BoolTypeTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Types/DateTimeTypeTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Types/FloatTypeTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Types/IntTypeTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Types/OldTypeWrapperTest.php delete mode 100644 tests/Weasel/JsonMarshaller/Types/StringTypeTest.php delete mode 100644 tests/benchmark.php delete mode 100644 tests/bootstrap.php diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1432d60..0000000 --- a/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.idea/ -atlassian-ide-plugin.xml -vendor/ -composer.lock -*.iml \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f83ec01..0000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: php -php: - - "5.6" - - "5.5" - - "5.4" -before_script: composer install -n --dev -script: "phpunit --coverage-text --bootstrap ./tests/bootstrap.php tests" diff --git a/LICENSE b/LICENSE deleted file mode 100644 index da13ce2..0000000 --- a/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2012, Moo Print Ltd. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index eab642b..0000000 --- a/README.md +++ /dev/null @@ -1,42 +0,0 @@ -PHP Weasel -========== -[![Build Status](https://travis-ci.org/moodev/php-weasel.png)](https://travis-ci.org/moodev/php-weasel) - -Weasel is an object marshalling library for PHP supporting JSON and XML. Marshalling is, by default, configured using “annotations”, driven by the `Doctrine\Common\Annotation` library. - -It also includes its own Annotation library, `Weasel\Annotation`, but this is considered deprecated in favour of using Doctrine. - -The latest version can be found here: https://github.com/moodev/php-weasel - -The documentation can be found here: https://github.com/moodev/php-weasel/wiki - -Installation ------------- - -If you can, use [composer](http://getcomposer.org/). If you can't, you'll find the list of dependencies in [composer.json](./composer.json). - -Usage ------ - -Annotate the classes you want to serialize/deserialize (see the documentation.) - -Then: -```php -$factory = new WeaselDoctrineAnnotationDrivenFactory(); -// optionally: - $factory->setCache($cacheInstance); - $factory->setLogger($psr3LoggerInstance); - -$mapper = $factory->getJsonMapperInstance(); -$thing = $mapper->readString($json, $typeToDecodeTo); -$backToJson = $mapper->writeString($thing); -``` -Why? ----- -`json_decode()` decodes to arrays or stdObj. Weasel, while making use of `json_decode()` internally, maps to objects; it's basically a configuration driven Object Mapper for JSON. - -Meanwhile, `json_encode()` gives you no fine grained control over how your data gets serialized to JSON. You can't disable marshalling of fields, you can't add typing information without adding it to your classes, and, most annoyingly, you don't have any control over how `array()` gets mapped on a field-by-field basis. Weasel allows you to configure how fields are marshalled on a per-field level: if you've got an array that should always be mapped as a JSON object, while other arrays need to be mapped as an array, you can have just that. - -The `XmlMarshaller` just seemed like a good idea at the time. It probably wasn't. It's incomplete and unloved. As soon as I find a better approach to the problem, it'll be deprecated. - -This project spawned from work on [moo-php](https://github.com/JonathanO/moo-php), a client library for the moo.com API. After writing serialization/deserialization code that was specific to that object structure, I realised that a general purpose, configurable marshaller, similar to Jackson in the Java world, would be rather useful. Weasel is the result. diff --git a/bin/BuildBootstrapConfigs.php b/bin/BuildBootstrapConfigs.php deleted file mode 100644 index 8820a1c..0000000 --- a/bin/BuildBootstrapConfigs.php +++ /dev/null @@ -1,63 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - * - * Builds the serialized bootstrap configs from the annotation driven configs. - */ - - -require_once(__DIR__ . '/../vendor/autoload.php'); - -$factory = new \Weasel\WeaselDoctrineAnnotationDrivenFactory(); - -$readerProvider = $factory->getAnnotationReaderFactoryInstance(); -$jsonProvider = new \Weasel\JsonMarshaller\Config\AnnotationDriver($readerProvider); -$jsonProvider->setAnnotationNamespace('\Weasel\JsonMarshaller\Config\DoctrineAnnotations'); - -$config = array(); - -addConfig('\Weasel\JsonMarshaller\Config\ClassMarshaller', $config, $jsonProvider); -buildSubConfig(__DIR__ . '/../lib/Weasel/JsonMarshaller/Config/Deserialization', - '\Weasel\JsonMarshaller\Config\Deserialization', - $config, - $jsonProvider); -buildSubConfig(__DIR__ . '/../lib/Weasel/JsonMarshaller/Config/Serialization', - '\Weasel\JsonMarshaller\Config\Serialization', - $config, - $jsonProvider); - -addConfig('\Weasel\XmlMarshaller\Config\ClassMarshaller', $config, $jsonProvider); -buildSubConfig(__DIR__ . '/../lib/Weasel/XmlMarshaller/Config/Deserialization', - '\Weasel\XmlMarshaller\Config\Deserialization', - $config, - $jsonProvider); -buildSubConfig(__DIR__ . '/../lib/Weasel/XmlMarshaller/Config/Serialization', - '\Weasel\XmlMarshaller\Config\Serialization', - $config, - $jsonProvider); - -file_put_contents(__DIR__ . '/../lib/Weasel/JsonMarshaller/Config/bootstrap.cnf', serialize($config)); - -exit(0); - -function addConfig($class, &$config, \Weasel\JsonMarshaller\Config\AnnotationDriver $provider) -{ - $config[ltrim($class, '\\')] = $provider->getConfig($class); -} - -function buildSubConfig($dir, $bns, &$config, $provider) -{ - $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS; - foreach (new FilesystemIterator($dir, $flags) as $fileInfo) { - /** - * @var SplFileInfo $fileInfo - */ - $class = $bns . '\\' . $fileInfo->getBasename(".php"); - addConfig($class, $config, $provider); - } -} - - - diff --git a/bin/buildJsonConfig.php b/bin/buildJsonConfig.php deleted file mode 100644 index 80efeff..0000000 --- a/bin/buildJsonConfig.php +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/php -add(new BuildJsonMapperJsonConfigCommand()); -$application->add(new BuildXmlMapperJsonConfigCommand()); -$application->run(); - diff --git a/composer.json b/composer.json deleted file mode 100644 index 4ac922e..0000000 --- a/composer.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "moodev/Weasel", - "type": "library", - "description": "Object marshalling library for PHP supporting JSON and XML", - "keywords": ["marshall", "marshalling", "json", "serialization", "deserialization", "jackson"], - "homepage": "http://github.com/moodev/php-weasel", - "license": "ISC", - "require": { - "php": ">=5.3.0", - "psr/log": "~1.0", - "doctrine/annotations": "~1.1", - "doctrine/cache": "~1.0", - "symfony/Console": ">=2.3" - }, - "require-dev": { - "mockery/mockery": "dev-master", - "phpunit/phpunit": "4.3.*" - }, - "suggest": { - "monolog/monolog": "A logging framework that implements PSR 3" - }, - "autoload": { - "psr-0": { - "Weasel": "lib" - } - }, - "bin": ["bin/buildJsonConfig.php"] -} diff --git a/lib/Weasel/Annotation/AnnotationConfigProvider.php b/lib/Weasel/Annotation/AnnotationConfigProvider.php deleted file mode 100644 index f642ff7..0000000 --- a/lib/Weasel/Annotation/AnnotationConfigProvider.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation; - -interface AnnotationConfigProvider -{ - - /** - * @abstract - * @param string $name The name of the annotation to load - * @return \Weasel\Annotation\Config\Annotation The annotation object - */ - public function get($name); -} diff --git a/lib/Weasel/Annotation/AnnotationConfigurator.php b/lib/Weasel/Annotation/AnnotationConfigurator.php deleted file mode 100644 index 30e62fb..0000000 --- a/lib/Weasel/Annotation/AnnotationConfigurator.php +++ /dev/null @@ -1,203 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation; - -use Weasel\Common\Cache\Cache; -use Weasel\Common\Cache\Exception; - -use Psr\Log\LoggerInterface; -use Psr\Log\LoggerAwareInterface; -use Weasel\Common\Cache\CacheAwareInterface; - -class AnnotationConfigurator implements AnnotationConfigProvider, LoggerAwareInterface, CacheAwareInterface -{ - - /** - * @var Config\AnnotationConfig - */ - protected static $builtIns; - - protected $logger; - - /** - * @var Cache - */ - protected $cache; - - protected $ownedFactory = false; - - /** - * @var AnnotationReaderFactory - */ - protected $readerFactory = null; - - public function __construct(LoggerInterface $logger = null, - Cache $cache = null, - AnnotationReaderFactory $readerFactory = null) - { - if (isset($logger)) { - $this->setLogger($logger); - } - if (isset($cache)) { - $this->setCache($cache); - } - if (!isset(self::$builtIns)) { - self::$builtIns = Config\BuiltInsProvider::getConfig(); - } - if (isset($readerFactory)) { - $this->setReaderFactory($readerFactory); - } else { - $readerFactory = new AnnotationReaderFactory($this); - $this->ownedFactory = true; - if (isset($logger)) { - $readerFactory->setLogger($logger); - } - $this->setReaderFactory($readerFactory); - } - - } - - public function get($name) - { - if (isset($this->cache)) { - $found = false; - $cached = $this->cache->get($name, "Annotation", $found); - if ($found) { - return $cached; - } - } - - if (self::$builtIns->getAnnotation($name)) { - return self::$builtIns->getAnnotation($name); - } - - $class = new \ReflectionClass($name); - $reader = $this->readerFactory->getReaderForClass($class); - - /** - * @var \Weasel\Annotation\Config\Annotations\Annotation $annotation - */ - $annotation = $reader->getSingleClassAnnotation('\Weasel\Annotation\Config\Annotations\Annotation'); - if (!isset($annotation)) { - throw new \RuntimeException("Did not find an @Annotation annotation on $name"); - } - - $metaConfig = new Config\Annotation($name, $annotation->getOn(), $annotation->getMax()); - - foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { - /** - * @var \ReflectionMethod $method - * @var \Weasel\Annotation\Config\Annotations\AnnotationCreator $creator - */ - $creator = $reader->getSingleMethodAnnotation($method->getName(), - '\Weasel\Annotation\Config\Annotations\AnnotationCreator' - ); - if (isset($creator)) { - if (!$method->isStatic() && !$method->isConstructor()) { - throw new \RuntimeException("Non-static methods cannot be configured as creators"); - } - $metaConfig->setCreatorMethod($method->getName()); - $creatorArgs = $method->getParameters(); - if (count($creatorArgs) != count($creator->getParams())) { - throw new \RuntimeException("Creator args don't match with method args"); - } - $i = 0; - foreach ($creator->getParams() as $param) { - $paramName = $param->getName(); - if (!isset($paramName)) { - $paramName = $creatorArgs[$i]->getName(); - } - $creatorParam = new Config\Param($paramName, $param->getType(), $param->getRequired()); - $i++; - $metaConfig->addCreatorParam($creatorParam); - } - - } - } - - foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { - /** - * @var \ReflectionProperty $property - * @var \Weasel\Annotation\Config\Annotations\Property $annotProperty - */ - $annotProperty = $reader->getSinglePropertyAnnotation($property->getName(), - '\Weasel\Annotation\Config\Annotations\Property' - ); - - if (isset($annotProperty)) { - $propertyConfig = new Config\Property($property->getName(), $annotProperty->getType()); - $metaConfig->addProperty($propertyConfig); - } - - /** - * @var \Weasel\Annotation\Config\Annotations\Enum $annotEnum - */ - $annotEnum = $reader->getSinglePropertyAnnotation($property->getName(), - '\Weasel\Annotation\Config\Annotations\Enum' - ); - - if (isset($annotEnum)) { - if (!$property->isStatic()) { - throw new \RuntimeException("Enums must be static properties"); - } - $name = $annotEnum->getName(); - if (!isset($name)) { - $name = $property->getName(); - } - $value = $property->getValue(null); - if (!is_array($value)) { - throw new \RuntimeException("Enum must be an array"); - } - $metaConfig->addEnum(new Config\Enum($name, $value)); - } - - } - - if (isset($this->cache)) { - $this->cache->set($name, $metaConfig, "Annotation"); - } - - return $metaConfig; - } - - public function getLogger() - { - return $this->logger; - } - - /** - * @param \Weasel\Annotation\AnnotationReaderFactory $readerFactory - * @return AnnotationConfigurator - */ - public function setReaderFactory($readerFactory) - { - $this->readerFactory = $readerFactory; - return $this; - } - - /** - * @param \Weasel\Common\Cache\Cache $cache - */ - public function setCache(Cache $cache) - { - $this->cache = $cache; - } - - /** - * Sets a logger instance on the object - * - * @param LoggerInterface $logger - * @return null - */ - public function setLogger(LoggerInterface $logger) - { - $this->logger = $logger; - if ($this->ownedFactory) { - $this->readerFactory->setLogger($logger); - } - } -} diff --git a/lib/Weasel/Annotation/AnnotationReader.php b/lib/Weasel/Annotation/AnnotationReader.php deleted file mode 100644 index 1a30626..0000000 --- a/lib/Weasel/Annotation/AnnotationReader.php +++ /dev/null @@ -1,251 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation; - -use Psr\Log\LoggerInterface; -use Psr\Log\LoggerAwareInterface; -use Weasel\Common\Annotation\IAnnotationReader; - -/** - * Class AnnotationReader - * @package Weasel\Annotation - * @deprecated Use the DoctrineAnnotation driven reader. - */ -class AnnotationReader implements LoggerAwareInterface, IAnnotationReader -{ - - /** - * @var \ReflectionClass - */ - protected $class; - - /** - * @var null|array[] - */ - protected $classAnnotations = null; - /** - * @var null|array[] - */ - protected $methodAnnotations = null; - /** - * @var null|array[] - */ - protected $propertyAnnotations = null; - - protected $parser = null; - protected $namespaces; - - protected $otherNamespaces = array(); - - /** - * @var \Psr\Log\LoggerInterface - */ - protected $logger; - - /** - * @var PhpParser - */ - protected $nsParser; - - /** - * @param \ReflectionClass $class - * @param AnnotationConfigProvider $annotations - */ - public function __construct(\ReflectionClass $class, AnnotationConfigProvider $annotations) - { - $this->class = $class; - $this->parser = new DocblockParser($annotations); - $this->nsParser = new PhpParser(); - } - - protected function _getNamespaces() - { - if (!isset($this->namespaces)) { - $this->namespaces = $this->nsParser->parseClass($this->class); - } - return $this->namespaces; - } - - /** - * @return array[] - */ - public function getClassAnnotations() - { - if (isset($this->classAnnotations)) { - return $this->classAnnotations; - } - - $docblock = $this->class->getDocComment(); - - if ($docblock === false) { - $this->classAnnotations = array(); - } else { - $this->classAnnotations = $this->parser->parse($docblock, "class", $this->_getNamespaces()); - } - return $this->classAnnotations; - } - - /** - * @param string $annotation - * @return mixed[] - */ - public function getClassAnnotation($annotation) - { - $classes = $this->getClassAnnotations(); - return isset($classes[$annotation]) ? $classes[$annotation] : null; - } - - /** - * @param mixed[] $annotations - * @return mixed - * @throws \Exception - */ - protected function _singleAnnotation($annotations) - { - if (empty($annotations)) { - return null; - } - if (count($annotations) > 1) { - throw new \Exception("Attempt to get single annotation when there are multiple"); - } - return array_shift($annotations); - } - - /** - * @param string $annotation - * @return mixed - */ - public function getSingleClassAnnotation($annotation) - { - return $this->_singleAnnotation($this->getClassAnnotation($annotation)); - } - - /** - * @param \Reflection|\ReflectionMethod|\ReflectionProperty $rThing - * @return array - */ - protected function _getDeclaredNamespaces($rThing) - { - /** - * @var \ReflectionClass $dClass - */ - $dClass = $rThing->getDeclaringClass(); - - if ($dClass != $this->class) { - $fullName = $dClass->getNamespaceName() . '\\' . $dClass->getName(); - if (!isset($this->otherNamespaces[$fullName])) { - $this->otherNamespaces[$fullName] = $this->nsParser->parseClass($dClass); - } - return $this->otherNamespaces[$fullName]; - } - return $this->_getNamespaces(); - } - - /** - * @param string $method - * @return array[] - */ - public function getMethodAnnotations($method) - { - if (isset($this->methodAnnotations[$method])) { - return $this->methodAnnotations[$method]; - } - - $this->methodAnnotations[$method] = array(); - $rMethod = $this->class->getMethod($method); - $docblock = $rMethod->getDocComment(); - if ($docblock !== false) { - $this->methodAnnotations[$method] = $this->parser->parse($docblock, - "method", - $this->_getDeclaredNamespaces($rMethod) - ); - } - return $this->methodAnnotations[$method]; - - } - - /** - * @param string $method - * @param string $annotation - * @return mixed[] - */ - public function getMethodAnnotation($method, $annotation) - { - $methods = $this->getMethodAnnotations($method); - return (isset($methods[$annotation]) ? $methods[$annotation] : null); - - } - - /** - * @param string $method - * @param string $annotation - * @return mixed - */ - public function getSingleMethodAnnotation($method, $annotation) - { - return $this->_singleAnnotation($this->getMethodAnnotation($method, $annotation)); - } - - /** - * @param string $property - * @return array[] - */ - public function getPropertyAnnotations($property) - { - if (isset($this->propertyAnnotations[$property])) { - return $this->propertyAnnotations[$property]; - } - - $this->propertyAnnotations[$property] = array(); - $rProperty = $this->class->getProperty($property); - $docblock = $rProperty->getDocComment(); - if ($docblock !== false) { - $this->propertyAnnotations[$property] = $this->parser->parse($docblock, - "property", - $this->_getDeclaredNamespaces($rProperty) - ); - } - return $this->propertyAnnotations[$property]; - - } - - /** - * @param string $property - * @param string $annotation - * @return mixed[] - */ - public function getPropertyAnnotation($property, $annotation) - { - $properties = $this->getPropertyAnnotations($property); - return isset($properties[$annotation]) ? $properties[$annotation] : null; - } - - /** - * @param string $property - * @param string $annotation - * @return mixed - */ - public function getSinglePropertyAnnotation($property, $annotation) - { - return $this->_singleAnnotation($this->getPropertyAnnotation($property, $annotation)); - } - - /** - * Sets a logger instance on the mixed - * - * @param LoggerInterface $logger - * @return null - */ - public function setLogger(LoggerInterface $logger) - { - $this->logger = $logger; - if (isset($logger)) { - $this->parser->setLogger($logger); - $this->nsParser->setLogger($logger); - } - } -} diff --git a/lib/Weasel/Annotation/AnnotationReaderFactory.php b/lib/Weasel/Annotation/AnnotationReaderFactory.php deleted file mode 100644 index 68839b9..0000000 --- a/lib/Weasel/Annotation/AnnotationReaderFactory.php +++ /dev/null @@ -1,63 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation; - -use Psr\Log\LoggerAwareInterface; -use Psr\Log\LoggerInterface; -use Weasel\Common\Annotation\IAnnotationReaderFactory; - -/** - * Class AnnotationReaderFactory - * @package Weasel\Annotation - * @deprecated Use the DoctrineAnnotation driven reader. - */ -class AnnotationReaderFactory implements IAnnotationReaderFactory, LoggerAwareInterface -{ - - /** - * @var LoggerInterface - */ - protected $logger; - - /** - * @var AnnotationConfigProvider - */ - protected $configProvider; - - /** - * @param AnnotationConfigProvider $configProvider - */ - public function __construct(AnnotationConfigProvider $configProvider) - { - $this->configProvider = $configProvider; - } - - /** - * @param \ReflectionClass $class - * @return \Weasel\Common\Annotation\IAnnotationReader - */ - public function getReaderForClass(\ReflectionClass $class) - { - $reader = new AnnotationReader($class, $this->configProvider); - if (isset($this->logger)) { - $reader->setLogger($this->logger); - } - return $reader; - } - - - /** - * Sets a logger instance on the object - * - * @param LoggerInterface $logger - * @return null - */ - public function setLogger(LoggerInterface $logger) - { - $this->logger = $logger; - } -} diff --git a/lib/Weasel/Annotation/ArrayCachingAnnotationConfigurator.php b/lib/Weasel/Annotation/ArrayCachingAnnotationConfigurator.php deleted file mode 100644 index 0bf9191..0000000 --- a/lib/Weasel/Annotation/ArrayCachingAnnotationConfigurator.php +++ /dev/null @@ -1,29 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation; - -use Psr\Log\LoggerInterface; -use Psr\Log\LoggerAwareInterface; -use Weasel\Common\Cache\ArrayCache; - -/** - * Left over from prior to new cache system. - * Stop using this. Use an AnnotationConfigurator, and call setCache. - * @deprecated Use the AnnotationConfiguration and call setCache()! - */ -class ArrayCachingAnnotationConfigurator extends AnnotationConfigurator implements LoggerAwareInterface -{ - public function __construct(LoggerInterface $logger = null, - AnnotationReaderFactory $readerFactory = null) - { - parent::__construct($logger, $readerFactory); - $this->setCache(new ArrayCache("AnnotationConfigurator")); - } - - -} - diff --git a/lib/Weasel/Annotation/Config/Annotation.php b/lib/Weasel/Annotation/Config/Annotation.php deleted file mode 100644 index 426c154..0000000 --- a/lib/Weasel/Annotation/Config/Annotation.php +++ /dev/null @@ -1,223 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config; - -class Annotation -{ - - /** - * @var string - */ - private $class; - - /** - * @var string[] - */ - private $on; - - private $onFlipped; - - /** - * @var int - */ - private $max; - - /** - * @var string - */ - private $creatorMethod; - - /** - * @var \Weasel\Annotation\Config\Param[] - */ - private $creatorParams; - - /** - * @var \Weasel\Annotation\Config\Property[] - */ - private $properties; - - /** - * @var \Weasel\Annotation\Config\Enum[] - */ - private $enums; - - /** - * @param string $class - * @param string[] $on - * @param int $max - */ - public function __construct($class, $on, $max = null) - { - $this->class = $class; - $this->on = $on; - $this->max = $max; - $this->onFlipped = array_flip($on); - } - - /** - * @return string - */ - public function getClass() - { - return $this->class; - } - - /** - * @return string - */ - public function getCreatorMethod() - { - return $this->creatorMethod; - } - - /** - * @return \Weasel\Annotation\Config\Param[] - */ - public function getCreatorParams() - { - return $this->creatorParams; - } - - /** - * @return int - */ - public function getMax() - { - return $this->max; - } - - /** - * @return \string[] - */ - public function getOn() - { - return $this->on; - } - - public function permittedOn($location) - { - return isset($this->onFlipped[$location]); - } - - /** - * @param string $creatorMethod - * @return \Weasel\Annotation\Config\Annotation - */ - public function setCreatorMethod($creatorMethod) - { - $this->creatorMethod = $creatorMethod; - return $this; - } - - /** - * @param \Weasel\Annotation\Config\Param $param - * @return Annotation - */ - public function addCreatorParam($param) - { - $this->creatorParams[] = $param; - return $this; - } - - /** - * @param \Weasel\Annotation\Config\Param[] $creatorParams - * @return Annotation - */ - public function setCreatorParams($creatorParams) - { - $this->creatorParams = $creatorParams; - return $this; - } - - /** - * @param int $max - * @return \Weasel\Annotation\Config\Annotation - */ - public function setMax($max) - { - $this->max = $max; - return $this; - } - - /** - * @param $on - * @return Annotation - */ - public function setOn($on) - { - $this->on = $on; - return $this; - } - - /** - * @return \Weasel\Annotation\Config\Property[] - */ - public function getProperties() - { - return $this->properties; - } - - /** - * @param \Weasel\Annotation\Config\Property[] $properties - * @return Annotation - */ - public function setProperties($properties) - { - $this->properties = $properties; - return $this; - } - - /** - * @param \Weasel\Annotation\Config\Property $property - * @return Annotation - */ - public function addProperty(Property $property) - { - $this->properties[$property->getName()] = $property; - return $this; - } - - /** - * @return \Weasel\Annotation\Config\Enum[] - */ - public function getEnums() - { - return $this->enums; - } - - /** - * @param \Weasel\Annotation\Config\Enum[] $enums - * @return Annotation - */ - public function setEnums($enums) - { - $this->enums = $enums; - return $this; - } - - /** - * @param \Weasel\Annotation\Config\Enum $enum - * @return Annotation - */ - public function addEnum($enum) - { - $this->enums[$enum->getName()] = $enum; - return $this; - } - - /** - * @param string $name - * @return \Weasel\Annotation\Config\Enum - */ - public function getEnum($name) - { - return isset($this->enums[$name]) ? $this->enums[$name] : null; - } - -} - diff --git a/lib/Weasel/Annotation/Config/AnnotationConfig.php b/lib/Weasel/Annotation/Config/AnnotationConfig.php deleted file mode 100644 index 3969711..0000000 --- a/lib/Weasel/Annotation/Config/AnnotationConfig.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config; - -class AnnotationConfig -{ - - /** - * @var \Weasel\Annotation\Config\Annotation[] - */ - private $annotations = array(); - - /** - * @param \Weasel\Annotation\Config\Annotation $annotation - */ - public function addAnnotation($annotation) - { - $this->annotations[$annotation->getClass()] = $annotation; - } - - /** - * @param \Weasel\Annotation\Config\Annotation[] $annotations - * @return AnnotationConfig - */ - public function setAnnotations($annotations) - { - $this->annotations = $annotations; - return $this; - } - - /** - * @return Annotation[] - */ - public function getAnnotations() - { - return $this->annotations; - } - - public function getAnnotation($class) - { - return isset($this->annotations[$class]) ? $this->annotations[$class] : null; - } - - -} diff --git a/lib/Weasel/Annotation/Config/Annotations/Annotation.php b/lib/Weasel/Annotation/Config/Annotations/Annotation.php deleted file mode 100644 index 4e7cc7c..0000000 --- a/lib/Weasel/Annotation/Config/Annotations/Annotation.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; - -/** - * @Annotation(on="class", max=1) - */ -class Annotation -{ - - protected $on; - protected $max; - - /** - * @param string[]|null $on - * @param int|null $max - * @AnnotationCreator({@Parameter(name="on", type="string[]", required=false), @Parameter(name="max", type="integer", required=false)}) - */ - public function __construct(array $on, $max) - { - $this->on = isset($on) ? $on : null; - $this->max = isset($max) ? $max : null; - } - - public function getMax() - { - return $this->max; - } - - public function getOn() - { - return $this->on; - } - -} diff --git a/lib/Weasel/Annotation/Config/Annotations/AnnotationCreator.php b/lib/Weasel/Annotation/Config/Annotations/AnnotationCreator.php deleted file mode 100644 index cf788b9..0000000 --- a/lib/Weasel/Annotation/Config/Annotations/AnnotationCreator.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\Parameter; - -/** - * @Annotation(on="method", max=1) - */ -class AnnotationCreator -{ - - /** - * @var array|null|\Weasel\Annotation\Config\Annotations\Parameter[] - */ - protected $params; - - /** - * @param \Weasel\Annotation\Config\Annotations\Parameter[]|null $params - * @AnnotationCreator(@Parameter(name="params", type="\Weasel\Annotation\Config\Annotations\Parameter[]", required=false)) - */ - public function __construct(array $params) - { - $this->params = isset($params) ? $params : null; - } - - /** - * @return array|null|\Weasel\Annotation\Config\Annotations\Parameter[] - */ - public function getParams() - { - return $this->params; - } - -} diff --git a/lib/Weasel/Annotation/Config/Annotations/Enum.php b/lib/Weasel/Annotation/Config/Annotations/Enum.php deleted file mode 100644 index f596ffc..0000000 --- a/lib/Weasel/Annotation/Config/Annotations/Enum.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; - -/** - * @Annotation(on="property") - */ -class Enum -{ - - protected $name; - - /** - * @param string $name - * @AnnotationCreator(@Parameter(name="name", type="string", required=false)) - */ - public function __construct($name) - { - $this->name = isset($name) ? $name : null; - } - - public function getName() - { - return $this->name; - } - -} - diff --git a/lib/Weasel/Annotation/Config/Annotations/Parameter.php b/lib/Weasel/Annotation/Config/Annotations/Parameter.php deleted file mode 100644 index ce05012..0000000 --- a/lib/Weasel/Annotation/Config/Annotations/Parameter.php +++ /dev/null @@ -1,50 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; - -/** - * @Annotation(on="\Weasel\Annotation\Config\Annotations\AnnotationCreator") - */ -class Parameter -{ - - protected $name; - protected $type; - protected $required; - - /** - * @param string $name - * @param string $type - * @param bool $required - * @AnnotationCreator({@Parameter(name="name", type="string", required=false), @Parameter(name="type", type="string", required=false), @Parameter(name="required", type="boolean", required=false)}) - */ - public function __construct($name, $type, $required) - { - $this->name = isset($name) ? $name : null; - $this->type = isset($type) ? $type : "string"; - $this->required = isset($required) ? $required : false; - } - - public function getName() - { - return $this->name; - } - - public function getRequired() - { - return $this->required; - } - - public function getType() - { - return $this->type; - } - -} diff --git a/lib/Weasel/Annotation/Config/Annotations/Property.php b/lib/Weasel/Annotation/Config/Annotations/Property.php deleted file mode 100644 index d921bea..0000000 --- a/lib/Weasel/Annotation/Config/Annotations/Property.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; - -/** - * @Annotation(on="property", max=1) - */ -class Property -{ - - /** - * @var string - */ - protected $type; - - /** - * @param string $type - * @AnnotationCreator - * @CreatorParam(name="type", type="string", required=false) - */ - public function __construct($type) - { - $this->type = isset($type) ? $type : "string"; - } - - /** - * @return string - */ - public function getType() - { - return $this->type; - } -} diff --git a/lib/Weasel/Annotation/Config/BuiltInsProvider.php b/lib/Weasel/Annotation/Config/BuiltInsProvider.php deleted file mode 100644 index 0435a57..0000000 --- a/lib/Weasel/Annotation/Config/BuiltInsProvider.php +++ /dev/null @@ -1,62 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config; - -class BuiltInsProvider -{ - - /** - * @var AnnotationConfig - */ - protected static $builtIns; - - protected static function _buildConfig() - { - - self::$builtIns = new AnnotationConfig(); - - $annotation = new Annotation('\Weasel\Annotation\Config\Annotations\Annotation', array('class'), 1); - $annotation->setCreatorMethod('__construct'); - $annotation->addCreatorParam( - new Param('on', 'string[]', false) - ); - $annotation->addCreatorParam( - new Param('max', 'integer', false) - ); - self::$builtIns->addAnnotation($annotation); - - $annotation = new Annotation('\Weasel\Annotation\Config\Annotations\AnnotationCreator', array('method'), 1); - $annotation->setCreatorMethod('__construct'); - $annotation->addCreatorParam( - new Param('params', '\Weasel\Annotation\Config\Annotations\Parameter[]', false) - ); - self::$builtIns->addAnnotation($annotation); - - $annotation = - new Annotation('\Weasel\Annotation\Config\Annotations\Parameter', array('\Weasel\Annotation\Config\Annotations\AnnotationCreator'), null); - $annotation->setCreatorMethod('__construct'); - $annotation->addCreatorParam( - new Param('name', 'string', false) - ); - $annotation->addCreatorParam( - new Param('type', 'string', false) - ); - $annotation->addCreatorParam( - new Param('required', 'bool', false) - ); - self::$builtIns->addAnnotation($annotation); - } - - public static function getConfig() - { - if (!isset(self::$builtIns)) { - self::_buildConfig(); - } - return self::$builtIns; - } - -} diff --git a/lib/Weasel/Annotation/Config/Enum.php b/lib/Weasel/Annotation/Config/Enum.php deleted file mode 100644 index b6237eb..0000000 --- a/lib/Weasel/Annotation/Config/Enum.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config; - -class Enum -{ - - /** - * @var string - */ - private $name; - - /** - * @var array - */ - private $values; - - /** - * @param string $name - * @param array $values - */ - public function __construct($name, $values) - { - $this->name = $name; - $this->values = $values; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * @return array - */ - public function getValues() - { - return $this->values; - } - -} diff --git a/lib/Weasel/Annotation/Config/Param.php b/lib/Weasel/Annotation/Config/Param.php deleted file mode 100644 index c236183..0000000 --- a/lib/Weasel/Annotation/Config/Param.php +++ /dev/null @@ -1,62 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config; - -class Param -{ - - /** - * @var string - */ - private $name; - - /** - * @var string - */ - private $type; - - /** - * @var bool - */ - private $required; - - /** - * @param string $name - * @param string $type - * @param bool $required - */ - public function __construct($name, $type, $required) - { - $this->name = $name; - $this->type = $type; - $this->required = $required; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * @return bool - */ - public function getRequired() - { - return $this->required; - } - - /** - * @return string - */ - public function getType() - { - return $this->type; - } -} diff --git a/lib/Weasel/Annotation/Config/Property.php b/lib/Weasel/Annotation/Config/Property.php deleted file mode 100644 index 3b97537..0000000 --- a/lib/Weasel/Annotation/Config/Property.php +++ /dev/null @@ -1,47 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Config; - -class Property -{ - - /** - * @var string - */ - private $name; - - /** - * @var string - */ - private $type; - - /** - * @param string $name - * @param string $type - */ - public function __construct($name, $type) - { - $this->name = $name; - $this->type = $type; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * @return string - */ - public function getType() - { - return $this->type; - } -} diff --git a/lib/Weasel/Annotation/DocblockLexer.php b/lib/Weasel/Annotation/DocblockLexer.php deleted file mode 100644 index 72de017..0000000 --- a/lib/Weasel/Annotation/DocblockLexer.php +++ /dev/null @@ -1,263 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation; -class DocblockLexer -{ - - const T_MEH = 1; - const T_WHITESPACE = 2; - const T_EOL = 3; - const T_PREAMBLE = 4; - const T_NULL = 10; - const T_QUOTED_STRING = 11; - const T_INTEGER = 12; - const T_FLOAT = 13; - const T_BOOLEAN = 14; - - const T_IDENTIFIER = 50; - - const T_AT = 60; - const T_OPEN_PAREN = 61; - const T_CLOSE_PAREN = 62; - const T_OPEN_BRACE = 63; - const T_CLOSE_BRACE = 64; - const T_COMMA = 65; - const T_EQUAL = 66; - const T_BACKSLASH = 67; - const T_COLON = 68; - const T_DOT = 69; - - public static $TREAT_AS_WS = array(self::T_WHITESPACE => self::T_WHITESPACE, - self::T_EOL => self::T_EOL, - self::T_PREAMBLE => self::T_PREAMBLE, - ); - - protected $tokens = array(); - - protected $pos; - - public function __construct($input) - { - $this->_scan($input); - } - - - /** - * @param string $input - * @throws \Exception - */ - protected function _scan($input) - { - - // In a more traditional world we'd scan the input a single char at a time - // Fortunately preg_split gives us a way to split the input up into a slightly more helpful form. - // Yay. - $split = preg_split( - '(' . implode('|', - array( - // Quoted strings - '("(?:[^"]|"")*")', - // Numeric - '([+-]?[0-9]+(?:\.[0-9]+|[eE][+-]?[0-9]+)?)', - // Identifier - '([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)', - // Line preamble - '(\v+\s+\*[^\S\v])', - // End of line - '(\v+)', - // All other whitespace - '(\s+)', - // Everything else will be split into single chars - '(.)', - ) - ) . ')', - $input, - -1, - (PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_DELIM_CAPTURE) - ); - - foreach ($split as $segment) { - list ($token, $position) = $segment; - $type = $this->_processToken($token); - $tokens['token'] = $token; - $tokens['type'] = $type; - $tokens['pos'] = $position; - $this->tokens[] = $tokens; - } - $this->pos = 0; - } - - protected function _processToken(&$value) - { - - switch (strtolower($value)) { - case '@': - return self::T_AT; - case '(': - return self::T_OPEN_PAREN; - case ')': - return self::T_CLOSE_PAREN; - case '{': - return self::T_OPEN_BRACE; - case '}': - return self::T_CLOSE_BRACE; - case ',': - return self::T_COMMA; - case '=': - return self::T_EQUAL; - case '\\': - return self::T_BACKSLASH; - case ':': - return self::T_COLON; - case '.': - return self::T_DOT; - case 'true': - $value = true; - return self::T_BOOLEAN; - case 'false': - $value = false; - return self::T_BOOLEAN; - case 'null': - return self::T_NULL; - } - - if ($value[0] === '"' && strlen($value) > 1) { - $value = str_replace('""', '"', substr($value, 1, -1)); - return self::T_QUOTED_STRING; - } - - if (is_numeric($value)) { - if (strpos($value, '.') !== false || stripos($value, 'e') !== false) { - return self::T_FLOAT; - } - return self::T_INTEGER; - } - - if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $value)) { - return self::T_IDENTIFIER; - } - - if (preg_match('/^(\v+\s+\*\s+)$/', $value)) { - return self::T_PREAMBLE; - } - - if (preg_match('/^\v+$/', $value)) { - return self::T_EOL; - } - - if (preg_match('/^\s+$/', $value)) { - return self::T_WHITESPACE; - } - - return self::T_MEH; - } - - public function skipToType($target) - { - if (!$cur = $this->get()) { - return null; - } - do { - if ($cur['type'] === $target) { - return $cur; - } - } while ($cur = $this->next()); - return null; - } - - public function get() - { - if (!isset($this->tokens[$this->pos])) { - return null; - } else { - return $this->tokens[$this->pos]; - } - } - - public function skip($types = null) - { - if (!isset($types)) { - $types = self::$TREAT_AS_WS; - } - if (!$cur = $this->get()) { - return null; - } - do { - if (!isset($types[$cur['type']])) { - return $cur; - } - } while ($cur = $this->next()); - return null; - } - - public function next($skipWS = false) - { - $this->pos++; - if ($skipWS) { - return $this->skip(); - } - return $this->get(); - } - - public function seek($to = 0) - { - if ($to < 0) { - $to = count($this->tokens) + $to; - } - if (!isset($this->tokens[$to])) { - return null; - } - $this->pos = $to; - return $this->get(); - } - - public function cur() - { - return $this->pos; - } - - protected function _wsSkippingPeek($num = 1) - { - if ($num === 0) { - $cur = $this->get(); - if (!isset(self::$TREAT_AS_WS[$cur["type"]])) { - return $cur["type"]; - } - } - $pos = $this->pos; - $ret = null; - $i = 0; - do { - $ret = $this->next(true); - $i++; - } while ($i < $num && $ret !== null); - $this->seek($pos); - return isset($ret) ? $ret["type"] : null; - } - - public function peek($num = 1, $skipWS = false) - { - if ($num < 0) { - throw new \InvalidArgumentException("Cannot peek backwards"); - } - if ($skipWS) { - return $this->_wsSkippingPeek($num); - } - if ($num === 0) { - $cur = $this->get(); - return $cur["type"]; - } - $pos = $this->pos; - if ($ret = $this->seek($pos + $num)) { - $this->seek($pos); - return $ret['type']; - } - $this->seek($pos); - return null; - } - -} diff --git a/lib/Weasel/Annotation/DocblockParser.php b/lib/Weasel/Annotation/DocblockParser.php deleted file mode 100644 index fbc4d87..0000000 --- a/lib/Weasel/Annotation/DocblockParser.php +++ /dev/null @@ -1,471 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation; - -use Psr\Log\LoggerInterface; -use Psr\Log\LoggerAwareInterface; - -class DocblockParser implements LoggerAwareInterface -{ - - /** - * @var AnnotationConfigProvider - */ - protected $annotations; - - /** - * @var LoggerInterface - */ - protected $logger; - - static $silentlyDiscard = array( - "param" => true, - "author" => true, - "copyright" => true, - "var" => true, - "return" => true, - "package" => true, - "throws" => true, - ); - - public function parse($docBlock, $location, $namespaces) - { - return $this->_parse($docBlock, $location, $namespaces); - } - - public function __construct(AnnotationConfigProvider $annotations) - { - $this->annotations = $annotations; - } - - protected function _getAnnotation($name, $namespaces) - { - - if ($name[0] !== '\\') { - $exploded = explode('\\', $name); - $alias = ""; - $name = null; - $part = null; - do { - if ($part !== null) { - $alias .= '\\' . $part; - } - $baseNamespace = implode('\\', $exploded); - if (isset($namespaces[$baseNamespace])) { - $name = '\\' . $namespaces[$baseNamespace] . ($alias !== '' ? ($alias) : ''); - break; - } - } while ($part = array_pop($exploded)); - - if ($name === null) { - return null; - } - - } - - return $this->annotations->get($name); - } - - protected function _parse($input, $location, $namespaces) - { - $lexer = new DocblockLexer($input); - return $this->_DocBlock($lexer, $location, $namespaces); - } - - protected function _DocBlock(DocblockLexer $lexer, $location, $namespaces) - { - $annotations = array(); - while ($lexer->skipToType(DocblockLexer::T_PREAMBLE)) { - $next = $lexer->next(); - if ($next["type"] !== DocblockLexer::T_AT) { - // Skip because it doesn't have an annotation at the start - continue; - } - $pos = $lexer->cur(); - try { - $annotation = $this->_Annotation($lexer, $location, $namespaces); - $this->_expectNext($lexer, DocblockLexer::$TREAT_AS_WS); - if (isset($annotation)) { - $annotations[$annotation[0]][] = $annotation[1]; - } else { - // If not then it parsed fine, but it isn't something we know about - } - } catch (\Exception $e) { - // OK, try starting 1 char after the @ to find the next annotation. - if ($this->logger) { - $this->logger->debug("Skipping syntax error: " . $e->getMessage(), array("exception" => $e)); - } - $lexer->seek($pos); - if (!$lexer->next()) { - break; - } - } - } - return $annotations; - } - - protected function _Array(DocblockLexer $lexer, $location, $namespaces) - { - - $elements = array(); - - while (($next = $lexer->peek(1, true)) !== DocblockLexer::T_CLOSE_BRACE) { - $elements[] = $this->_ParamValue($lexer, $location, $namespaces); - - if ($lexer->peek(1, true) === DocblockLexer::T_CLOSE_BRACE) { - break; - } - $this->_expectNext($lexer, DocblockLexer::T_COMMA, true); - } - $this->_expectNext($lexer, DocblockLexer::T_CLOSE_BRACE, true); - return $elements; - } - - protected function _ParamValue(DocblockLexer $lexer, $location, $namespaces) - { - $next = $lexer->peek(1, true); - if ($next === DocblockLexer::T_IDENTIFIER) { - // Might be an enum then... - $enum = $this->_Enum($lexer, $location, $namespaces); - return $enum; - } - - $cur = $lexer->next(true); - switch ($cur['type']) { - case DocblockLexer::T_INTEGER: - $param = array('integer', - $cur['token'] - ); - break; - case DocblockLexer::T_FLOAT: - $param = array('float', - $cur['token'] - ); - break; - case DocblockLexer::T_BOOLEAN: - $param = array('boolean', - $cur['token'] - ); - break; - case DocblockLexer::T_QUOTED_STRING: - $param = array('string', - $cur['token'] - ); - break; - case DocblockLexer::T_AT: - $object = $this->_Annotation($lexer, $location, $namespaces); - return $object; - break; - case DocblockLexer::T_OPEN_BRACE: - $array = $this->_Array($lexer, $location, $namespaces); - return array('array', - $array - ); - default: - throw new \Exception("Parse error got {$cur["type"]} ({$cur['token']})"); - } - return $param; - } - - protected function _NamedParam(DocblockLexer $lexer, $location, $namespaces) - { - $nameToken = $this->_expectNext($lexer, DocblockLexer::T_IDENTIFIER, true); - - $this->_expectNext($lexer, DocblockLexer::T_EQUAL, true); - - $value = $this->_ParamValue($lexer, $location, $namespaces); - - return array($nameToken['token'], - $value - ); - - } - - protected function _expectNext(DocblockLexer $lexer, $types, $skipWS = false) - { - if (!is_array($types)) { - $types = array($types => $types); - } - $next = $lexer->next($skipWS); - if (!$next || !isset($types[$next['type']])) { - throw new \Exception('Parse error, expected one of ' . implode(',', $types) . ' but got ' . ($next ? - $next['type'] : 'EOF')); - } - return $next; - } - - protected function _ClassName(DocblockLexer $lexer) - { - $next = $lexer->next(); - - $class = ''; - if ($next['type'] === DocblockLexer::T_BACKSLASH) { - $class .= '\\'; - $next = $this->_expectNext($lexer, DocblockLexer::T_IDENTIFIER); - } - - $class .= $next['token']; - - while ($lexer->peek() === DocblockLexer::T_BACKSLASH) { - $this->_expectNext($lexer, DocblockLexer::T_BACKSLASH); - $class .= '\\'; - $part = $this->_expectNext($lexer, DocblockLexer::T_IDENTIFIER); - $class .= $part['token']; - } - return $class; - } - - protected function _Enum(DocblockLexer $lexer, $location, $namespaces) - { - $class = $this->_ClassName($lexer); - $meta = $this->_getAnnotation($class, $namespaces); - if (!$meta) { - throw new \Exception("Unable to resolve enum class $class"); - } - - $this->_expectNext($lexer, DocblockLexer::T_DOT); - $enumTok = $this->_expectNext($lexer, DocblockLexer::T_IDENTIFIER); - $enum = $enumTok["token"]; - $this->_expectNext($lexer, DocblockLexer::T_DOT); - $indexTok = $this->_expectNext($lexer, DocblockLexer::T_IDENTIFIER); - $index = $indexTok["token"]; - - if ($meta->getEnum($enum) === null) { - throw new \Exception("Unable to find an enum for $class : $enum : $index"); - } - $enumValues = $meta->getEnum($enum)->getValues(); - if (!isset($enumValues[$index])) { - throw new \Exception("Unable to lookup enum value for $class : $enum : $index"); - } - - return array("integer", - $enumValues[$index] - ); - - } - - protected function _Annotation(DocblockLexer $lexer, $location, $namespaces) - { - - $identifier = $this->_ClassName($lexer); - - $meta = $this->_getAnnotation($identifier, $namespaces); - if (!$meta) { - if ($this->logger) { - if (!isset(self::$silentlyDiscard[$identifier])) { - $this->logger->debug("Skipping unknown annotation: $identifier"); - } - } - return null; - } - - if ($meta->getOn() && !$meta->permittedOn($location)) { - throw new \Exception( - "Found annotation in wrong location, got $location but expected one of " . implode(", ", - $meta->getOn() - )); - } - - if ($lexer->peek() === DocblockLexer::T_OPEN_PAREN) { - // There are params to read - $this->_expectNext($lexer, DocblockLexer::T_OPEN_PAREN); - - $anonParams = array(); - $namedParams = array(); - - $expectingComma = false; - while (($next = $lexer->peek(1, true)) !== DocblockLexer::T_CLOSE_PAREN) { - if ($next === null) { - throw new \Exception('Unmatched parentheses'); - } - if ($next === DocblockLexer::T_IDENTIFIER && $lexer->peek(2, true) === DocblockLexer::T_EQUAL) { - if ($expectingComma) { - throw new \Exception('Unexpected identifier, expecting comma or close paren'); - } - list($name, $param) = $this->_NamedParam($lexer, $meta->getClass(), $namespaces); - $namedParams[$name] = $param; - $expectingComma = true; - } elseif ($next === DocblockLexer::T_COMMA) { - if (!$expectingComma) { - throw new \Exception('Unexpected comma'); - } - $this->_expectNext($lexer, DocblockLexer::T_COMMA, true); - $expectingComma = false; - } else { - if ($expectingComma) { - throw new \Exception('Unexpected value, expecting comma or close paren'); - } - $anonParams[] = $this->_ParamValue($lexer, $meta->getClass(), $namespaces); - $expectingComma = true; - } - } - if (!empty($anonParams) && !empty($namedParams)) { - throw new \Exception('Named or anonymous params, pick one.'); - } - - $this->_expectNext($lexer, DocblockLexer::T_CLOSE_PAREN, true); - - if ((!empty($anonParams) || !empty($namedParams)) && $expectingComma === false) { - // There has been a comma followed by a close paren... - throw new \Exception('Unexpected close paren after comma'); - } - - } - - $class = $meta->getClass(); - - if ($meta->getCreatorMethod()) { - // There's a creator method to call - - /** - * @var \Weasel\Annotation\Config\Param[] $expectedParams - */ - $expectedParams = $meta->getCreatorParams() ? $meta->getCreatorParams() : array(); - $actualParams = array(); - if (!empty($anonParams)) { - if (count($anonParams) > count($expectedParams)) { - throw new \Exception("Too many parameters"); - } - reset($anonParams); - foreach ($expectedParams as $paramConfig) { - $param = each($anonParams); - $param = ($param === false) ? null : $param['value']; - if ($param === null) { - if ($paramConfig->getRequired() && $paramConfig->getRequired() === true) { - throw new \Exception('Missing required parameter ' . $paramConfig->getName()); - } - $actualParams[] = null; - } else { - $actualParams[] = $this->_collapseAndCheckType($param, $paramConfig->getType()); - } - } - } elseif (!empty($namedParams)) { - foreach ($expectedParams as $paramConfig) { - if (!isset($namedParams[$paramConfig->getName()])) { - if ($paramConfig->getRequired() && $paramConfig->getRequired() === true) { - throw new \Exception('Missing required parameter ' . $paramConfig->getName()); - } - $actualParams[] = null; - } else { - $actualParams[] = $this->_collapseAndCheckType($namedParams[$paramConfig->getName()], - $paramConfig->getType() - ); - } - } - } else { - $actualParams = array_fill(0, count($expectedParams), null); - } - - if ($meta->getCreatorMethod() === '__construct') { - $reflectionClass = new \ReflectionClass($class); - $annotation = $reflectionClass->newInstanceArgs($actualParams); - } else { - $method = $meta->getCreatorMethod(); - $reflectionMethod = new \ReflectionMethod($class, $method); - $annotation = $reflectionMethod->invokeArgs(null, $actualParams); - } - } else { - $annotation = new $class(); - } - - if (!empty($namedParams) && $meta->getProperties()) { - foreach ($meta->getProperties() as $name => $property) { - /** - * @var Config\Property $property - */ - if (isset($namedParams[$name])) { - $annotation->$name = $this->_collapseAndCheckType($namedParams[$name], $property->getType()); - } - } - } - - return array($class, - $annotation - ); - } - - protected function _collapseAndCheckType($param, $type) - { - list($paramType, $paramValue) = $param; - switch ($type) { - case "bool": - case "boolean": - if ($paramType === "bool" || $paramType === "boolean") { - return (bool)$paramValue; - } - break; - case "int": - case "integer": - if ($paramType === "integer" || $paramType === "int") { - return (int)$paramValue; - } - break; - case "string": - if ($paramType === $type) { - return (string)$paramValue; - } - break; - case "float": - if ($paramType === $type) { - return (float)$paramValue; - } - break; - default: - - } - if ($paramType === $type) { - if (!is_object($paramValue)) { - throw new \Exception("Expected object"); - } - if (!$paramValue instanceof $type) { - throw new \Exception("Expected object of type $type"); - } - return $paramValue; - } - - // Assume type strings are well formed: look for the last [ to see if it's an array or map. - // Note that this might be an array of arrays, and we're after the outermost type, so we're after the last [! - $pos = strrpos($type, '['); - if ($pos === false) { - // Erm, right, it's not good then. - throw new \Exception("Type mismatch, expected $type but got $paramType"); - } - - // Extract the base type, and whatever's between the [...] as the index type. - // Potentially the type string is actually badly formed: - // e.g. this code will accept string[int! as being an array of string with index int. - // Bah. I'll ignore that case for now. This bit of code gets called a lot, I'd rather not add another substr. - $elementType = substr($type, 0, $pos); - - // Not currently supported - // $indexType = substr($type, $pos+1, -1); - - $result = array(); - if (!is_array($paramValue)) { - $paramValue = array(array($paramType, - $paramValue - ) - ); - } - foreach ($paramValue as $element) { - $result[] = $this->_collapseAndCheckType($element, $elementType); - } - return $result; - - } - - /** - * Sets a logger instance on the object - * - * @param LoggerInterface $logger - * @return null - */ - public function setLogger(LoggerInterface $logger) - { - $this->logger = $logger; - } -} diff --git a/lib/Weasel/Annotation/PhpParser.php b/lib/Weasel/Annotation/PhpParser.php deleted file mode 100644 index 5209328..0000000 --- a/lib/Weasel/Annotation/PhpParser.php +++ /dev/null @@ -1,255 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation; - -use RuntimeException; -use Psr\Log\LoggerInterface; -use Psr\Log\LoggerAwareInterface; - -class PhpParser implements LoggerAwareInterface -{ - - /** - * @var LoggerInterface - */ - protected $logger; - - public function __construct(LoggerInterface $logger = null) - { - if (isset($logger)) { - $this->setLogger($logger); - } - } - - public function parseClass(\ReflectionClass $class) - { - if (isset($this->logger)) { - $this->logger->debug("Parsing file " . $class->getFileName() . " for " . $class->getName()); - } - return $this->_parse($class); - } - - protected function _parse(\ReflectionClass $class) - { - // Read PHP file up to the point the class is defined - $data = $this->_readPrologue($class); - - $tokens = token_get_all('_Namespace($tokens); - $namespaces = array(); - continue; - } - - if ($name === T_USE) { - $namespaces = array_merge($namespaces, $this->_Use($tokens)); - } - - if ($name === T_CLASS) { - $foundClass = $this->_Class($tokens); - if (empty($foundClass)) { - // Class name is not on the same line as the class keyword. We're good to assume that we've read the right thing. - break; - } - if ($foundClass[0] != '\\') { - $foundClass = $curNamespace . '\\' . $foundClass; - } - if ($foundClass === $class->getName()) { - if ($class->getNamespaceName() !== $curNamespace) { - throw new \RuntimeException("Parsing error: Thought $foundClass was in {$class->getNamespaceName()} but it isn't."); - } - break; - } - } - - } - - $classNS = $class->getNamespaceName(); - if (!empty($classNS)) { - $namespaces[""] = $classNS; - } else { - $namespaces[""] = ""; - } - - return $namespaces; - } - - protected function _Use($tokens) - { - - $namespaces = array(); - - $aliasPart = false; - $namespace = ""; - $alias = null; - $lastSegment = null; - - while ($token = array_shift($tokens)) { - if (!is_array($token)) { - $namespace = ltrim($namespace, '\\'); - if ($token === ',') { - if (!isset($alias)) { - $alias = $lastSegment; - } - $namespaces[$alias] = $namespace; - $alias = null; - $lastSegment = null; - $aliasPart = false; - $namespace = ""; - continue; - } elseif ($token === ';') { - if (!isset($alias)) { - $alias = $lastSegment; - } - $namespaces[$alias] = $namespace; - break; - } else { - // Who knows. - break; - } - } - if (!$aliasPart && $token[0] === T_STRING) { - $namespace .= $token[1]; - $lastSegment = $token[1]; - } elseif (!$aliasPart && $token[0] === T_NS_SEPARATOR) { - $namespace .= $token[1]; - } elseif ($token[0] === T_AS) { - $aliasPart = true; - $alias = ""; - } elseif ($token[0] === T_WHITESPACE || $token[0] === T_COMMENT || $token[0] === T_DOC_COMMENT) { - // Meh - } elseif ($aliasPart && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) { - $alias .= $token[1]; - } else { - break; - } - } - return $namespaces; - - } - - - protected function _readPrologue(\ReflectionClass $class) - { - $file = $class->getFileName(); - $line = $class->getStartLine(); - - $buffer = ""; - $handle = @fopen($file, "r"); - if ($handle) { - for ($curLine = 0; $curLine < $line; $curLine++) { - $data = fgets($handle); - if ($data === false) { - break; - } - $buffer .= $data; - } - - fclose($handle); - } - - return $buffer; - - } - - private function _Namespace($tokens) - { - $namespace = ""; - - while ($token = array_shift($tokens)) { - if (!is_array($token)) { - switch ($token) { - case ";": - case "{": - return $namespace; - default: - throw new RuntimeException("Parse error: got $token expected ;"); - } - } else { - switch ($token[0]) { - case T_STRING: - case T_NS_SEPARATOR: - $namespace .= $token[1]; - break; - case T_WHITESPACE: - if (empty($namespace)) { - break; - } else { - return $namespace; - } - case T_COMMENT: - case T_DOC_COMMENT: - break; - default: - throw new RuntimeException("Parse error: got {$token[1]} expected part of namespace"); - } - } - } - return $namespace; - } - - private function _Class($tokens) - { - $class = ""; - - while ($token = array_shift($tokens)) { - if (!is_array($token)) { - switch ($token) { - case "{": - return $class; - default: - throw new RuntimeException("Parse error: got $token expected {"); - } - } else { - switch ($token[0]) { - case T_STRING: - case T_NS_SEPARATOR: - $class .= $token[1]; - break; - case T_WHITESPACE: - if (empty($class)) { - break; - } else { - return $class; - } - case T_COMMENT: - case T_DOC_COMMENT: - break; - default: - throw new RuntimeException("Parse error: got {$token[1]} expected part of class name"); - } - } - } - return $class; - } - - /** - * Sets a logger instance on the object - * - * @param LoggerInterface $logger - * @return null - */ - public function setLogger(LoggerInterface $logger) - { - $this->logger = $logger; - } -} diff --git a/lib/Weasel/BounceContexts/WeaslDefaultAnnotationDrivenContext.xml b/lib/Weasel/BounceContexts/WeaslDefaultAnnotationDrivenContext.xml deleted file mode 100644 index 3a1ce77..0000000 --- a/lib/Weasel/BounceContexts/WeaslDefaultAnnotationDrivenContext.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/Weasel/Command/BuildJsonMapperJsonConfigCommand.php b/lib/Weasel/Command/BuildJsonMapperJsonConfigCommand.php deleted file mode 100644 index 633b3fd..0000000 --- a/lib/Weasel/Command/BuildJsonMapperJsonConfigCommand.php +++ /dev/null @@ -1,104 +0,0 @@ -setName('json') - ->setDescription('Build a config for the JSON mapper') - ->addArgument( - 'in', - InputArgument::REQUIRED, - 'What directory/file should I scan?' - ) - ->addArgument( - 'out', - InputArgument::OPTIONAL, - 'What file should I write to? Default is stdout' - ) - ->addOption("builtinannot", - null, - InputOption::VALUE_OPTIONAL, - "Use the built in annotations rather than Doctrine", - false); - } - - /** - * @var AnnotationDriver - */ - protected $driver; - - /** - * @var JsonMapper - */ - protected $mapper; - - protected function setupDriver($useBuiltin) - { - if ($useBuiltin) { - $factory = new WeaselDefaultAnnotationDrivenFactory(); - $driver = $factory->getJsonDriverInstance(); - } else { - $factory = new WeaselDoctrineAnnotationDrivenFactory(); - $driver = $factory->getJsonDriverInstance(); - } - - $this->mapper = $factory->getJsonMapperInstance(); - $this->driver = $driver; - - } - - protected function generateConfigs($target) - { - $before = get_declared_classes(); - $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS; - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($target, $flags)) as $fileInfo) { - /** - * @var \SplFileInfo $fileInfo - */ - if ($fileInfo->isFile() && preg_match('/\.(php[0-9.]*|inc)$/', $fileInfo->getFilename())) { - include_once($fileInfo->getPathname()); - } - } - $after = get_declared_classes(); - $new = array_diff($after, $before); - - $config = array(); - foreach ($new as $class) { - $config[$class] = $this->driver->getConfig($class); - } - return $config; - - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $in = $input->getArgument('in'); - if (!is_readable($in)) { - throw new \InvalidArgumentException("in must be a readable file or directory"); - } - $this->setupDriver($input->getOption("builtinannot")); - $config = $this->generateConfigs($in); - $json = $this->mapper->writeString($config, '\Weasel\JsonMarshaller\Config\ClassMarshaller[string]'); - if ($out = $input->getArgument("out")) { - file_put_contents($out, $json); - } else { - print $json; - } - } -} \ No newline at end of file diff --git a/lib/Weasel/Command/BuildXmlMapperJsonConfigCommand.php b/lib/Weasel/Command/BuildXmlMapperJsonConfigCommand.php deleted file mode 100644 index f71523c..0000000 --- a/lib/Weasel/Command/BuildXmlMapperJsonConfigCommand.php +++ /dev/null @@ -1,104 +0,0 @@ -setName('xml') - ->setDescription('Build a config for the JSON mapper') - ->addArgument( - 'in', - InputArgument::REQUIRED, - 'What directory/file should I scan?' - ) - ->addArgument( - 'out', - InputArgument::OPTIONAL, - 'What file should I write to? Default is stdout' - ) - ->addOption("builtinannot", - null, - InputOption::VALUE_OPTIONAL, - "Use the built in annotations rather than Doctrine", - false); - } - - /** - * @var AnnotationDriver - */ - protected $driver; - - /** - * @var JsonMapper - */ - protected $mapper; - - protected function setupDriver($useBuiltin) - { - if ($useBuiltin) { - $factory = new WeaselDefaultAnnotationDrivenFactory(); - $driver = $factory->getXmlDriverInstance(); - } else { - $factory = new WeaselDoctrineAnnotationDrivenFactory(); - $driver = $factory->getXmlDriverInstance(); - } - - $this->mapper = $factory->getJsonMapperInstance(); - $this->driver = $driver; - - } - - protected function generateConfigs($target) - { - $before = get_declared_classes(); - $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS; - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($target, $flags)) as $fileInfo) { - /** - * @var \SplFileInfo $fileInfo - */ - if ($fileInfo->isFile() && preg_match('/\.(php[0-9.]*|inc)$/', $fileInfo->getFilename())) { - include_once($fileInfo->getPathname()); - } - } - $after = get_declared_classes(); - $new = array_diff($after, $before); - - $config = array(); - foreach ($new as $class) { - $config[$class] = $this->driver->getConfig($class); - } - return $config; - - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $in = $input->getArgument('in'); - if (!is_readable($in)) { - throw new \InvalidArgumentException("in must be a readable file or directory"); - } - $this->setupDriver($input->getOption("builtinannot")); - $config = $this->generateConfigs($in); - $json = $this->mapper->writeString($config, '\Weasel\XmlMarshaller\Config\ClassMarshaller[string]'); - if ($out = $input->getArgument("out")) { - file_put_contents($out, $json); - } else { - print $json; - } - } -} \ No newline at end of file diff --git a/lib/Weasel/Common/Annotation/IAnnotationReader.php b/lib/Weasel/Common/Annotation/IAnnotationReader.php deleted file mode 100644 index 6265a82..0000000 --- a/lib/Weasel/Common/Annotation/IAnnotationReader.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Common\Annotation; - -/** - * Something that reads annotation objects from a class. - */ -interface IAnnotationReader -{ - - /** - * @return array[] - */ - public function getClassAnnotations(); - - /** - * @param string $annotation - * @return mixed[] - */ - public function getClassAnnotation($annotation); - - /** - * @param string $annotation - * @return object - */ - public function getSingleClassAnnotation($annotation); - - /** - * @param string $method - * @return array[] - */ - public function getMethodAnnotations($method); - - /** - * @param string $method - * @param string $annotation - * @return mixed[] - */ - public function getMethodAnnotation($method, $annotation); - - /** - * @param string $method - * @param string $annotation - * @return mixed - */ - public function getSingleMethodAnnotation($method, $annotation); - - /** - * @param string $property - * @return array[] - */ - public function getPropertyAnnotations($property); - - /** - * @param string $property - * @param string $annotation - * @return mixed[] - */ - public function getPropertyAnnotation($property, $annotation); - - /** - * @param string $property - * @param string $annotation - * @return mixed - */ - public function getSinglePropertyAnnotation($property, $annotation); - -} diff --git a/lib/Weasel/Common/Annotation/IAnnotationReaderFactory.php b/lib/Weasel/Common/Annotation/IAnnotationReaderFactory.php deleted file mode 100644 index eab80bc..0000000 --- a/lib/Weasel/Common/Annotation/IAnnotationReaderFactory.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Common\Annotation; - -/** - * A factory for annotation readers. - */ -interface IAnnotationReaderFactory -{ - - /** - * Obtain an annotation reader for the provided reflection class. - * This is perfectly entitled to return the same instance of IAnnotationReader no matter what class you call it - * with. - * @param \ReflectionClass $class - * @return \Weasel\Common\Annotation\IAnnotationReader - */ - public function getReaderForClass(\ReflectionClass $class); - -} diff --git a/lib/Weasel/Common/Cache/ApcCache.php b/lib/Weasel/Common/Cache/ApcCache.php deleted file mode 100644 index b32b0be..0000000 --- a/lib/Weasel/Common/Cache/ApcCache.php +++ /dev/null @@ -1,53 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Common\Cache; - -class ApcCache extends Cache -{ - - /** - * @param string $key Key to load from cache. - * @param null $namespace - * @param bool $found - * @return mixed - */ - public function get($key, $namespace = null, &$found = true) - { - $key = $this->_getRealKeyName($key, $namespace); - $success = false; - $res = apc_fetch($key, $success); - if (!$success) { - $found = false; - return null; - } - $found = true; - return $res; - } - - /** - * @param string $key Key to store data under - * @param mixed $value Data to store. If it's serializable it can be stored. - * @param null $namespace - * @throws Exception\BackingFailure - * @return void - */ - public function set($key, $value, $namespace = null) - { - $key = $this->_getRealKeyName($key, $namespace); - if (!apc_store($key, $value)) { - throw new Exception\BackingFailure($key, "apc_store returned false"); - } - } - - public function delete($key, $namespace = null) - { - $key = $this->_getRealKeyName($key, $namespace); - if (!apc_delete($key)) { - throw new Exception\BackingFailure($key, "apc_store returned false"); - } - } -} diff --git a/lib/Weasel/Common/Cache/ArrayCache.php b/lib/Weasel/Common/Cache/ArrayCache.php deleted file mode 100644 index fe1dcd6..0000000 --- a/lib/Weasel/Common/Cache/ArrayCache.php +++ /dev/null @@ -1,50 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Common\Cache; - -class ArrayCache extends Cache -{ - - private $cache = array(); - - /** - * @param string $key Key to load from cache. - * @param null|string $namespace - * @param bool $found - * @return mixed - */ - public function get($key, $namespace = null, &$found = true) - { - $key = $this->_getRealKeyName($key, $namespace); - if (array_key_exists($key, $this->cache)) { - $found = true; - return $this->cache[$key]; - } - $found = false; - return null; - } - - /** - * @param string $key Key to store data under - * @param mixed $value Data to store. If it's serializable it can be stored. - * @param null $namespace - * @return void - */ - public function set($key, $value, $namespace = null) - { - $key = $this->_getRealKeyName($key, $namespace); - $this->cache[$key] = $value; - } - - public function delete($key, $namespace = null) - { - $key = $this->_getRealKeyName($key, $namespace); - if (array_key_exists($key, $this->cache)) { - unset($this->cache[$key]); - } - } -} diff --git a/lib/Weasel/Common/Cache/Cache.php b/lib/Weasel/Common/Cache/Cache.php deleted file mode 100644 index 9cf2cd3..0000000 --- a/lib/Weasel/Common/Cache/Cache.php +++ /dev/null @@ -1,80 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Common\Cache; - -/** - * A really boring interface for accessing caches. - */ -abstract class Cache -{ - - private $prefix; - - /** - * @abstract - * @param string $key Key to load from cache. - * @param string $namespace - * @param bool $found True if the key was found in the cache, false if it wasn't. Useful if the cache can store nulls. - * @return mixed - */ - public abstract function get($key, $namespace = null, &$found = true); - - /** - * @abstract - * @param string $key Key to store data under - * @param mixed $value Data to store. If it's serializable it can be stored. - * @param string $namespace - * @return - */ - public abstract function set($key, $value, $namespace = null); - - /** - * Delete something from the cache. - * To preserve keep old implementations working this base class implements the method to lob an error. - * This MUST be implemented for the DoctrineAnnotation cache adapter to work. - * @param string $key Key to delete - * @param string $namespace - * @throws \RuntimeException - */ - public function delete($key, $namespace = null) - { - throw new \RuntimeException("Unsupported for this cache implementation"); - } - - /** - * @param string $prefix - */ - public function setPrefix($prefix) - { - $this->prefix = $prefix; - } - - /** - * @return string - */ - public function getPrefix() - { - return $this->prefix; - } - - public function __construct($prefix = null) - { - $this->setPrefix($prefix); - } - - protected function _getRealKeyName($key, $namespace = null) - { - if (isset($namespace)) { - $key = $namespace . ':~:' . $key; - } - if (isset($this->prefix)) { - $key = $this->prefix . '::' . $key; - } - return $key; - } - -} diff --git a/lib/Weasel/Common/Cache/CacheAwareInterface.php b/lib/Weasel/Common/Cache/CacheAwareInterface.php deleted file mode 100644 index 9c8903e..0000000 --- a/lib/Weasel/Common/Cache/CacheAwareInterface.php +++ /dev/null @@ -1,12 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Common\Cache; - -use Exception; - -class CacheException extends Exception -{ - - protected $key; - - public function __construct($key, $message = "", $code = 0, Exception $previous = null) - { - $this->key = $key; - parent::__construct($message, $code, $previous); - } - -} diff --git a/lib/Weasel/Common/Cache/Exception/BackingFailure.php b/lib/Weasel/Common/Cache/Exception/BackingFailure.php deleted file mode 100644 index 6bedbbb..0000000 --- a/lib/Weasel/Common/Cache/Exception/BackingFailure.php +++ /dev/null @@ -1,14 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Common\Cache\Exception; - -use Weasel\Common\Cache\CacheException; - -class BackingFailure extends CacheException -{ - -} diff --git a/lib/Weasel/Common/Logger/FileLogger.php b/lib/Weasel/Common/Logger/FileLogger.php deleted file mode 100644 index 9446b5a..0000000 --- a/lib/Weasel/Common/Logger/FileLogger.php +++ /dev/null @@ -1,55 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Common\Logger; - -use Psr\Log\AbstractLogger; -use Psr\Log\LogLevel; - -/** - * This exists as a lame shim so that anyone relying on it can move to a real logging framework. - * @deprecated Use a real logger, like monolog! - */ -class FileLogger extends AbstractLogger implements Logger -{ - - protected $_logLevel = 0; - protected $_logFile; - - public function __construct($logFile = null) - { - if (!isset($logFile)) { - $this->_logFile = 'php://stderr'; - } else { - $this->_logFile = $logFile; - } - } - - public function setLogLevel($level) - { - $this->_logLevel = $level; - } - - public function logDebug($entry) - { - $this->debug($entry); - } - - /** - * Logs with an arbitrary level. - * - * @param mixed $level - * @param string $message - * @param array $context - * @return null - */ - public function log($level, $message, array $context = array()) - { - if ($this->_logLevel >= self::LOG_LEVEL_DEBUG) { - error_log($message . "\n", 3, $this->_logFile); - } - } -} diff --git a/lib/Weasel/Common/Logger/Logger.php b/lib/Weasel/Common/Logger/Logger.php deleted file mode 100644 index 485ce4c..0000000 --- a/lib/Weasel/Common/Logger/Logger.php +++ /dev/null @@ -1,22 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Common\Logger; - -/** - * @deprecated Use the PSR3 logger interface. - */ -interface Logger -{ - - const LOG_LEVEL_OFF = 0; - const LOG_LEVEL_DEBUG = 255; - - public function setLogLevel($level); - - public function logDebug($entry); - -} diff --git a/lib/Weasel/Common/Utils/NoUndeclaredProperties.php b/lib/Weasel/Common/Utils/NoUndeclaredProperties.php deleted file mode 100644 index baaac32..0000000 --- a/lib/Weasel/Common/Utils/NoUndeclaredProperties.php +++ /dev/null @@ -1,33 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Common\Utils; - -/** - * Utility class to do stuff involving reflection. - */ -class ReflectionUtils -{ - - /** - * Call a static method with some args. - * We avoid reflection for up to 4 args. - * Allegedly this is faster than using ReflectionMethod (really?) - * @param string $class - * @param string $method - * @param array $args - * @return mixed - */ - public static function invokeStaticMethod($class, $method, $args) - { - switch (count($args)) { - case 0: - return $class::$method(); - case 1: - return $class::$method($args[0]); - case 2: - return $class::$method($args[0], $args[1]); - case 3: - return $class::$method($args[0], $args[1], $args[2]); - case 4: - return $class::$method($args[0], $args[1], $args[2], $args[3]); - default: - $rMethod = new \ReflectionMethod($class, $method); - return $rMethod->invokeArgs(null, $args); - } - } - - /** - * Instantiate a class with some constructor args. - * We avoid reflection for up to 4 args. - * Allegedly this is faster than using ReflectionClass (really?) - * @param string $class - * @param array $args - * @return mixed - */ - public static function instantiateClassByConstructor($class, $args) - { - switch (count($args)) { - case 0: - return new $class(); - case 1: - return new $class($args[0]); - case 2: - return new $class($args[0], $args[1]); - case 3: - return new $class($args[0], $args[1], $args[2]); - case 4: - return new $class($args[0], $args[1], $args[2], $args[3]); - default: - $rClass = new \ReflectionClass($class); - return $rClass->newInstanceArgs($args); - } - } - -} diff --git a/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderAdapter.php b/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderAdapter.php deleted file mode 100644 index 5a4c84b..0000000 --- a/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderAdapter.php +++ /dev/null @@ -1,157 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\DoctrineAnnotation; - -use Doctrine\Common\Annotations\Reader; -use Weasel\Common\Annotation\IAnnotationReader; - -/** - * An adapter to allow a Doctrine AnnotationReader to be used in place of a Weasel one. - */ -class DoctrineAnnotationReaderAdapter implements IAnnotationReader -{ - - /** - * @var \Doctrine\Common\Annotations\Reader - */ - private $annotationReader; - - /** - * @var \ReflectionClass - */ - private $rClass; - - public function __construct(Reader $annotationReader, \ReflectionClass $rClass) - { - $this->annotationReader = $annotationReader; - $this->rClass = $rClass; - } - - /** - * @return array[] - */ - public function getClassAnnotations() - { - return $this->annotationReader->getClassAnnotations($this->rClass); - } - - /** - * @param string $annotation - * @return null|object[] - */ - public function getClassAnnotation($annotation) - { - $annotation = ltrim($annotation, '\\'); - $res = $this->annotationReader->getClassAnnotation($this->rClass, $annotation); - if (!is_array($res)) { - $res = array($res); - } - return $res; - } - - /** - * @param string $annotation - * @return object - */ - public function getSingleClassAnnotation($annotation) - { - $annotation = ltrim($annotation, '\\'); - $res = $this->annotationReader->getClassAnnotation($this->rClass, $annotation); - if (empty($res)) { - return null; - } - if (is_array($res)) { - return array_shift($res); - } - return $res; - } - - /** - * @param string $method - * @return array[] - */ - public function getMethodAnnotations($method) - { - return $this->annotationReader->getMethodAnnotations($this->rClass->getMethod($method)); - } - - /** - * @param string $method - * @param string $annotation - * @return null|object[] - */ - public function getMethodAnnotation($method, $annotation) - { - $annotation = ltrim($annotation, '\\'); - $res = $this->annotationReader->getMethodAnnotation($this->rClass->getMethod($method), $annotation); - if (!is_array($res)) { - $res = array($res); - } - return $res; - } - - /** - * @param string $method - * @param string $annotation - * @return null|object - */ - public function getSingleMethodAnnotation($method, $annotation) - { - $annotation = ltrim($annotation, '\\'); - $res = $this->annotationReader->getMethodAnnotation($this->rClass->getMethod($method), $annotation); - if (empty($res)) { - return null; - } - if (is_array($res)) { - return array_shift($res); - } - return $res; - } - - /** - * @param string $property - * @return array[] - */ - public function getPropertyAnnotations($property) - { - return $this->annotationReader->getPropertyAnnotations($this->rClass->getProperty($property)); - } - - /** - * @param string $property - * @param string $annotation - * @return null|object[] - */ - public function getPropertyAnnotation($property, $annotation) - { - $annotation = ltrim($annotation, '\\'); - $res = $this->annotationReader->getPropertyAnnotation($this->rClass->getProperty($property), $annotation); - if (!is_array($res)) { - $res = array($res); - } - return $res; - } - - /** - * @param string $property - * @param string $annotation - * @return null|object - */ - public function getSinglePropertyAnnotation($property, $annotation) - { - $annotation = ltrim($annotation, '\\'); - $res = $this->annotationReader->getPropertyAnnotation($this->rClass->getProperty($property), $annotation); - if (empty($res)) { - return null; - } - if (is_array($res)) { - return array_shift($res); - } - return $res; - } -} - diff --git a/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactory.php b/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactory.php deleted file mode 100644 index 85842cb..0000000 --- a/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactory.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\DoctrineAnnotation; - -use Doctrine\Common\Annotations\Reader; -use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Annotations\AnnotationRegistry; -use Weasel\Common\Annotation\IAnnotationReaderFactory; -use Doctrine\Common\Annotations\CachedReader; - -/** - * An AnnotationReaderFactory that provides Doctrine powered readers. - */ -class DoctrineAnnotationReaderFactory implements IAnnotationReaderFactory -{ - - /** - * @var \Doctrine\Common\Annotations\Reader - */ - protected $annotationReader; - - /** - * @param \Doctrine\Common\Annotations\Reader $annotationReader - */ - public function __construct(Reader $annotationReader) - { - $this->annotationReader = $annotationReader; - AnnotationRegistry::registerAutoloadNamespace('Weasel', array(__DIR__ . '/../../')); - AnnotationRegistry::registerAutoloadNamespace('\Weasel', array(__DIR__ . '/../../')); - } - - /** - * @param \ReflectionClass $class - * @return \Weasel\Common\Annotation\IAnnotationReader - */ - public function getReaderForClass(\ReflectionClass $class) - { - return new DoctrineAnnotationReaderAdapter($this->annotationReader, $class); - } - -} diff --git a/lib/Weasel/DoctrineAnnotation/WeaselCacheAdapter.php b/lib/Weasel/DoctrineAnnotation/WeaselCacheAdapter.php deleted file mode 100644 index 63799ff..0000000 --- a/lib/Weasel/DoctrineAnnotation/WeaselCacheAdapter.php +++ /dev/null @@ -1,114 +0,0 @@ -delegate = $cache; - } - - /** - * Fetches an entry from the cache. - * - * @param string $id The id of the cache entry to fetch. - * - * @return string|bool The cached data or FALSE, if no cache entry exists for the given id. - */ - protected function doFetch($id) - { - $found = false; - $val = $this->delegate->get($id, null, $found); - if ($found) { - return $val; - } else { - return false; - } - } - - /** - * Tests if an entry exists in the cache. - * - * @param string $id The cache id of the entry to check for. - * - * @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise. - */ - protected function doContains($id) - { - $found = false; - $this->delegate->get($id, null, $found); - return $found; - } - - /** - * Puts data into the cache. - * - * @param string $id The cache id. - * @param string $data The cache entry/data. - * @param int $lifeTime The lifetime. If != 0, sets a specific lifetime for this - * cache entry (0 => infinite lifeTime). - * - * @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise. - */ - protected function doSave($id, $data, $lifeTime = 0) - { - $this->delegate->set($id, $data); - return true; - } - - /** - * Deletes a cache entry. - * - * @param string $id The cache id. - * - * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. - */ - protected function doDelete($id) - { - $this->delegate->delete($id); - return true; - } - - /** - * Flushes all cache entries. - * - * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. - */ - protected function doFlush() - { - return false; - } - - /** - * Retrieves cached information from the data store. - * - * @since 2.2 - * - * @return array|null An associative array with server's statistics if available, NULL otherwise. - */ - protected function doGetStats() - { - return null; - } - - /** - * @param Cache $cache - */ - public function setCache(Cache $cache) - { - $this->delegate = $cache; - } -} diff --git a/lib/Weasel/JsonMarshaller/Config/AnnotationDriver.php b/lib/Weasel/JsonMarshaller/Config/AnnotationDriver.php deleted file mode 100644 index fe6b9b5..0000000 --- a/lib/Weasel/JsonMarshaller/Config/AnnotationDriver.php +++ /dev/null @@ -1,96 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config; - -use Weasel\JsonMarshaller\Config\Annotations; -use Weasel\Annotation\AnnotationConfigurator; -use Weasel\Common\Cache\CacheAwareInterface; -use Weasel\Common\Cache\Cache; -use Weasel\Common\Annotation\IAnnotationReaderFactory; - -/** - * A config provider that uses Annotations - */ -class AnnotationDriver implements JsonConfigProvider, CacheAwareInterface -{ - - protected $classPaths = array(); - - protected $annotationNamespace = '\Weasel\JsonMarshaller\Config\Annotations'; - - /** - * @var \Weasel\Common\Cache\Cache - */ - protected $cache = null; - - /** - * @var \Weasel\Common\Annotation\IAnnotationReaderFactory - */ - public $annotationReaderFactory; - - public function __construct(IAnnotationReaderFactory $annotationReaderFactory) - { - $this->annotationReaderFactory = $annotationReaderFactory; - } - - /** - * Obtain the config for a named class - * @param string $class The class to get the config for - * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found - */ - public function getConfig($class) - { - $key = strtolower($class); - if (isset($this->cache)) { - $found = false; - $cached = $this->cache->get($key, "JsonConfig", $found); - if ($found) { - return $cached; - } - } - $config = $this->_getConfig($class); - - if (isset($this->cache)) { - $this->cache->set($key, $config, "JsonConfig"); - } - return $config; - } - - /** - * _Really_ obtain the config for a named class - * @param string $class The class to get the config for - * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found - */ - protected function _getConfig($class) - { - $rClass = new \ReflectionClass($class); - - // Delegate actually loading the config for the class to the ClassAnnotationDriver - $classDriver = new ClassAnnotationDriver($rClass, $this->annotationReaderFactory, $this->annotationNamespace); - - return $classDriver->getConfig(); - - } - - public function setCache(Cache $cache) - { - $this->cache = $cache; - } - - public function setAnnotationReaderFactory(IAnnotationReaderFactory $annotationReaderFactory) - { - $this->annotationReaderFactory = $annotationReaderFactory; - } - - /** - * @param string $annotationNamespace - */ - public function setAnnotationNamespace($annotationNamespace) - { - $this->annotationNamespace = $annotationNamespace; - } -} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnyGetter.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnyGetter.php deleted file mode 100644 index 1e42968..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnyGetter.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnyGetter; - -/** - * @Annotation(on="method", max=1) - */ -class JsonAnyGetter extends NoUndeclaredProperties implements IJsonAnyGetter -{ - - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnySetter.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnySetter.php deleted file mode 100644 index 65ac105..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnySetter.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnySetter; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation(on="method", max=1) - */ -class JsonAnySetter extends NoUndeclaredProperties implements IJsonAnySetter -{ - - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonCreator.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonCreator.php deleted file mode 100644 index 5eaaafe..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonCreator.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonCreator; - -/** - * @Annotation(on="method", max=1) - */ -class JsonCreator extends NoUndeclaredProperties implements IJsonCreator -{ - - /** - * @var \Weasel\JsonMarshaller\Config\Annotations\JsonProperty[] - */ - protected $params = array(); - - /** - * @param \Weasel\JsonMarshaller\Config\Annotations\JsonProperty[] params - * @AnnotationCreator(@Parameter(name="params", type="\Weasel\JsonMarshaller\Config\Annotations\JsonProperty[]", required=false)) - */ - public function __construct(array $params) - { - $this->params = isset($params) ? $params : array(); - } - - /** - * @return array|JsonProperty[] - */ - public function getParams() - { - return $this->params; - } - - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonIgnoreProperties.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonIgnoreProperties.php deleted file mode 100644 index dd31b01..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonIgnoreProperties.php +++ /dev/null @@ -1,53 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonIgnoreProperties; - -/** - * Provides a list of properties not to consider when serializing/deserializing. - * If ignoreUnknown is true then errors will not be thrown when we encounter properties to deserialize that we do not have a property for, - * they will just be discarded. - * - * @Annotation(on="class") - */ -class JsonIgnoreProperties extends NoUndeclaredProperties implements IJsonIgnoreProperties -{ - - /** - * @param $names - * @param $ignoreUnknown - * @AnnotationCreator({ - * @Parameter(name="names", type="string[]", required=false), - * @Parameter(name="ignoreUnknown", type="boolean", required=false) - * }) - */ - public function __construct($names, $ignoreUnknown) - { - $this->names = isset($names) ? $names : array(); - $this->ignoreUnknown = isset($ignoreUnknown) ? $ignoreUnknown : false; - } - - public function getIgnoreUnknown() - { - return $this->ignoreUnknown; - } - - public function getNames() - { - return $this->names; - } - - protected $names; - - protected $ignoreUnknown; - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonInclude.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonInclude.php deleted file mode 100644 index cc4afb0..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonInclude.php +++ /dev/null @@ -1,55 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\Annotation\Config\Annotations\Enum; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonInclude; - -/** - * @Annotation(on={"class", "method", "property"}, max=1) - */ -class JsonInclude extends NoUndeclaredProperties implements IJsonInclude -{ - - /** - * @var int[string] - * @Enum("Include") - */ - public static $enumInclude = array( - "ALWAYS" => self::INCLUDE_ALWAYS, - "NON_DEFAULT" => self::INCLUDE_NON_DEFAULT, - "NON_EMPTY" => self::INCLUDE_NON_EMPTY, - "NON_NULL" => self::INCLUDE_NON_NULL - ); - - /** - * @var integer - */ - protected $value; - - /** - * @AnnotationCreator(@Parameter(name="value", type="integer", required=true)) - * @param $value - */ - public function __construct($value) - { - $this->value = $value; - } - - /** - * @return int - */ - public function getValue() - { - return $this->value; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonProperty.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonProperty.php deleted file mode 100644 index a03c1e8..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonProperty.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonProperty; - -/** - * Sets a property up to be serialized/deserialized explicitly. - * The name sets the json field name to use for this property. - * The type specifies the type to use. - * Because PHP is not strongly typed we can only make best guesses about types if you do not provide type info! - * @Annotation(on={"property", "method", "\Weasel\JsonMarshaller\Config\Annotations\JsonCreator"}) - */ -class JsonProperty extends NoUndeclaredProperties implements IJsonProperty -{ - - protected $name; - protected $type; - protected $strict; - - /** - * @param string $name - * @param string $type - * @param bool $strict - * @AnnotationCreator({@Parameter(name="name", type="string", required=false), @Parameter(name="type", type="string", required=false), @Parameter(name="strict", type="bool", required=false)}) - */ - public function __construct($name, $type, $strict) - { - $this->name = isset($name) ? $name : null; - $this->type = isset($type) ? $type : "string"; - $this->strict = isset($strict) ? $strict : true; - } - - public function getName() - { - return $this->name; - } - - public function getType() - { - return $this->type; - } - - public function getStrict() - { - return $this->strict; - } - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes.php deleted file mode 100644 index 2534288..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonSubTypes; - -/** - * The list of subtypes of this base class - * @Annotation(on={"class", "method", "property"}) - */ -class JsonSubTypes extends NoUndeclaredProperties implements IJsonSubTypes -{ - - /** - * @var JsonSubTypes\Type[] - */ - protected $value; - - /** - * @param \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type[] $value - * @AnnotationCreator(@Parameter(name="value", type="\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type[]", required=true)) - */ - public function __construct($value) - { - $this->value = $value; - } - - /** - * @return JsonSubTypes\Type[] - */ - public function getValue() - { - return $this->value; - } - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/Type.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/Type.php deleted file mode 100644 index 2fc0850..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/Type.php +++ /dev/null @@ -1,57 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\JsonSubTypes\IType; - -/** - * A subtype - * @Annotation(on={"\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes"}) - */ -class Type extends NoUndeclaredProperties implements IType -{ - - /** - * @var string - */ - protected $value; - - /** - * @var string|null - */ - protected $name; - - /** - * @param string $value - * @param string|null $name - * @AnnotationCreator({@Parameter(name="value", type="string", required=true), @Parameter(name="name", type="string", required=false)}) - */ - public function __construct($value, $name) - { - $this->value = $value; - $this->name = $name; - } - - public function getValue() - { - return $this->value; - } - - /** - * @return null|string - */ - public function getName() - { - return $this->name; - } - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfo.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfo.php deleted file mode 100644 index 2193c4a..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfo.php +++ /dev/null @@ -1,123 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\Annotation\Config\Annotations\Enum; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonTypeInfo; - -/** - * @Annotation(on={"class", "method", "property"}) - */ -class JsonTypeInfo extends NoUndeclaredProperties implements IJsonTypeInfo -{ - - /** - * @var int[string] - * @Enum("Id") - */ - public static $enumId = array( - "CLASS" => self::ID_CLASS, - "CUSTOM" => self::ID_CUSTOM, - "MINIMAL_CLASS" => self::ID_MINIMAL_CLASS, - "NAME" => self::ID_NAME, - "NONE" => self::ID_NONE, - ); - - /** - * @var int[string] - * @Enum("As") - */ - public static $enumAs = array( - "PROPERTY" => self::AS_PROPERTY, - "WRAPPER_ARRAY" => self::AS_WRAPPER_ARRAY, - "WRAPPER_OBJECT" => self::AS_WRAPPER_OBJECT, - "EXTERNAL_PROPERTY" => self::AS_EXTERNAL_PROPERTY, - ); - - /** - * @var string - */ - protected $use; - - /** - * @var string - */ - protected $include; - - /** - * @var string - */ - protected $property; - - /** - * @var bool - */ - protected $visible; - - /** - * @var string - */ - protected $defaultImpl; - - /** - * @AnnotationCreator({@Parameter(name="use", type="integer", required=true), @Parameter(name="include", type="integer", required=false), @Parameter(name="property", type="string", required=false), @Parameter(name="visible", type="bool", required=false), @Parameter(name="defaultImpl", type="string", required=false)}) - * @param int $use - * @param int $include - * @param string $property - * @param bool $visible - * @param string $defaultImpl - */ - public function __construct($use, $include = null, $property = null, $visible = false, $defaultImpl = null) - { - $this->use = $use; - $this->include = isset($include) ? $include : self::$enumAs["PROPERTY"]; - $this->property = empty($property) ? null : $property; - $this->visible = isset($visible) && $visible; - $this->defaultImpl = $defaultImpl; - } - - /** - * @return string - */ - public function getInclude() - { - return $this->include; - } - - /** - * @return string - */ - public function getProperty() - { - return $this->property; - } - - /** - * @return string - */ - public function getUse() - { - return $this->use; - } - - public function getVisible() - { - return $this->visible; - } - - /** - * @return string - */ - public function getDefaultImpl() - { - return $this->defaultImpl; - } -} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeName.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeName.php deleted file mode 100644 index de8c6b9..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeName.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonTypeName; - -/** - * Allows you to specify an explicit name for this implementation, for use by JsonTypeInfo - * @Annotation(on={"class"}) - */ -class JsonTypeName extends NoUndeclaredProperties implements IJsonTypeName -{ - - protected $name; - - /** - * @param string $name - * @AnnotationCreator(@Parameter(name="name", type="string", required=true)) - */ - public function __construct($name) - { - $this->name = $name; - } - - public function getName() - { - return $this->name; - } - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/ArrayCachingAnnotationDriver.php b/lib/Weasel/JsonMarshaller/Config/ArrayCachingAnnotationDriver.php deleted file mode 100644 index a912eb6..0000000 --- a/lib/Weasel/JsonMarshaller/Config/ArrayCachingAnnotationDriver.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config; - -use Weasel\JsonMarshaller\Config\Annotations as Annotations; -use Psr\Log\LoggerInterface; -use Weasel\Common\Cache\ArrayCache; -use Weasel\Common\Annotation\IAnnotationReaderFactory; - -/** - * A config provider that uses Annotations - * @deprecated Use the real driver, and pass in a cache implementation. - */ -class ArrayCachingAnnotationDriver extends AnnotationDriver -{ - - public function __construct(LoggerInterface $logger = null, IAnnotationReaderFactory $annotationReaderFactory = null) - { - parent::__construct($logger, $annotationReaderFactory); - $this->setCache(new ArrayCache()); - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/ClassAnnotationDriver.php b/lib/Weasel/JsonMarshaller/Config/ClassAnnotationDriver.php deleted file mode 100644 index ddc5b3f..0000000 --- a/lib/Weasel/JsonMarshaller/Config/ClassAnnotationDriver.php +++ /dev/null @@ -1,620 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config; - -use Weasel\JsonMarshaller\Config\Annotations as Annotations; -use Weasel\Annotation\AnnotationReader; -use Psr\Log\LoggerAwareInterface; -use Psr\Log\LoggerInterface; -use Weasel\Common\Annotation\IAnnotationReaderFactory; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonCreator; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonProperty; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnyGetter; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnySetter; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonTypeInfo; - -/** - * Load the configuration for a given class from annotations - */ -class ClassAnnotationDriver implements LoggerAwareInterface -{ - - /** - * @var \Weasel\Annotation\AnnotationReaderFactory - */ - protected $annotationReaderFactory; - - /** - * @var \Weasel\Common\Annotation\IAnnotationReader - */ - protected $annotationReader; - - /** - * @var \ReflectionClass - */ - protected $rClass; - - /** - * @var ClassMarshaller - */ - protected $config; - - /** - * @var string The namespace the annotations live in. Current default is the Weasel annotations. - */ - protected $annNS = '\Weasel\JsonMarshaller\Config\Annotations'; - - /** - * @param \ReflectionClass $rClass A reflection for the class we're configuring - * @param \Weasel\Common\Annotation\IAnnotationReaderFactory $annotationReaderFactory A factory for annotation readers - * @param string $annotationNamespace namespace in which we can find the annotations. - */ - public function __construct(\ReflectionClass $rClass, IAnnotationReaderFactory $annotationReaderFactory, $annotationNamespace = '\Weasel\JsonMarshaller\Config\Annotations') - { - $this->annotationReaderFactory = $annotationReaderFactory; - $this->rClass = $rClass; - $this->annNS = $annotationNamespace . '\\'; - } - - /** - * @return AnnotationReader - */ - protected function _getAnnotationReader() - { - if (!isset($this->annotationReader)) { - $this->annotationReader = $this->annotationReaderFactory->getReaderForClass($this->rClass); - } - return $this->annotationReader; - } - - /** - * @param \Reflector $thing - * @throws \Exception - * @return callable - */ - protected function _getConfigGetter(\Reflector $thing = null) - { - $reader = $this->_getAnnotationReader(); - $annNS = $this->annNS; - if ($thing === null) { - return function ($ann) use ($reader, $annNS) { - return $reader->getSingleClassAnnotation($annNS . $ann); - }; - } - if ($thing instanceof \ReflectionMethod) { - return function ($ann) use ($reader, $thing, $annNS) { - return $reader->getSingleMethodAnnotation($thing->getName(), $annNS . $ann); - }; - } - if ($thing instanceof \ReflectionProperty) { - return function ($ann) use ($reader, $thing, $annNS) { - return $reader->getSinglePropertyAnnotation($thing->getName(), $annNS . $ann); - }; - } - throw new \Exception("Unable to work out how to configure a " . get_class($thing)); - } - - protected function _configureGetter(\ReflectionMethod $method, IJsonProperty $propertyConfig) - { - $name = $method->getName(); - - $getterConfig = new Serialization\GetterSerialization(); - - $property = $propertyConfig->getName(); - if (!isset($property)) { - if (substr($name, 0, 3) === 'get') { - $property = lcfirst(substr($name, 3)); - } elseif (substr($name, 0, 2) === 'is') { - if ($propertyConfig->getType() === 'bool') { - $property = lcfirst(substr($name, 2)); - } else { - $property = lcfirst($name); - } - } else { - $property = lcfirst($name); - } - } - - $fGetConfig = $this->_getConfigGetter($method); - - /** - * @var Annotations\JsonTypeInfo $typeInfo - * @var Annotations\JsonSubTypes $subTypes - * @var Annotations\JsonInclude $includer - */ - $typeInfo = $fGetConfig('JsonTypeInfo'); - $subTypes = $fGetConfig('JsonSubTypes'); - $includer = $fGetConfig('JsonInclude'); - - $getterConfig->typeInfo = $this->_getSerializationTypeInfo($typeInfo, $subTypes); - $getterConfig->include = $this->_getIncluderValue($includer); - - if (isset($this->config->serialization->properties[$property])) { - throw new \Exception("Serialization for property of name $property has already been configured."); - } - $getterConfig->method = $name; - $getterConfig->type = $propertyConfig->getType(); - - $this->config->serialization->properties[$property] = $getterConfig; - } - - protected function _configureSetter(\ReflectionMethod $method, IJsonProperty $propertyConfig) - { - $name = $method->getName(); - - $property = $propertyConfig->getName(); - if (!isset($property)) { - if (substr($name, 0, 3) === 'set') { - $property = lcfirst(substr($name, 3)); - } else { - $property = lcfirst($name); - } - } - - $fConfigGetter = $this->_getConfigGetter($method); - - /** - * @var Annotations\JsonTypeInfo $typeInfo - * @var Annotations\JsonSubTypes $subTypes - */ - $typeInfo = $fConfigGetter('JsonTypeInfo'); - $subTypes = $fConfigGetter('JsonSubtypes'); - - if (isset($this->config->deserialization->properties[$property])) { - throw new \Exception("Deserialization for property of name $property has already been configured."); - } - $setterConfig = new Deserialization\SetterDeserialization(); - $setterConfig->method = $name; - $setterConfig->type = $propertyConfig->getType(); - $setterConfig->typeInfo = $this->_getDeserializationTypeInfo($typeInfo, $subTypes); - $setterConfig->strict = $propertyConfig->getStrict(); - - $this->config->deserialization->properties[$property] = $setterConfig; - } - - protected function _configureAnyGetter(\ReflectionMethod $method, IJsonAnyGetter $config) - { - if ($method->getNumberOfParameters() != 0) { - throw new \Exception("anyGetter {$method->getName()} must not have parameters"); - } - $this->config->serialization->anyGetter = $method->getName(); - } - - protected function _configureAnySetter(\ReflectionMethod $method, IJsonAnySetter $config) - { - if ($method->getNumberOfParameters() != 2) { - throw new \Exception("anySetter {$method->getName()} must have exactly two parameters"); - } - $this->config->deserialization->anySetter = $method->getName(); - } - - protected function _configureCreator(\ReflectionMethod $method, IJsonCreator $creatorConfig) - { - $name = $method->getName(); - if (isset($this->config->deserialization->creator)) { - throw new \Exception("Found more than one creator method! Last was $name"); - } - $rParams = $creatorConfig->getParams(); - if (count($rParams) === 0) { - $creator = new Deserialization\DelegateCreator(); - $creator->method = $name; - } else { - $creator = new Deserialization\PropertyCreator(); - $creator->method = $name; - $i = 0; - $paramNames = array(); - foreach ($rParams as $rParam) { - $paramNames[] = $rParam->getName(); - } - foreach ($creatorConfig->getParams() as $paramConfig) { - $param = new Deserialization\Param(); - $param->name = $paramConfig->getName(); - $param->type = $paramConfig->getType(); - $param->strict = $paramConfig->getStrict(); - if (!isset($param->name)) { - if (!isset($paramNames[$i])) { - throw new \Exception("Unable to establish name of param $i of $name"); - } - $param->name = $paramNames[$i]; - } - $creator->params[] = $param; - $i++; - } - if (count($creator->params) !== count($paramNames)) { - throw new \Exception('Expected ' . count($paramNames) . ' params but found ' . count($creator->params)); - } - } - $this->config->deserialization->creator = $creator; - } - - protected function _configureMethod(\ReflectionMethod $method) - { - $fGetConfig = $this->_getConfigGetter($method); - - switch (true) { - case ($method->isStatic() || $method->isConstructor()): - if ($config = $fGetConfig('JsonCreator')) { - $this->_configureCreator($method, $config); - } - break; - case ($config = $fGetConfig('JsonAnyGetter')): - $this->_configureAnyGetter($method, $config); - break; - case ($config = $fGetConfig('JsonAnySetter')): - $this->_configureAnySetter($method, $config); - break; - case ($config = $fGetConfig('JsonProperty')): - if ($method->getNumberOfRequiredParameters() == 0) { - $this->_configureGetter($method, $config); - } elseif ($method->getNumberOfRequiredParameters() == 1) { - $this->_configureSetter($method, $config); - } - break; - } - } - - protected function _configureProperty(\ReflectionProperty $property) - { - $name = $property->getName(); - - $fConfigGetter = $this->_getConfigGetter($property); - /** - * @var IJsonProperty $propertyConfig - */ - if (!$propertyConfig = $fConfigGetter('JsonProperty')) { - return; - } - $propertyName = $propertyConfig->getName(); - if (!isset($propertyName)) { - $propertyName = $name; - } - - - /** - * @var Annotations\JsonTypeInfo $typeInfo - * @var Annotations\JsonSubTypes $subTypes - */ - $typeInfo = $fConfigGetter('JsonTypeInfo'); - $subTypes = $fConfigGetter('JsonSubTypes'); - - if (!isset($this->config->deserialization->properties[$propertyName])) { - $setterConfig = new Deserialization\DirectDeserialization(); - $setterConfig->property = $name; - $setterConfig->type = $propertyConfig->getType(); - $setterConfig->typeInfo = $this->_getDeserializationTypeInfo($typeInfo, $subTypes); - - $this->config->deserialization->properties[$propertyName] = $setterConfig; - } - - - if (!isset($this->config->serialization->properties[$propertyName])) { - $getterConfig = new Serialization\DirectSerialization(); - $getterConfig->property = $name; - $getterConfig->type = $propertyConfig->getType(); - - /** - * @var Annotations\JsonInclude $includer - */ - $includer = $fConfigGetter('JsonInclude'); - $getterConfig->include = $this->_getIncluderValue($includer); - $getterConfig->typeInfo = $this->_getSerializationTypeInfo($typeInfo, $subTypes); - - $this->config->serialization->properties[$propertyName] = $getterConfig; - } - - } - - /** - * @param Annotations\JsonInclude $includer - * @return int - */ - protected function _getIncluderValue($includer) - { - $val = $this->config->serialization->include; - if (isset($includer)) { - switch ($includer->getValue()) { - case (IAnnotations\IJsonInclude::INCLUDE_ALWAYS): - $val = Serialization\ClassSerialization::INCLUDE_ALWAYS; - break; - case (IAnnotations\IJsonInclude::INCLUDE_NON_DEFAULT): - $val = Serialization\ClassSerialization::INCLUDE_NON_DEFAULT; - break; - case (IAnnotations\IJsonInclude::INCLUDE_NON_EMPTY): - $val = Serialization\ClassSerialization::INCLUDE_NON_EMPTY; - break; - case (IAnnotations\IJsonInclude::INCLUDE_NON_NULL): - $val = Serialization\ClassSerialization::INCLUDE_NON_NULL; - break; - default: - } - } - return $val; - } - - /** - * Find out what name we should use to referr to one of our subtypes. - * @param \ReflectionClass $rClass - * @return string - */ - protected function _getSubClassName(\ReflectionClass $rClass) - { - $subClassReader = $this->annotationReaderFactory->getReaderForClass($rClass); - /** - * @var Annotations\JsonTypeName $subNameA - */ - $subNameA = $subClassReader->getSingleClassAnnotation($this->annNS . 'JsonTypeName'); - if (isset($subNameA)) { - return $subNameA->getName(); - } else { - return $rClass->getName(); - } - - } - - /** - * @param Annotations\JsonTypeInfo $typeInfo - * @param Annotations\JsonSubTypes $subTypes - * @throws \Exception - * @return Deserialization\TypeInfo|null - */ - protected function _getSerializationTypeInfo($typeInfo, $subTypes) - { - - if (!isset($typeInfo)) { - return null; - } - - $typeConfig = new Serialization\TypeInfo(); - switch ($typeInfo->getUse()) { - case IJsonTypeInfo::ID_CLASS: - $typeConfig->typeInfo = Serialization\TypeInfo::TI_USE_CLASS; - $typeConfig->typeInfoProperty = '@class'; - break; - case IJsonTypeInfo::ID_CUSTOM: - $typeConfig->typeInfo = Serialization\TypeInfo::TI_USE_CUSTOM; - break; - case IJsonTypeInfo::ID_MINIMAL_CLASS: - $typeConfig->typeInfo = Serialization\TypeInfo::TI_USE_MINIMAL_CLASS; - $typeConfig->typeInfoProperty = '@class'; - break; - case IJsonTypeInfo::ID_NAME: - $typeConfig->typeInfo = Serialization\TypeInfo::TI_USE_NAME; - $typeConfig->typeInfoProperty = '@name'; - break; - case IJsonTypeInfo::ID_NONE: - $typeConfig->typeInfo = Serialization\TypeInfo::TI_USE_NONE; - return null; - break; - - } - - if ($typeInfo->getProperty() !== null) { - $typeConfig->typeInfoProperty = $typeInfo->getProperty(); - } - - switch ($typeInfo->getInclude()) { - case IJsonTypeInfo::AS_PROPERTY: - $typeConfig->typeInfoAs = Serialization\TypeInfo::TI_AS_PROPERTY; - break; - case IJsonTypeInfo::AS_WRAPPER_ARRAY: - $typeConfig->typeInfoAs = Serialization\TypeInfo::TI_AS_WRAPPER_ARRAY; - break; - case IJsonTypeInfo::AS_WRAPPER_OBJECT: - $typeConfig->typeInfoAs = Serialization\TypeInfo::TI_AS_WRAPPER_OBJECT; - break; - case IJsonTypeInfo::AS_EXTERNAL_PROPERTY: - $typeConfig->typeInfoAs = Serialization\TypeInfo::TI_AS_EXTERNAL_PROPERTY; - break; - } - - if (isset($subTypes)) { - foreach ($subTypes->getValue() as $type) { - switch ($typeConfig->typeInfo) { - case Serialization\TypeInfo::TI_USE_CLASS: - $subName = ltrim($type->getValue(), '\\'); - break; - case Serialization\TypeInfo::TI_USE_MINIMAL_CLASS: - $exploded = explode('\\', $type->getValue(), 2); - $subName = $exploded[0]; - break; - case Serialization\TypeInfo::TI_USE_NAME: - $subName = $type->getName(); - if (empty($subName)) { - $subName = $this->_getSubClassName(new \ReflectionClass($type->getValue())); - } - break; - case Serialization\TypeInfo::TI_USE_CUSTOM: - default: - throw new \Exception("Unsupported typeinfo mode"); - } - $typeConfig->subTypes[ltrim($type->getValue(), '\\')] = $subName; - } - } - - return $typeConfig; - - - } - - /** - * For the given typeinfo, and sub type info, work out how we're going to be deserialized. - * - * @param Annotations\JsonTypeInfo $typeInfo - * @param Annotations\JsonSubTypes $subTypes - * @throws \Exception - * @return Deserialization\TypeInfo|null - */ - protected function _getDeserializationTypeInfo($typeInfo, $subTypes) - { - - if (!isset($typeInfo)) { - return null; - } - - $typeConfig = new Deserialization\TypeInfo(); - /** - * Based on the Use value we should also choose the default property name - */ - switch ($typeInfo->getUse()) { - case IJsonTypeInfo::ID_CLASS: - $typeConfig->typeInfo = Deserialization\TypeInfo::TI_USE_CLASS; - $typeConfig->typeInfoProperty = '@class'; - break; - case IJsonTypeInfo::ID_CUSTOM: - $typeConfig->typeInfo = Deserialization\TypeInfo::TI_USE_CUSTOM; - break; - case IJsonTypeInfo::ID_MINIMAL_CLASS: - $typeConfig->typeInfo = Deserialization\TypeInfo::TI_USE_MINIMAL_CLASS; - $typeConfig->typeInfoProperty = '@class'; - break; - case IJsonTypeInfo::ID_NAME: - $typeConfig->typeInfo = Deserialization\TypeInfo::TI_USE_NAME; - $typeConfig->typeInfoProperty = '@name'; - break; - case IJsonTypeInfo::ID_NONE: - $typeConfig->typeInfo = Deserialization\TypeInfo::TI_USE_NONE; - return null; - break; - - } - - if ($typeInfo->getProperty() !== null) { - // If there is a property specified then we should use that rather than the default - $typeConfig->typeInfoProperty = $typeInfo->getProperty(); - } - - $typeConfig->typeInfoVisible = $typeInfo->getVisible(); - $typeConfig->defaultImpl = $typeInfo->getDefaultImpl(); - - switch ($typeInfo->getInclude()) { - case IJsonTypeInfo::AS_PROPERTY: - $typeConfig->typeInfoAs = Deserialization\TypeInfo::TI_AS_PROPERTY; - break; - case IJsonTypeInfo::AS_WRAPPER_ARRAY: - $typeConfig->typeInfoAs = Deserialization\TypeInfo::TI_AS_WRAPPER_ARRAY; - break; - case IJsonTypeInfo::AS_WRAPPER_OBJECT: - $typeConfig->typeInfoAs = Deserialization\TypeInfo::TI_AS_WRAPPER_OBJECT; - break; - case IJsonTypeInfo::AS_EXTERNAL_PROPERTY: - $typeConfig->typeInfoAs = Deserialization\TypeInfo::TI_AS_EXTERNAL_PROPERTY; - break; - } - - if (isset($subTypes)) { - // Now we need to store a mapping from our discriminator values to the sub types - foreach ($subTypes->getValue() as $type) { - switch ($typeConfig->typeInfo) { - case Deserialization\TypeInfo::TI_USE_CLASS: - $subName = ltrim($type->getValue(), '\\'); - break; - case Deserialization\TypeInfo::TI_USE_MINIMAL_CLASS: - $exploded = explode('\\', $type->getValue(), 2); - $subName = $exploded[0]; - break; - case Deserialization\TypeInfo::TI_USE_NAME: - $subName = $type->getName(); - if (empty($subName)) { - // We've got to find out if our sub class has a JsonTypeName annotation - $subName = $this->_getSubClassName(new \ReflectionClass($type->getValue())); - } - break; - case Deserialization\TypeInfo::TI_USE_CUSTOM: - default: - throw new \Exception("Unsupported typeinfo mode"); - } - $typeConfig->subTypes[$subName] = ltrim($type->getValue(), '\\'); - } - } - - return $typeConfig; - - - } - - /** - * Get the config for the current class. - * @return ClassMarshaller A populated ClassMarshaller config object. - */ - public function getConfig() - { - $this->config = new ClassMarshaller(); - $this->config->serialization = new Serialization\ClassSerialization(); - $this->config->deserialization = new Deserialization\ClassDeserialization(); - - $reader = $this->_getAnnotationReader(); - - /** - * @var \Weasel\JsonMarshaller\Config\Annotations\JsonInclude $includer - */ - $includer = $reader->getSingleClassAnnotation($this->annNS . 'JsonInclude'); - $this->config->serialization->include = $this->_getIncluderValue($includer); - - /** - * Work out what the class' "name" is, just in case inheritance is needed. - * @var \Weasel\JsonMarshaller\Config\Annotations\JsonTypeName $typeNamer - */ - $typeNamer = $reader->getSingleClassAnnotation($this->annNS . 'JsonTypeName'); - $name = null; - if (isset($typeNamer)) { - $name = $typeNamer->getName(); - } - if (empty($name)) { - // Default to the unqualified class name - $name = $this->rClass->getName(); - } - $this->config->deserialization->name = $name; - - /** - * @var Annotations\JsonTypeInfo $typeInfo - * @var Annotations\JsonSubTypes $subTypes - */ - $typeInfo = $reader->getSingleClassAnnotation($this->annNS . 'JsonTypeInfo'); - $subTypes = $reader->getSingleClassAnnotation($this->annNS . 'JsonSubTypes'); - $this->config->deserialization->typeInfo = $this->_getDeserializationTypeInfo($typeInfo, $subTypes); - $this->config->serialization->typeInfo = $this->_getSerializationTypeInfo($typeInfo, $subTypes); - - $methods = $this->rClass->getMethods(\ReflectionMethod::IS_PUBLIC); - - foreach ($methods as $method) { - $this->_configureMethod($method); - } - - $properties = $this->rClass->getProperties(\ReflectionProperty::IS_PUBLIC & ~\ReflectionProperty::IS_STATIC); - foreach ($properties as $property) { - $this->_configureProperty($property); - } - - /** - * @var \Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties $ignorer - */ - $ignorer = $reader->getSingleClassAnnotation($this->annNS . 'JsonIgnoreProperties'); - if (!empty($ignorer)) { - // The ignorer config affects which properties we will consider. - $this->config->deserialization->ignoreUnknown = $ignorer->getIgnoreUnknown(); - $this->config->deserialization->ignoreProperties = $ignorer->getNames(); - } - - - return $this->config; - - } - - - /** - * Sets a logger instance on the object - * - * @param LoggerInterface $logger - * @return null - */ - public function setLogger(LoggerInterface $logger) - { - $this->annotationReaderFactory->setLogger($logger); - } - - -} diff --git a/lib/Weasel/JsonMarshaller/Config/ClassMarshaller.php b/lib/Weasel/JsonMarshaller/Config/ClassMarshaller.php deleted file mode 100644 index ef21b35..0000000 --- a/lib/Weasel/JsonMarshaller/Config/ClassMarshaller.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config; - -/** - * Holder for the configuration for marshalling of a class - */ -use Weasel\JsonMarshaller\Config\Serialization\ClassSerialization; -use Weasel\JsonMarshaller\Config\Deserialization\ClassDeserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class ClassMarshaller -{ - - public function __construct() - { - $this->serialization = new ClassSerialization(); - $this->deserialization = new ClassDeserialization(); - } - - /** - * @var \Weasel\JsonMarshaller\Config\Serialization\ClassSerialization - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Serialization\ClassSerialization") - */ - public $serialization; - - /** - * @var \Weasel\JsonMarshaller\Config\Deserialization\ClassDeserialization - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\ClassDeserialization") - */ - public $deserialization; - - public function __toString() - { - return "[ClassMarshaller serialization=" . $this->serialization . " deserialization=" . $this->deserialization . "]"; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/ClassDeserialization.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/ClassDeserialization.php deleted file mode 100644 index 9d1a4e6..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Deserialization/ClassDeserialization.php +++ /dev/null @@ -1,79 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Deserialization; - -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class ClassDeserialization -{ - - /** - * @var \Weasel\JsonMarshaller\Config\Deserialization\PropertyDeserialization[] - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\PropertyDeserialization[string]") - */ - public $properties = array(); - - /** - * @var \Weasel\JsonMarshaller\Config\Deserialization\Creator - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\Creator") - */ - public $creator = null; - - /** - * @var bool - * @JsonProperty(type="bool") - */ - public $ignoreUnknown; - - /** - * @var string[] - * @JsonProperty(type="string[]") - */ - public $ignoreProperties; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $name; - - /** - * @var \Weasel\JsonMarshaller\Config\Deserialization\TypeInfo - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\TypeInfo") - */ - public $typeInfo; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $anySetter = null; - - - function __construct($name = null, $properties = array(), $anySetter = null, $creator = null, $ignoreProperties = null, $ignoreUnknown = null, $typeInfo = null) - { - $this->anySetter = $anySetter; - $this->creator = $creator; - $this->ignoreProperties = $ignoreProperties; - $this->ignoreUnknown = $ignoreUnknown; - $this->name = $name; - $this->properties = $properties; - $this->typeInfo = $typeInfo; - } - - public function __toString() - { - $props = array(); - foreach ($this->properties as $key => $value) { - $props[] = $key . ' => ' . $value; - } - return '[ClassDeserialization name=' . $this->name . ' ignoreProperties={' . implode(', ', - $this->ignoreProperties) . '} anySetter=' . $this->anySetter . - ' ignoreUnknown=' . ($this->ignoreUnknown ? "true" : "false") . ' typeInfo=' . $this->typeInfo . ' creator=' . $this->creator . - ' properties={' . implode(", ", $props) . '}'; - } -} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/Creator.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/Creator.php deleted file mode 100644 index 34c9c8d..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Deserialization/Creator.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Deserialization; - -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -/** - * Class Creator - * @package Weasel\JsonMarshaller\Config\Deserialization - * @JsonSubTypes({ - * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Deserialization\DelegateCreator"), - * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Deserialization\PropertyCreator"), - * }) - * @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="creator") - */ -abstract class Creator -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $method; - - public function __toString() - { - return '[Creator method=' . $this->method . ']'; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/DelegateCreator.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/DelegateCreator.php deleted file mode 100644 index 0aafb06..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Deserialization/DelegateCreator.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class DelegateCreator - * @package Weasel\JsonMarshaller\Config\Deserialization - * @JsonTypeName("delegate") - */ -class DelegateCreator extends Creator -{ - - public function __toString() - { - return '[DelegateCreator method=' . $this->method . ']'; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/DirectDeserialization.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/DirectDeserialization.php deleted file mode 100644 index 843d4a8..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Deserialization/DirectDeserialization.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class DirectDeserialization - * @package Weasel\JsonMarshaller\Config\Deserialization - * @JsonTypeName("direct") - */ -class DirectDeserialization extends PropertyDeserialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $property; - - function __construct() - { - $this->how = "direct"; - } - - public function __toString() - { - return "[DirectDeserialization property={$this->property} type={$this->realType} typeInfo={$this->typeInfo}]"; - } -} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/Feature.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/Feature.php deleted file mode 100644 index e251b26..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Deserialization/Feature.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Deserialization; - -/** - * Features for config general mapper behaviour. - * These are the keys to be passed to the mapper configure() method. - */ -interface Feature { - /** - * bool. When true, throw an exception (UnknownPropertyException) on encountering an unknown property in the JSON and - * there's no AnySetter configured (or ignoreUnknown isn't set.) Default: false. - */ - const FAIL_ON_UNKNOWN_PROPERTIES = "deserialization::fail_on_unknown"; - /** - * bool. When true trigger an E_USER_WARNING on encountering an unknown property in the JSON and there's no AnySetter - * configured (or ignoreUnknown isn't set.) Default: true. - */ - const WARN_ON_UNKNOWN_PROPERTIES = "deserialization::warn_on_unknown"; - - /** - * bool. When true apply strict type checking. JSON types encountered are expected to match the PHP types we're - * going to deserialize to. If they don't, throw an exception. Default true. - */ - const STRICT_TYPES = "deserialization::strict_types"; - -} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/Param.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/Param.php deleted file mode 100644 index 6b98c01..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Deserialization/Param.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class Param - * @package Weasel\JsonMarshaller\Config\Deserialization - * @JsonTypeName("param") - */ -class Param extends PropertyDeserialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $name; - - public function __toString() - { - return "[ParamDeserialization name={$this->name} type={$this->type} typeInfo={$this->typeInfo}]"; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyCreator.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyCreator.php deleted file mode 100644 index 27c59e5..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyCreator.php +++ /dev/null @@ -1,29 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class PropertyCreator - * @package Weasel\JsonMarshaller\Config\Deserialization - * @JsonTypeName("property") - */ -class PropertyCreator extends Creator -{ - /** - * @var \Weasel\JsonMarshaller\Config\Deserialization\Param[] - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\Param[]") - */ - public $params = array(); - - public function __toString() - { - return "[PropertyCreator method={$this->method} params={" . implode(", ", $this->params) . "}]"; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyDeserialization.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyDeserialization.php deleted file mode 100644 index fbd8d67..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyDeserialization.php +++ /dev/null @@ -1,69 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo; -use Weasel\JsonMarshaller\Config\Type\Type; -use Weasel\JsonMarshaller\Config\Type\TypeParser; - -/** - * Class PropertyDeserialization - * @package Weasel\JsonMarshaller\Config\Deserialization - * @JsonSubTypes({ - * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Deserialization\Param"), - * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Deserialization\SetterDeserialization"), - * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Deserialization\DirectDeserialization"), - * }) - * @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="how", visible=true) - */ -abstract class PropertyDeserialization -{ - - /** - * @var Type - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Type\Type") - */ - public $realType; - - /** - * @var \Weasel\JsonMarshaller\Config\Deserialization\TypeInfo - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\TypeInfo") - */ - public $typeInfo; - - /** - * @var bool Should type checking be strict? - * @JsonProperty(type="bool") - */ - public $strict = true; - - public $how; - - /** - * @param string $value - * @JsonProperty(type="string") - * @deprecated exists only for backwards compat, use realType. - */ - public function setType($value) - { - $this->realType = TypeParser::parseTypeString($value); - } - - /** - * @return string - */ - abstract public function __toString(); - - public function __set($key, $value) - { - if ($key == "type") { - $this->setType($value); - } - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/SetterDeserialization.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/SetterDeserialization.php deleted file mode 100644 index bc589f7..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Deserialization/SetterDeserialization.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Deserialization; - -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class SetterDeserialization - * @package Weasel\JsonMarshaller\Config\Deserialization - * @JsonTypeName("setter") - */ -class SetterDeserialization extends PropertyDeserialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $method; - - function __construct() - { - $this->how = "setter"; - } - - public function __toString() - { - return "[SetterDeserialization method={$this->method} type={$this->realType} typeInfo={$this->typeInfo}]"; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/TypeInfo.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/TypeInfo.php deleted file mode 100644 index aaa6f81..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Deserialization/TypeInfo.php +++ /dev/null @@ -1,65 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class TypeInfo -{ - const TI_USE_CLASS = 1; - const TI_USE_CUSTOM = 2; - const TI_USE_MINIMAL_CLASS = 3; - const TI_USE_NAME = 4; - const TI_USE_NONE = 5; - - const TI_AS_PROPERTY = 1; - const TI_AS_WRAPPER_OBJECT = 2; - const TI_AS_WRAPPER_ARRAY = 3; - const TI_AS_EXTERNAL_PROPERTY = 4; - - /** - * @var string[] - * @JsonProperty(type="string[string]") - */ - public $subTypes; - - /** - * @var int - * @JsonProperty(type="int") - */ - public $typeInfo = self::TI_USE_NONE; - - /** - * @var int - * @JsonProperty(type="int") - */ - public $typeInfoAs = self::TI_AS_PROPERTY; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $defaultImpl; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $typeInfoProperty; - - /** - * @var bool - * @JsonProperty(type="bool") - */ - public $typeInfoVisible = false; - - public function __toString() - { - return '[TypeInfo subTypes={' . implode(', ', $this->subTypes) . '} typeInfo=' . $this->typeInfo . - ' typeInfoAs=' . $this->typeInfoAs . ' typeInfoProperty=' . $this->typeInfoProperty . - 'defaultImpl=' . $this->defaultImpl . ' typeInfoVisible=' . ($this->typeInfoVisible ? "true" : "false") . ']'; - } -} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetter.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetter.php deleted file mode 100644 index 76cb5a8..0000000 --- a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetter.php +++ /dev/null @@ -1,21 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Weasel\Common\Utils\NoUndeclaredProperties; -use Doctrine\Common\Annotations\Annotation; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnyGetter; - -/** - * @Annotation - * @Target("METHOD") - */ -class JsonAnyGetter extends NoUndeclaredProperties implements IJsonAnyGetter -{ - - -} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetter.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetter.php deleted file mode 100644 index 76de796..0000000 --- a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetter.php +++ /dev/null @@ -1,21 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Weasel\Common\Utils\NoUndeclaredProperties; -use Doctrine\Common\Annotations\Annotation; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnySetter; - -/** - * @Annotation - * @Target("METHOD") - */ -class JsonAnySetter extends NoUndeclaredProperties implements IJsonAnySetter -{ - - -} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php deleted file mode 100644 index 67f5c1e..0000000 --- a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php +++ /dev/null @@ -1,51 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonCreator; - -/** - * @Annotation - * @Target("METHOD") - */ - -class JsonCreator extends NoUndeclaredProperties implements IJsonCreator -{ - - /** - * @var array - */ - public $params = array(); - - /** - * @return JsonProperty[] - */ - public function getParams() - { - return $this->params; - } - - /** - * @param array $values - */ - public function __construct($values) - { - if (isset($values["params"])) { - $this->params = $values["params"]; - } elseif (isset($values["value"])) { - if (!is_array($values["value"])) { - $this->params = array($values["value"]); - } else { - $this->params = $values["value"]; - } - } - } - - -} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php deleted file mode 100644 index a895c38..0000000 --- a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php +++ /dev/null @@ -1,68 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Weasel\Common\Utils\NoUndeclaredProperties; -use Doctrine\Common\Annotations\Annotation; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonIgnoreProperties; - -/** - * Provides a list of properties not to consider when serializing/deserializing. - * If ignoreUnknown is true then errors will not be thrown when we encounter properties to deserialize that we do not have a property for, - * they will just be discarded. - * - * @Annotation - * @Target("CLASS") - */ -class JsonIgnoreProperties extends NoUndeclaredProperties implements IJsonIgnoreProperties -{ - - /** - * @return bool - */ - public function getIgnoreUnknown() - { - return $this->ignoreUnknown; - } - - /** - * @return string[] - */ - public function getNames() - { - return $this->names; - } - - /** - * @var array - */ - public $names = array(); - - /** - * @var bool - */ - public $ignoreUnknown = false; - - /** - * @param array $values - */ - public function __construct($values) - { - if (isset($values["names"])) { - $this->names = $values["names"]; - } elseif (isset($values["value"])) { - if (!is_array($values["value"])) { - $this->names = array($values["value"]); - } else { - $this->names = $values["value"]; - } - } - if (isset($values["ignoreUnknown"])) { - $this->ignoreUnknown = $values["ignoreUnknown"]; - } - } -} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonInclude.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonInclude.php deleted file mode 100644 index 0b737e9..0000000 --- a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonInclude.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Weasel\Common\Utils\NoUndeclaredProperties; -use Doctrine\Common\Annotations\Annotation; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonInclude; - -/** - * @Annotation - * @Target({"CLASS", "METHOD", "PROPERTY"}) - */ -class JsonInclude extends NoUndeclaredProperties implements IJsonInclude -{ - - /** - * @var integer - * @Enum({\Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude::INCLUDE_ALWAYS, - * \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude::INCLUDE_NON_DEFAULT, - * \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude::INCLUDE_NON_EMPTY, - * \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude::INCLUDE_NON_NULL - * }) - */ - public $value; - - /** - * @return int - */ - public function getValue() - { - return $this->value; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php deleted file mode 100644 index 892afde..0000000 --- a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php +++ /dev/null @@ -1,77 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonProperty; - -/** - * Sets a property up to be serialized/deserialized explicitly. - * The name sets the json field name to use for this property. - * The type specifies the type to use. - * Because PHP is not strongly typed we can only make best guesses about types if you do not provide type info! - * - * @Annotation - * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) - */ -class JsonProperty extends NoUndeclaredProperties implements IJsonProperty -{ - - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $type; - - /** - * @var bool - */ - public $strict = true; - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * @return string - */ - public function getType() - { - return $this->type; - } - - public function __construct($value) - { - if (isset($value["name"])) { - $this->name = $value["name"]; - } - if (isset($value["type"])) { - $this->type = $value["type"]; - } - if (isset($value["strict"])) { - $this->strict = $value["strict"]; - } - } - - /** - * @return bool - */ - public function getStrict() - { - return $this->strict; - } - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes.php deleted file mode 100644 index cad1a27..0000000 --- a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Weasel\Common\Utils\NoUndeclaredProperties; -use Doctrine\Common\Annotations\Annotation; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonSubTypes; - -/** - * The list of subtypes of this base class - * @Annotation - * @Target({"CLASS", "METHOD", "PROPERTY"}) - */ -class JsonSubTypes extends NoUndeclaredProperties implements IJsonSubTypes -{ - - /** - * @var array - */ - public $value; - - /** - * @return JsonSubTypes\Type[] - */ - public function getValue() - { - return $this->value; - } - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes/Type.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes/Type.php deleted file mode 100644 index f246163..0000000 --- a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes/Type.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\Common\Utils\NoUndeclaredProperties; -use Weasel\JsonMarshaller\Config\IAnnotations\JsonSubTypes\IType; - -/** - * A subtype - * @Annotation - * @Target("ANNOTATION") - */ -class Type extends NoUndeclaredProperties implements IType -{ - - /** - * @var string - */ - public $value; - - /** - * @var string - */ - public $name; - - - /** - * @return string - */ - public function getValue() - { - return $this->value; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeInfo.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeInfo.php deleted file mode 100644 index 7a901a8..0000000 --- a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeInfo.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Weasel\Common\Utils\NoUndeclaredProperties; -use Doctrine\Common\Annotations\Annotation; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonTypeInfo; - -/** - * @Annotation - * @Target({"CLASS", "METHOD", "PROPERTY"}) - */ -class JsonTypeInfo extends NoUndeclaredProperties implements IJsonTypeInfo -{ - - /** - * @var int - */ - public $use = self::ID_CLASS; - - /** - * @var int - */ - public $include = self::AS_PROPERTY; - - /** - * @var string - */ - public $property = '@type'; - - /** - * @var bool - */ - public $visible = false; - - /** - * @var string - */ - public $defaultImpl; - - /** - * @return string - */ - public function getInclude() - { - return $this->include; - } - - /** - * @return string - */ - public function getProperty() - { - return $this->property; - } - - /** - * @return string - */ - public function getUse() - { - return $this->use; - } - - public function getVisible() - { - return $this->visible; - } - - /** - * @return string - */ - public function getDefaultImpl() - { - return $this->defaultImpl; - } -} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeName.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeName.php deleted file mode 100644 index 941b87d..0000000 --- a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeName.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Weasel\Common\Utils\NoUndeclaredProperties; -use Doctrine\Common\Annotations\Annotation; -use Weasel\JsonMarshaller\Config\IAnnotations\IJsonTypeName; - -/** - * Allows you to specify an explicit name for this implementation, for use by JsonTypeInfo - * @Annotation - * @Target("CLASS") - */ -class JsonTypeName extends NoUndeclaredProperties implements IJsonTypeName -{ - - /** - * @var string - */ - public $name; - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnyGetter.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnyGetter.php deleted file mode 100644 index e28892a..0000000 --- a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnyGetter.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\IAnnotations; - - -/** - * Used to mark as method as the "Any Getter." - * - * A method so marked will be called to obtain a map of extra stuff to add to the output. - */ -interface IJsonAnyGetter -{ - -} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnySetter.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnySetter.php deleted file mode 100644 index e72975b..0000000 --- a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnySetter.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\IAnnotations; - - -/** - * Mark a method as the "Any Setter" - * This method will be called with a set of key => value pairs containing any data from the JSON that we didn't - * recognise as belonging in another field. - */ -interface IJsonAnySetter -{ - -} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonCreator.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonCreator.php deleted file mode 100644 index 65688f4..0000000 --- a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonCreator.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\IAnnotations; - -/** - * Mark a static factory method or constructor, and define the params to call it with. - */ -interface IJsonCreator -{ - - /** - * @return IJsonProperty[] An array of IJsonProperty defining the params to call the method with. - */ - public function getParams(); - -} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonIgnoreProperties.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonIgnoreProperties.php deleted file mode 100644 index 140504e..0000000 --- a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonIgnoreProperties.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\IAnnotations; - -/** - * Configure the ignoring of unknown JSON elements for a class. - */ -interface IJsonIgnoreProperties -{ - - /** - * @return bool True if we should silently ignore all unknowns, false if not. - */ - public function getIgnoreUnknown(); - - /** - * @return string[] List of JSON properties we should silently ignore. - */ - public function getNames(); - -} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonInclude.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonInclude.php deleted file mode 100644 index 986da77..0000000 --- a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonInclude.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\IAnnotations; - -/** - * Set what properties to include for a class when serializing to JSON. - */ -interface IJsonInclude -{ - - const INCLUDE_ALWAYS = 1; // Always include every property - const INCLUDE_NON_DEFAULT = 2; // Include any property not set to it's default value. - const INCLUDE_NON_EMPTY = 3; // Include any property that isn't empty() - const INCLUDE_NON_NULL = 4; // Include any property that isn't === null - - /** - * @return int One of the INCLUDE_ consts. - */ - public function getValue(); - -} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonProperty.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonProperty.php deleted file mode 100644 index 734642c..0000000 --- a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonProperty.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\IAnnotations; - -/** - * Sets a property up to be serialized/deserialized explicitly. - * The name sets the json field name to use for this property. - * The type specifies the type to use. - * Because PHP is not strongly typed we can only make best guesses about types if you do not provide type info! - */ -interface IJsonProperty -{ - - /** - * @return string Name to use for the JSON field (optional.) For a property the default is lcfirst($propertyName) - * For a method any leading "get" or "set" will be stripped, and a leading "is" stripped if the - * type's a bool and the method is thought to be a getter (it has 1 param.) - */ - public function getName(); - - /** - * @return string The Weasel type for the field. - */ - public function getType(); - - /** - * @return bool Should strict type checking be used? - */ - public function getStrict(); - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonSubTypes.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonSubTypes.php deleted file mode 100644 index a51b965..0000000 --- a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonSubTypes.php +++ /dev/null @@ -1,21 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\IAnnotations; - -/** - * The list of subtypes of this base class. - */ -interface IJsonSubTypes -{ - - /** - * @return JsonSubTypes\IType[] The list of sub-types - */ - public function getValue(); - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeInfo.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeInfo.php deleted file mode 100644 index ec1805b..0000000 --- a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeInfo.php +++ /dev/null @@ -1,63 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\IAnnotations; - -/** - * Configure behaviour when dealing with inheritance. - * When on a class this defines the behaviour to use when dealing with it's subclasses. - * When on a property this defines the behaviour to use when dealing with subclasses of a the property's type. - * - * Without this we wont be able to work out how to encode the type of subclasses. - */ -interface IJsonTypeInfo -{ - - /* - * These constants define what to use as the identifier of a subclass - */ - const ID_CLASS = 1; // Use the fully qualified class name. - const ID_CUSTOM = 2; // Use a custom method to obtain the name. - const ID_MINIMAL_CLASS = 3; // Use the class name not including namespace. - const ID_NAME = 4; // Use a "name" configured by @JsonSubTypes (on the parent) or @JsonTypeName (on the child) - const ID_NONE = 5; // Don't store anything. This will not permit deserialization as a subclass (default.) - - /* - * And these constants set where to store the identifier. - */ - const AS_PROPERTY = 1; // Store as a property on the JSON object (default.) - const AS_WRAPPER_ARRAY = 2; // Store as a wrapper array e.g. array($id, $object) - const AS_WRAPPER_OBJECT = 3; // Store as a wrapper object e.g. array($id => $object) - const AS_EXTERNAL_PROPERTY = 4; // Store as a property on the containing object (only works if on a property.) - - /** - * @return int Get how to include the ID, one of the AS_ constants. - */ - public function getInclude(); - - /** - * @return string If we're storing as property or ext property, what name should we use? - * Default for ID_*CLASS is "@class" - * Default for ID_NAME is "@name" - */ - public function getProperty(); - - /** - * @return int Get what to use as the ID, one of the ID_ constants. - */ - public function getUse(); - - /** - * @return bool If we're storing as a property should the property be visible on the PHP object? - */ - public function getVisible(); - - /** - * @return string If we can't work out what subclass to use, we'll assume it's one of these. Fully qualified class. - */ - public function getDefaultImpl(); - -} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeName.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeName.php deleted file mode 100644 index ec39d9c..0000000 --- a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeName.php +++ /dev/null @@ -1,21 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\IAnnotations; - -/** - * Allows you to specify an explicit name for a class, for use by JsonTypeInfo - */ -interface IJsonTypeName -{ - - /** - * @return string The name. - */ - public function getName(); - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/JsonSubTypes/IType.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/JsonSubTypes/IType.php deleted file mode 100644 index 2faf1e7..0000000 --- a/lib/Weasel/JsonMarshaller/Config/IAnnotations/JsonSubTypes/IType.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\IAnnotations\JsonSubTypes; - -/** - * Type values for use in IJsonSubTypes; - */ -interface IType -{ - - /** - * @return string The fully qualified class which is our subtype (required.) - */ - public function getValue(); - - /** - * @return string The name to use for this subtype (optional.) - */ - public function getName(); - -} - diff --git a/lib/Weasel/JsonMarshaller/Config/JsonConfigProvider.php b/lib/Weasel/JsonMarshaller/Config/JsonConfigProvider.php deleted file mode 100644 index b3e8c32..0000000 --- a/lib/Weasel/JsonMarshaller/Config/JsonConfigProvider.php +++ /dev/null @@ -1,22 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config; - -/** - * A config provider is expected to somehow obtain the configuration (Config\ClassMarshaller) for a named class. - */ -interface JsonConfigProvider -{ - - /** - * Obtain the config for a named class - * @param string $class The class to get the config for - * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found - */ - public function getConfig($class); - -} diff --git a/lib/Weasel/JsonMarshaller/Config/MultiConfigProvider.php b/lib/Weasel/JsonMarshaller/Config/MultiConfigProvider.php deleted file mode 100644 index 2d6f4bb..0000000 --- a/lib/Weasel/JsonMarshaller/Config/MultiConfigProvider.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ - -namespace Weasel\JsonMarshaller\Config; - -/** - * Allow you to have multiple config sources, all working together to provide one config. - * This would be useful if you've broken your JSON config up into multiple different files for some reason. - * @package Weasel\JsonMarshaller\Config - */ -class MultiConfigProvider implements JsonConfigProvider -{ - - /** - * @var JsonConfigProvider[] - */ - private $providers = array(); - - /** - * @param JsonConfigProvider[] $providers Array of providers - */ - public function __construct(array $providers = array()) - { - $this->providers = $providers; - } - - /** - * Obtain the config for a named class - * @param string $class The class to get the config for - * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found - */ - public function getConfig($class) - { - foreach ($this->providers as $provider) { - $config = $provider->getConfig($class); - if ($config) { - return $config; - } - } - return null; - } -} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/PropertyConfigProvider.php b/lib/Weasel/JsonMarshaller/Config/PropertyConfigProvider.php deleted file mode 100644 index ac31c44..0000000 --- a/lib/Weasel/JsonMarshaller/Config/PropertyConfigProvider.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ - -namespace Weasel\JsonMarshaller\Config; - -/** - * Class PropertyConfigProvider - * A really boring config provider which works off a public property containing a config object structure. - * This might be suitable for building a configuration from some DI framework or something. - * @package Weasel\JsonMarshaller\Config - */ -class PropertyConfigProvider implements JsonConfigProvider -{ - - /** - * @var ClassMarshaller[] Map of class names to ClassMarshallers - */ - public $config = array(); - - /** - * @param ClassMarshaller[] $config Map of class names to ClassMarshallers - */ - public function __construct(array $config = array()) - { - $this->config = $config; - } - - /** - * Obtain the config for a named class - * @param string $class The class to get the config for - * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found - */ - public function getConfig($class) - { - $class = ltrim($class, '\\'); - if (isset($this->config[$class])) { - return $this->config[$class]; - } - return null; - } -} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Serialization/ClassSerialization.php b/lib/Weasel/JsonMarshaller/Config/Serialization/ClassSerialization.php deleted file mode 100644 index 72bcfd2..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Serialization/ClassSerialization.php +++ /dev/null @@ -1,51 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Serialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class ClassSerialization -{ - - const INCLUDE_ALWAYS = 1; - const INCLUDE_NON_DEFAULT = 2; - const INCLUDE_NON_EMPTY = 3; - const INCLUDE_NON_NULL = 4; - - /** - * @var \Weasel\JsonMarshaller\Config\Serialization\PropertySerialization[] Map of names to how to serialize them - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Serialization\PropertySerialization[string]") - */ - public $properties = array(); - - /** - * @var int - * @JsonProperty(type="int") - */ - public $include = self::INCLUDE_ALWAYS; - - /** - * @var \Weasel\JsonMarshaller\Config\Serialization\TypeInfo - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Serialization\TypeInfo") - */ - public $typeInfo; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $anyGetter = null; - - public function __toString() - { - $props = array(); - foreach ($this->properties as $key => $value) { - $props[] = $key . ' => ' . $value; - } - return '[ClassSerialization include=' . $this->include . ' anyGetter=' . $this->anyGetter . ' typeInfo=' . $this->typeInfo . - ' properties={' . implode(", ", $props) . '}'; - } -} diff --git a/lib/Weasel/JsonMarshaller/Config/Serialization/DirectSerialization.php b/lib/Weasel/JsonMarshaller/Config/Serialization/DirectSerialization.php deleted file mode 100644 index bb61f0d..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Serialization/DirectSerialization.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Serialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class DirectSerialization - * @package Weasel\JsonMarshaller\Config\Serialization - * @JsonTypeName("direct") - */ -class DirectSerialization extends PropertySerialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $property; - - function __construct() - { - $this->how = "direct"; - } - - public function __toString() - { - return "[DirectSerialization property={$this->property} include={$this->include} type={$this->realType} typeInfo={$this->typeInfo}]"; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Serialization/GetterSerialization.php b/lib/Weasel/JsonMarshaller/Config/Serialization/GetterSerialization.php deleted file mode 100644 index b881265..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Serialization/GetterSerialization.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Serialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class GetterSerialization - * @package Weasel\JsonMarshaller\Config\Serialization - * @JsonTypeName("getter") - */ -class GetterSerialization extends PropertySerialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $method; - - function __construct($method = null, $type = null, $include = null, $typeInfo = null) - { - $this->method = $method; - $this->include = $include; - $this->typeInfo = $typeInfo; - $this->how = "getter"; - $this->setType($type); - } - - public function __toString() - { - return "[GetterSerialization method={$this->method} include={$this->include} type={$this->realType} typeInfo={$this->typeInfo}]"; - } - - -} diff --git a/lib/Weasel/JsonMarshaller/Config/Serialization/PropertySerialization.php b/lib/Weasel/JsonMarshaller/Config/Serialization/PropertySerialization.php deleted file mode 100644 index 3e761f0..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Serialization/PropertySerialization.php +++ /dev/null @@ -1,68 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Serialization; - -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo; -use Weasel\JsonMarshaller\Config\Type\Type; -use Weasel\JsonMarshaller\Config\Type\TypeParser; - -/** - * Class PropertySerialization - * @package Weasel\JsonMarshaller\Config\Serialization - * @JsonSubTypes({ - * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Serialization\DirectSerialization"), - * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Serialization\GetterSerialization"), - * }) - * @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="how", visible=true) - */ -abstract class PropertySerialization -{ - - /** - * @var integer - * @JsonProperty(type="int") - */ - public $include; - - /** - * @var Type - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Type\Type") - */ - public $realType; - - /** - * @var \Weasel\JsonMarshaller\Config\Serialization\TypeInfo - * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Serialization\TypeInfo") - */ - public $typeInfo; - - public $how; - - /** - * @return string - */ - abstract public function __toString(); - - public function __set($key, $value) - { - if ($key == "type") { - $this->setType($value); - } - } - - /** - * @param string $value - * @JsonProperty(type="string") - * @deprecated exists only for backwards compat, use realType. - */ - public function setType($value) - { - $this->realType = TypeParser::parseTypeString($value); - } -} diff --git a/lib/Weasel/JsonMarshaller/Config/Serialization/TypeInfo.php b/lib/Weasel/JsonMarshaller/Config/Serialization/TypeInfo.php deleted file mode 100644 index e3b5fce..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Serialization/TypeInfo.php +++ /dev/null @@ -1,53 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Serialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class TypeInfo -{ - const TI_USE_CLASS = 1; - const TI_USE_CUSTOM = 2; - const TI_USE_MINIMAL_CLASS = 3; - const TI_USE_NAME = 4; - const TI_USE_NONE = 5; - - const TI_AS_PROPERTY = 1; - const TI_AS_WRAPPER_OBJECT = 2; - const TI_AS_WRAPPER_ARRAY = 3; - const TI_AS_EXTERNAL_PROPERTY = 4; - - /** - * @var string[] - * @JsonProperty(type="string[string]") - */ - public $subTypes; - - /** - * @var int - * @JsonProperty(type="int") - */ - public $typeInfo = self::TI_USE_NONE; - - /** - * @var int - * @JsonProperty(type="int") - */ - public $typeInfoAs = self::TI_AS_PROPERTY; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $typeInfoProperty; - - public function __toString() - { - return '[TypeInfo subTypes={' . implode(', ', - $this->subTypes) . '} typeInfo=' . $this->typeInfo . ' typeInfoAs=' . $this->typeInfoAs . ' typeInfoProperty=' . $this->typeInfoProperty . ']'; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Config/SerializedConfigProvider.php b/lib/Weasel/JsonMarshaller/Config/SerializedConfigProvider.php deleted file mode 100644 index 52315ed..0000000 --- a/lib/Weasel/JsonMarshaller/Config/SerializedConfigProvider.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ - -namespace Weasel\JsonMarshaller\Config; - -use Weasel\JsonMarshaller\Config\Serialization\ClassSerialization; - -class SerializedConfigProvider implements JsonConfigProvider -{ - - private static $_bootstrapConfig = null; - - private $configFile = null; - - public function __construct($filename) - { - $this->configFile = $filename; - } - - private function _buildBootstrapConfig() - { - $file = $this->configFile; - self::$_bootstrapConfig[$file] = unserialize(file_get_contents($file)); - } - - /** - * Obtain the config for a named class - * @param string $class The class to get the config for - * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found - */ - public function getConfig($class) - { - $class = ltrim($class, '\\'); - $file = $this->configFile; - if (!isset(self::$_bootstrapConfig[$file])) { - $this->_buildBootstrapConfig(); - } - return isset(self::$_bootstrapConfig[$file][$class]) ? self::$_bootstrapConfig[$file][$class] : null; - } - -} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Type/ListType.php b/lib/Weasel/JsonMarshaller/Config/Type/ListType.php deleted file mode 100644 index 2183eb9..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Type/ListType.php +++ /dev/null @@ -1,23 +0,0 @@ -type = "list"; - $this->elementType = $elementType; - $this->indexType = new ScalarType("int"); - } - -} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Type/MapType.php b/lib/Weasel/JsonMarshaller/Config/Type/MapType.php deleted file mode 100644 index 3955f31..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Type/MapType.php +++ /dev/null @@ -1,36 +0,0 @@ -type = "map"; - $this->elementType = $elementType; - $this->indexType = $indexType; - } - -} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Type/ScalarType.php b/lib/Weasel/JsonMarshaller/Config/Type/ScalarType.php deleted file mode 100644 index a2b6e57..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Type/ScalarType.php +++ /dev/null @@ -1,28 +0,0 @@ -type = "scalar"; - $this->typeName = $typeName; - } - -} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Type/Type.php b/lib/Weasel/JsonMarshaller/Config/Type/Type.php deleted file mode 100644 index c757258..0000000 --- a/lib/Weasel/JsonMarshaller/Config/Type/Type.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ - -namespace Weasel\JsonMarshaller\Exception; - -class BadConfigurationException extends JsonMarshallerException -{ - -} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Exception/InvalidTypeException.php b/lib/Weasel/JsonMarshaller/Exception/InvalidTypeException.php deleted file mode 100644 index a5fa657..0000000 --- a/lib/Weasel/JsonMarshaller/Exception/InvalidTypeException.php +++ /dev/null @@ -1,66 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Exception; -use Exception; - -class InvalidTypeException extends JsonMarshallerException -{ - - protected $expectedType; - protected $gotType; - protected $gotValue; - - protected function _stringifyValue($value) - { - $typeStr = '(' . gettype($value) . ')'; - if (is_int($value) || is_float($value) || (is_object($value) && method_exists($value, "__toString"))) { - return $typeStr . $value; - } elseif (is_string($value)) { - return $typeStr . '"' . addcslashes($value, '"') . '"'; - } elseif (is_bool($value)) { - return $typeStr . ($value ? "true" : "false"); - } elseif (is_array($value)) { - $pos = current($value); - $retval = $typeStr . '{'; - $fst = true; - foreach ($value as $key => $element) { - if (!$fst) { - $retval .= ', '; - } - $retval .= $this->_stringifyValue($key) . ' => ' . $this->_stringifyValue($element); - $fst = false; - } - $retval .= '}'; - - if ($pos !== false) { - for (reset($value); current($value) != $pos && current($value) !== false; each($value)) { - ; - } - } - - return $retval; - } - return $typeStr; - } - - /** - * @param string $expected - * @param mixed $gotValue - * @param int $code - * @param \Exception $previous - */ - public function __construct($expected, $gotValue, $code = 0, Exception $previous = null) - { - $this->expectedType = $expected; - $this->gotType = gettype($gotValue); - $this->gotValue = $gotValue; - $message = "Expected $expected but got " . $this->_stringifyValue($gotValue); - parent::__construct($message, $code, $previous); - } - - -} diff --git a/lib/Weasel/JsonMarshaller/Exception/JsonMarshallerException.php b/lib/Weasel/JsonMarshaller/Exception/JsonMarshallerException.php deleted file mode 100644 index 1a54350..0000000 --- a/lib/Weasel/JsonMarshaller/Exception/JsonMarshallerException.php +++ /dev/null @@ -1,13 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Exception; -use Exception; - -class JsonMarshallerException extends Exception -{ - -} diff --git a/lib/Weasel/JsonMarshaller/Exception/UnknownPropertyException.php b/lib/Weasel/JsonMarshaller/Exception/UnknownPropertyException.php deleted file mode 100644 index 27ea509..0000000 --- a/lib/Weasel/JsonMarshaller/Exception/UnknownPropertyException.php +++ /dev/null @@ -1,8 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller; - -use Weasel\Common\Utils\ReflectionUtils; -use Weasel\JsonMarshaller\Config\Serialization\ClassSerialization; -use Weasel\JsonMarshaller\Config\Type\ListType; -use Weasel\JsonMarshaller\Config\Type\MapType; -use Weasel\JsonMarshaller\Config\Type\ScalarType; -use Weasel\JsonMarshaller\Config\Type\Type; -use Weasel\JsonMarshaller\Config\Type\TypeParser; -use Weasel\JsonMarshaller\Exception\BadConfigurationException; -use Weasel\JsonMarshaller\Exception\InvalidTypeException; -use InvalidArgumentException; -use Weasel\JsonMarshaller\Exception\UnknownPropertyException; -use Weasel\JsonMarshaller\Types; -use Weasel\JsonMarshaller\Types\JsonType; -use Weasel\JsonMarshaller\Types\OldTypeWrapper; -use Weasel\JsonMarshaller\Exception\JsonMarshallerException; -use Weasel\JsonMarshaller\Config\JsonConfigProvider; - -class JsonMapper -{ - - /** - * @var \Weasel\JsonMarshaller\Config\JsonConfigProvider The source of our configuration - */ - protected $configProvider; - - /** - * @var Types\JsonType[] Array mapping type names to their handlers - */ - protected $typeHandlers = array(); - - /** - * @var array Configuration parameters. - */ - protected $mapperConfig = array(); - - /** - * Setup a JsonMapper from a config provider - * @param Config\JsonConfigProvider $configProvider - * @param bool $strict Default for strict mode. - */ - public function __construct(JsonConfigProvider $configProvider, $strict = true) - { - $this->configProvider = $configProvider; - $this->_registerBuiltInTypes(); - if (isset($strict)) { - // Legacy way to configure strict mode. - $this->configure(Config\Deserialization\Feature::STRICT_TYPES, $strict); - } - } - - /** - * @param string $key One of the Config\*\Feature:: constants. - * @param mixed $value Appropriate value for the config option. See their documentation. - */ - public function configure($key, $value) - { - $this->mapperConfig[$key] = $value; - } - - protected function getConfigOption($key, $default, $permitsNull = false) - { - if (($permitsNull && array_key_exists($key, $this->mapperConfig)) || isset($this->mapperConfig[$key])) { - return $this->mapperConfig[$key]; - } else { - return $default; - } - } - - /** - * Setup the types we consider "built-in". - */ - protected function _registerBuiltInTypes() - { - $this->registerJsonType("boolean", new Types\BoolType(), array("bool")); - $this->registerJsonType("float", new Types\FloatType()); - $this->registerJsonType("integer", new Types\IntType(), array("int")); - $this->registerJsonType("string", new Types\StringType()); - $this->registerJsonType("datetime", new Types\DateTimeType()); - } - - /** - * Given a string of JSON, decode it into an instance of the named $class. - * @param string $string JSON string containing an object - * @param string $type Type to deserialize to. - * @param bool $strict Use strict type checking. If false will not check any types. If true can be overridden on a property by property basis. If null use the default. - * @throws \InvalidArgumentException - * @return mixed A populated instance of $class - */ - public function readString($string, $type, $strict = null) - { - if ($string === "null" || $string === "") { - return null; - } - $decoded = json_decode($string, true); - if ($decoded === null) { - throw new InvalidArgumentException("Unable to decode JSON: $string"); - } - if ($strict === null) { - $strict = $this->getConfigOption(Config\Deserialization\Feature::STRICT_TYPES, true); - } - return $this->_decodeValue($decoded, $this->_parseTypeString($type), $strict); - } - - /** - * Given a string containing a JSON array decode it into an array of the named $class. - * @param string $string JSON string containing an array - * @param string $class Full namespaced name of the class this JSON array contains - * @param bool $strict Use strict type checking. If false will not check any types. If true can be overridden on a property by property basis. If null use the default. - * @return array Array of populated $class instances - * @deprecated Use readString with an array type. - */ - public function readArray($string, $class, $strict = null) - { - return $this->readString($string, $class . '[]', $strict); - } - - protected function _guessType($data) - { - $type = gettype($data); - - switch ($type) { - case "integer": - case "string": - break; - case "double": - $type = "float"; - break; - case "object": - $type = get_class($data); - break; - case "NULL": - $type = "string"; - break; - default: - throw new InvalidArgumentException("Unable to guess type of data, please provide a type specification."); - } - - return $type; - } - - /** - * Serialize an data to a string of JSON. - * @param mixed $data Data to serialize - * @param string $type Type of the data being encoded. If not provided then this will be guessed. - * Guessing only works with primitives and simple objects. - * @return string The JSON - */ - public function writeString($data, $type = null) - { - if (!isset($type)) { - $type = $this->_guessType($data); - } - return $this->_encodeValue($data, $this->_parseTypeString($type)); - } - - /** - * Serialize an object to an array suitable for passing to json_encode. - * This used to be useful. Now all it does is call json_decode on the result of a writeString(). - * It's probably not what you want to use. - * @param mixed $data The data to serialize - * @param string $type Type of the data being encoded. If not provided then this will be guessed. - * Guessing may not work reliably with complex array structures, or if $data is a subclass - * of the class you actually want to serialize as. - * @return array An array suitable for json_encode. - * @deprecated This is no longer useful since all it does is call json_decode on the result of a writeString() operation. - */ - public function writeArray($data, $type = null) - { - return json_decode($this->writeString($data, $type), true); - } - - /** - * Encode an object to an array representation based on our configuration. - * @param object $object Object to serialize. - * @param Config\Serialization\TypeInfo $typeInfo TypeInfo to override that from the class config, used when a - * property has TypeInfo associated with it. - * @param string $type Type this is being encoded into. - * @throws Exception\InvalidTypeException - * @throws \Exception - * @return array - */ - protected function _encodeObject($object, $typeInfo = null, $type = null) - { - if (!is_object($object)) { - throw new InvalidTypeException($type, $object); - } - - $class = get_class($object); - if (!$class) { - throw new InvalidTypeException($type, $object); - } - $classconfig = $this->configProvider->getConfig($class); - if (!isset($classconfig)) { - throw new BadConfigurationException("No configuration found for class $class"); - } - $config = $classconfig->serialization; - if (!isset($config)) { - throw new BadConfigurationException("No serialization configuration found for class $class"); - } - - $properties = array(); - if (isset($config->anyGetter)) { - $method = $config->anyGetter; - $extras = $object->$method(); - if (isset($extras)) { - if (!is_array($properties)) { - throw new InvalidTypeException("array", $properties); - } - foreach ($extras as $key => $value) { - $properties[$key] = json_encode($value); - } - } - } - - foreach ($config->properties as $key => $propConfig) { - - $value = null; - if ($propConfig->how == "direct") { - /** - * @var Config\Serialization\DirectSerialization $propConfig - */ - - $prop = $propConfig->property; - $value = $object->$prop; - - } elseif ($propConfig->how == "getter") { - /** - * @var Config\Serialization\GetterSerialization $propConfig - */ - - $meth = $propConfig->method; - $value = $object->$meth(); - } else { - throw new BadConfigurationException("No idea how to serialize something with the given config"); - } - - switch ($propConfig->include) { - case ClassSerialization::INCLUDE_ALWAYS: - break; - case Config\Serialization\ClassSerialization::INCLUDE_NON_EMPTY: - if (empty($value)) { - continue 2; - } - break; - case Config\Serialization\ClassSerialization::INCLUDE_NON_DEFAULT: - throw new \Exception("Not currently supported"); - case Config\Serialization\ClassSerialization::INCLUDE_NON_NULL: - if (is_null($value)) { - continue 2; - } - } - - $properties[$key] = $this->_encodeValue($value, $propConfig->realType, $propConfig->typeInfo); - if ($propConfig->typeInfo && - $propConfig->typeInfo->typeInfoAs === Config\Serialization\TypeInfo::TI_AS_EXTERNAL_PROPERTY - ) { - // We need to store the type of the encoded object on ourselves - $propClass = get_class($object); - if ($propClass && isset($typeInfo->subTypes[$propClass])) { - $classId = $typeInfo->subTypes[$propClass]; - - $properties[$propConfig->typeInfo->typeInfoProperty] = $classId; - } - - } - } - - if (!$typeInfo) { - // Typeinfo wasn't passed in on the property, we need to see if we have any to load - if (isset($type)) { - // We load typeinfo stuff from our base type, not the actual class we're serializing. - $parentConfig = $this->configProvider->getConfig($type); - if (isset($parentConfig)) { - $typeInfo = $parentConfig->serialization->typeInfo; - } - } - } - - if ($typeInfo) { - // We need to encode information about what type we are somewhere. - // First off work out what name we go by (what value should be stored wherever it is) - switch ($typeInfo->typeInfo) { - case Config\Serialization\TypeInfo::TI_USE_CLASS: - case Config\Serialization\TypeInfo::TI_USE_MINIMAL_CLASS: - case Config\Serialization\TypeInfo::TI_USE_NAME: - // In all these cases the typeInfo subTypes config should contain the mapping from our class to - // whatever value we should be called by. - if (!isset($typeInfo->subTypes[$class])) { - break; - } - $classId = $typeInfo->subTypes[$class]; - break; - case Config\Serialization\TypeInfo::TI_USE_CUSTOM: // TODO - default: - throw new BadConfigurationException("Unsupported type info at class level"); - } - // Now where should we put this information? - switch ($typeInfo->typeInfoAs) { - case Config\Serialization\TypeInfo::TI_AS_EXTERNAL_PROPERTY: - // The property is on the object that contains us, so this is SEP. - break; - case Config\Serialization\TypeInfo::TI_AS_PROPERTY: - // We're going to store the classId as a string on this object - if (!isset($classId)) { - break; - } - $property = $typeInfo->typeInfoProperty; - $properties[$property] = $this->_encodeToString($classId); - break; - case Config\Serialization\TypeInfo::TI_AS_WRAPPER_ARRAY: - // We're actually going to encase this encoded object in an array containing the classId. - if (!isset($classId)) { - break; - } - return '[' . $this->_encodeToString($classId) . ', ' . $this->_objectToJson($properties) . ']'; - break; - case Config\Serialization\TypeInfo::TI_AS_WRAPPER_OBJECT: - // Very similar yo the wrapper array case, but this time it's a map from the classId to the object. - if (!isset($classId)) { - break; - } - return '{' . $this->_encodeToString($classId) . ': ' . $this->_objectToJson($properties) . '}'; - break; - default: - throw new BadConfigurationException("Unsupported type info storage at class level"); - } - } - - return $this->_objectToJson($properties); - - } - - protected function _objectToJson($properties) - { - $elements = array(); - foreach ($properties as $key => $property) { - $elements[] = $this->_encodeToString($key) . ': ' . $property; - } - return '{' . implode(', ', $elements) . '}'; - } - - - protected function _instantiateClassFromPropertyCreator($array, - $class, - Config\Deserialization\PropertyCreator $creator, - $strict) - { - $args = array(); - foreach ($creator->params as $param) { - $val = null; - if (isset($array[$param->name])) { - $val = $this->_decodeValue($array[$param->name], $param->realType, $param->strict && $strict); - } - $args[] = $val; - } - - if ($creator->method === '__construct') { - return ReflectionUtils::instantiateClassByConstructor($class, $args); - } else { - return ReflectionUtils::invokeStaticMethod($class, $creator->method, $args); - } - } - - - protected function _decodeClass($array, $class, $strict) - { - $classconfig = $this->configProvider->getConfig($class); - if (!isset($classconfig)) { - throw new BadConfigurationException("No configuration found for class $class"); - } - - $deconfig = $classconfig->deserialization; - - $canIgnoreProperties = array(); - if (isset($deconfig->typeInfo)) { - $typeInfo = $deconfig->typeInfo; - // First we need to work out what type to deserialize as - if (isset($typeInfo->defaultImpl)) { - $class = $typeInfo->defaultImpl; - } - $typeId = null; - switch ($typeInfo->typeInfoAs) { - case Config\Deserialization\TypeInfo::TI_AS_EXTERNAL_PROPERTY: - case Config\Deserialization\TypeInfo::TI_AS_PROPERTY: - $property = $typeInfo->typeInfoProperty; - $canIgnoreProperties[$property] = true; - if (!isset($array[$property])) { - break; - } - $typeId = $array[$property]; - if ($typeInfo->typeInfoVisible == false) { - unset($array[$property]); - } - break; - case Config\Deserialization\TypeInfo::TI_AS_WRAPPER_ARRAY: - if (count($array) !== 2) { - throw new InvalidTypeException("array(2)", $array); - } - $typeId = $array[0]; - $array = $array[1]; - break; - case Config\Deserialization\TypeInfo::TI_AS_WRAPPER_OBJECT: - if (count($array) !== 1) { - throw new InvalidTypeException("array(1)", $array); - } - list($typeId) = array_keys($array); - $array = array_shift($array); - break; - default: - throw new BadConfigurationException("Unsupported type info storage at class level"); - } - - switch ($typeInfo->typeInfo) { - case Config\Deserialization\TypeInfo::TI_USE_CLASS: - case Config\Deserialization\TypeInfo::TI_USE_MINIMAL_CLASS: - case Config\Deserialization\TypeInfo::TI_USE_NAME: - if (!isset($typeInfo->subTypes[$typeId])) { - break; - } - $class = $typeInfo->subTypes[$typeId]; - break; - case Config\Deserialization\TypeInfo::TI_USE_CUSTOM: // TODO - default: - throw new BadConfigurationException("Unsupported type info at class level"); - } - - } - $classconfig = $this->configProvider->getConfig($class); - - if (!isset($classconfig)) { - throw new BadConfigurationException("No config found to decode $class"); - } - $deconfig = $classconfig->deserialization; - - if ($deconfig->creator) { - if ($deconfig->creator instanceof Config\Deserialization\DelegateCreator) { - return new $class($array); - } else { - $creator = $deconfig->creator; - /** - * @var Config\Deserialization\PropertyCreator $creator - */ - $object = $this->_instantiateClassFromPropertyCreator($array, $class, $creator, $strict); - foreach ($creator->params as $param) { - $canIgnoreProperties[$param->name] = true; - } - } - } else { - if (class_exists($class)) { - $object = new $class(); - } else { - throw new BadConfigurationException("Configured class $class is not an instantiable class."); - } - } - - if (isset($deconfig->ignoreProperties)) { - foreach ($deconfig->ignoreProperties as $ignore) { - $canIgnoreProperties[$ignore] = true; - } - } - - foreach ($array as $key => $value) { - if (isset($deconfig->properties[$key])) { - $propConfig = $deconfig->properties[$key]; - - try { - $decodedValue = $this->_decodeValue($value, $propConfig->realType, $propConfig->strict && $strict); - } catch (\Exception $e) { - throw new \Exception("Failed to decode property $key on $class", 0, $e); - } - - if ($propConfig->how == "direct") { - /** - * @var Config\Deserialization\DirectDeserialization $propConfig - */ - - $prop = $propConfig->property; - - $object->$prop = $decodedValue; - - } elseif ($propConfig->how == "setter") { - /** - * @var Config\Deserialization\SetterDeserialization $propConfig - */ - - $meth = $propConfig->method; - - $object->$meth($decodedValue); - - } - } elseif (isset($deconfig->anySetter)) { - $method = $deconfig->anySetter; - $object->$method($key, $value); - } elseif (!$deconfig->ignoreUnknown) { - if (!isset($canIgnoreProperties[$key])) { - if ($this->getConfigOption(Config\Deserialization\Feature::WARN_ON_UNKNOWN_PROPERTIES, true)) { - trigger_error("Unknown property $key on $class", E_USER_WARNING); - } - if ($this->getConfigOption(Config\Deserialization\Feature::FAIL_ON_UNKNOWN_PROPERTIES, false)) { - throw new UnknownPropertyException("Unknown property $key on $class"); - } - } - } - } - - return $object; - - - } - - /** - * @param string $typeName - * @return JsonType - */ - protected function _getTypeHandler($typeName) - { - if (isset($this->typeHandlers[$typeName])) { - // Assumption: if there's a type handler for this type string, then it's the right thing to use. - return $this->typeHandlers[$typeName]; - } - return null; - } - - protected function _parseTypeString($type) - { - return TypeParser::parseTypeString($type); - } - - /** - * @param mixed $value - * @param Type $type - * @return mixed - * @throws Exception\InvalidTypeException - * @throws Exception\JsonMarshallerException - */ - protected function _decodeKey($value, $type) - { - if (!isset($value)) { - throw new JsonMarshallerException("Key values cannot be null"); - } - if ($type->type != "scalar") { - throw new JsonMarshallerException("Keys must be of type int or string, not " . $type); - } - // Keys are always strings, however we will allow other types, and disable strict type checking. - return $this->_decodeValue($value, $type, false); - } - - protected function _decodeValue($value, $type, $strict) - { - if (!isset($value)) { - return null; - } - if ($type->type == "scalar") { - $typeName = $type->typeName; - if ($typeName == "integer" || $typeName == "string" || $typeName == "float" || $typeName == "boolean" || $typeName == "datetime") { - return $this->typeHandlers[$typeName]->decodeValue($value, $this, $strict); - } - $typeHandler = $this->_getTypeHandler($typeName); - if (isset($typeHandler)) { - return $typeHandler->decodeValue($value, $this, $strict); - } - if (!is_array($value)) { - throw new InvalidTypeException($typeName, $value); - } - return $this->_decodeClass($value, $typeName, $strict); - } - if ($type->type == "map" || $type->type == "list") { - $indexType = $type->indexType; - $elementType = $type->elementType; - $result = array(); - if (!is_array($value)) { - $value = array($value); - } - foreach ($value as $key => $element) { - $result[$this->_decodeKey($key, $indexType)] = $this->_decodeValue($element, $elementType, $strict); - } - return $result; - - } - return null; - } - - protected function _encodeKey($value, $type) - { - if (!isset($value)) { - throw new JsonMarshallerException("Key values cannot be null"); - } - if (!isset($type->typeName)) { - throw new JsonMarshallerException("Keys must be of type int or string, not " . $type); - } - return $this->_encodeToString($value); - } - - protected function _encodeToString($value) - { - return $this->typeHandlers["string"]->encodeValue($value, $this); - } - - /** - * @param mixed $value - * @param Type $type - * @param Config\Serialization\TypeInfo $typeInfo - * @throws Exception\InvalidTypeException - * @return mixed - */ - protected function _encodeValue($value, $type, $typeInfo = null) - { - if (!isset($value)) { - return "null"; - } - if ($type->type == "scalar") { - /** - * @var ScalarType $type - */ - $typeName = $type->typeName; - if ($typeName == "integer" || $typeName == "string" || $typeName == "float" || $typeName == "boolean" || $typeName == "datetime") { - return $this->typeHandlers[$typeName]->encodeValue($value, $this); - } - $typeHandler = $this->_getTypeHandler($typeName); - if (isset($typeHandler)) { - return $typeHandler->encodeValue($value, $this); - } - return $this->_encodeObject($value, $typeInfo, $type->typeName); - } - if ($type->type == "list") { - /** - * @var ListType $type - */ - $elementType = $type->elementType; - if (!is_array($value)) { - $value = array($value); - } - $elements = array(); - foreach ($value as $element) { - $elements[] = $this->_encodeValue($element, $elementType); - } - return '[' . implode(', ', $elements) . ']'; - } - if ($type->type == "map") { - /** - * @var MapType $type - */ - $indexType = $type->indexType; - $elementType = $type->elementType; - if (!is_array($value)) { - $value = array($value); - } - $elements = array(); - foreach ($value as $key => $element) { - $elements[] = $this->_encodeKey($key, $indexType) . ': ' . $this->_encodeValue($element, - $elementType); - } - return '{' . implode(', ', $elements) . '}'; - } - return "null"; - } - - - /** - * Register a custom type. - * @param string $name - * @param Types\JsonType $handler - * @param string[] $aliases - */ - public function registerJsonType($name, $handler, $aliases = array()) - { - $this->typeHandlers[$name] = $handler; - foreach ($aliases as $alias) { - $this->typeHandlers[$alias] = $handler; - } - } - - /** - * Register an old style custom type. - * This is a compatibility handler and will be removed. Please use registerJsonType! - * @Deprecated - * @param string $name - * @param Types\Type $handler - * @param string[] $aliases - */ - public function registerType($name, $handler, $aliases = array()) - { - trigger_error("Types are deprecated, use JsonTypes through registerJsonType.", E_USER_DEPRECATED); - $this->registerJsonType($name, new OldTypeWrapper($handler), $aliases); - } -} diff --git a/lib/Weasel/JsonMarshaller/Types/BoolType.php b/lib/Weasel/JsonMarshaller/Types/BoolType.php deleted file mode 100644 index d3078b5..0000000 --- a/lib/Weasel/JsonMarshaller/Types/BoolType.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; -use Weasel\JsonMarshaller\JsonMapper; -use Weasel\JsonMarshaller\Exception\InvalidTypeException; - -class BoolType implements JsonType -{ - - public function decodeValue($value, JsonMapper $mapper, $strict) - { - if (is_bool($value)) { - return $value; - } - if ($value === "true" || $value === 1) { - return true; - } - if ($value === "false" || $value === 0) { - return false; - } - throw new InvalidTypeException("boolean", $value); - } - - public function encodeValue($value, JsonMapper $mapper) - { - if (!is_bool($value)) { - throw new InvalidTypeException("boolean", $value); - } - return ((bool)$value) ? "true" : "false"; - } - -} diff --git a/lib/Weasel/JsonMarshaller/Types/DateTimeType.php b/lib/Weasel/JsonMarshaller/Types/DateTimeType.php deleted file mode 100644 index 4b2deff..0000000 --- a/lib/Weasel/JsonMarshaller/Types/DateTimeType.php +++ /dev/null @@ -1,53 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; -use Weasel\JsonMarshaller\JsonMapper; -use Exception; -use DateTime; -use Weasel\JsonMarshaller\Exception\InvalidTypeException; - -class DateTimeType implements JsonType -{ - - protected $dateTimeFormat; - - public function __construct($dateTimeFormat = DateTime::ISO8601) - { - $this->dateTimeFormat = $dateTimeFormat; - } - - public function decodeValue($value, JsonMapper $mapper, $strict) - { - if (!is_string($value)) { - throw new InvalidTypeException('date string', $value); - } - try { - $retval = DateTime::createFromFormat($this->dateTimeFormat, $value); - if ($retval !== false) { - return $retval; - } - } catch (Exception $e) { - throw new InvalidTypeException('date string', $value, 0, $e); - } - throw new InvalidTypeException('date string', $value); - } - - /** - * @param \DateTime $value - * @param \Weasel\JsonMarshaller\JsonMapper $mapper - * @throws \Weasel\JsonMarshaller\Exception\InvalidTypeException - * @return string - */ - public function encodeValue($value, JsonMapper $mapper) - { - if (!$value instanceof DateTime) { - throw new InvalidTypeException('\DateTime', $value); - } - return json_encode($value->format($this->dateTimeFormat)); - } - -} diff --git a/lib/Weasel/JsonMarshaller/Types/FloatType.php b/lib/Weasel/JsonMarshaller/Types/FloatType.php deleted file mode 100644 index b4f1e28..0000000 --- a/lib/Weasel/JsonMarshaller/Types/FloatType.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; -use Weasel\JsonMarshaller\JsonMapper; -use Weasel\JsonMarshaller\Exception\InvalidTypeException; - -class FloatType implements JsonType -{ - - protected function checkAndCast($value) - { - if (!is_numeric($value)) { - throw new InvalidTypeException("float", $value); - } - return (float)($value + 0); - } - - public function decodeValue($value, JsonMapper $mapper, $strict) - { - if ($strict) { - if (!is_int($value) && !is_double($value)) { - throw new InvalidTypeException("float", $value); - } - } - return $this->checkAndCast($value); - } - - public function encodeValue($value, JsonMapper $mapper) - { - return json_encode($this->checkAndCast($value)); - } - -} diff --git a/lib/Weasel/JsonMarshaller/Types/IntType.php b/lib/Weasel/JsonMarshaller/Types/IntType.php deleted file mode 100644 index b692d05..0000000 --- a/lib/Weasel/JsonMarshaller/Types/IntType.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; -use Weasel\JsonMarshaller\JsonMapper; -use Weasel\JsonMarshaller\Exception\InvalidTypeException; - -class IntType implements JsonType -{ - - protected function checkAndCastValue($value) - { - if (!is_numeric($value)) { - throw new InvalidTypeException("integer", $value); - } - $intval = (int)($value + 0); - if ($intval != $value) { - throw new InvalidTypeException("integer", $value); - } - return $intval; - } - - public function decodeValue($value, JsonMapper $mapper, $strict) - { - if ($strict) { - if (!is_int($value)) { - throw new InvalidTypeException("integer", $value); - } - } - return $this->checkAndCastValue($value); - } - - public function encodeValue($value, JsonMapper $mapper) - { - return json_encode($this->checkAndCastValue($value)); - } - -} diff --git a/lib/Weasel/JsonMarshaller/Types/JsonType.php b/lib/Weasel/JsonMarshaller/Types/JsonType.php deleted file mode 100644 index e2ead44..0000000 --- a/lib/Weasel/JsonMarshaller/Types/JsonType.php +++ /dev/null @@ -1,30 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; -use Weasel\JsonMarshaller\JsonMapper; -use Weasel\JsonMarshaller\Exception\InvalidTypeException; - -interface JsonType -{ - /** - * Deserialize something to its PHP type. - * @param mixed $value - * @param \Weasel\JsonMarshaller\JsonMapper $mapper - * @param bool $strict Apply strict checking of input values. - * @return mixed - */ - public function decodeValue($value, JsonMapper $mapper, $strict); - - /** - * Serialize a PHP value to Json. - * @param $value - * @param \Weasel\JsonMarshaller\JsonMapper $mapper - * @return string - */ - public function encodeValue($value, JsonMapper $mapper); - -} diff --git a/lib/Weasel/JsonMarshaller/Types/OldTypeWrapper.php b/lib/Weasel/JsonMarshaller/Types/OldTypeWrapper.php deleted file mode 100644 index 2c98d78..0000000 --- a/lib/Weasel/JsonMarshaller/Types/OldTypeWrapper.php +++ /dev/null @@ -1,29 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; -use Weasel\JsonMarshaller\JsonMapper; - -class OldTypeWrapper implements JsonType -{ - - protected $_oldType; - - public function __construct(Type $oldType) - { - $this->_oldType = $oldType; - } - - public function decodeValue($value, JsonMapper $mapper, $strict) - { - return $this->_oldType->decodeValue($value, $mapper); - } - - public function encodeValue($value, JsonMapper $mapper) - { - return json_encode($this->_oldType->encodeValue($value, $mapper)); - } -} diff --git a/lib/Weasel/JsonMarshaller/Types/StringType.php b/lib/Weasel/JsonMarshaller/Types/StringType.php deleted file mode 100644 index 59605f3..0000000 --- a/lib/Weasel/JsonMarshaller/Types/StringType.php +++ /dev/null @@ -1,32 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; -use Weasel\JsonMarshaller\JsonMapper; -use Weasel\JsonMarshaller\Exception\InvalidTypeException; - -class StringType implements JsonType -{ - - protected function checkAndCastValue($value) - { - return (string)("" . $value); - } - - public function decodeValue($value, JsonMapper $mapper, $strict) - { - if ($strict && !is_string($value)) { - throw new InvalidTypeException("string", $value); - } - return $this->checkAndCastValue($value); - } - - public function encodeValue($value, JsonMapper $mapper) - { - return json_encode($this->checkAndCastValue($value)); - } - -} diff --git a/lib/Weasel/JsonMarshaller/Types/Type.php b/lib/Weasel/JsonMarshaller/Types/Type.php deleted file mode 100644 index 741c5da..0000000 --- a/lib/Weasel/JsonMarshaller/Types/Type.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; -use Weasel\JsonMarshaller\JsonMapper; -use Weasel\JsonMarshaller\Exception\InvalidTypeException; - - -/** - * @Deprecated - * Custom types should extend JsonType, not this. - */ -interface Type -{ - /** - * Deserialize something to its PHP type. - * @param mixed $value - * @param \Weasel\JsonMarshaller\JsonMapper $mapper - * @return mixed - */ - public function decodeValue($value, JsonMapper $mapper); - - /** - * Serialize a PHP value. - * @param $value - * @param \Weasel\JsonMarshaller\JsonMapper $mapper - * @return string - */ - public function encodeValue($value, JsonMapper $mapper); - -} diff --git a/lib/Weasel/WeaselDefaultAnnotationDrivenFactory.php b/lib/Weasel/WeaselDefaultAnnotationDrivenFactory.php deleted file mode 100644 index 46e4f97..0000000 --- a/lib/Weasel/WeaselDefaultAnnotationDrivenFactory.php +++ /dev/null @@ -1,181 +0,0 @@ -setCache(new ArrayCache()); - $this->_strict = $strict; - } - - /** - * @return AnnotationConfigurator - */ - public function getAnnotationConfigProviderInstance() - { - if (!isset($this->_configurator)) { - $configurator = new AnnotationConfigurator(); - $this->_autowire($configurator); - $this->_configurator = $configurator; - } - return $this->_configurator; - } - - /** - * @return Annotation\AnnotationReaderFactory - */ - public function getAnnotationReaderFactoryInstance() - { - if (!isset($this->_annotationReaderFactory)) { - $factory = new AnnotationReaderFactory($this->getAnnotationConfigProviderInstance()); - $this->_autowire($factory); - $this->_annotationReaderFactory = $factory; - } - return $this->_annotationReaderFactory; - } - - /** - * @return XmlAnnotationDriver - */ - public function getXmlDriverInstance() - { - if (!isset($this->_xmlDriver)) { - $driver = new XmlAnnotationDriver($this->getAnnotationReaderFactoryInstance()); - $this->_autowire($driver); - $this->_xmlDriver = $driver; - } - return $this->_xmlDriver; - } - - /** - * @return XmlMarshaller\XmlMapper - */ - public function getXmlMapperInstance() - { - if (!isset($this->_xmlMapper)) { - $this->_xmlMapper = new XmlMapper($this->getXmlDriverInstance()); - } - return $this->_xmlMapper; - } - - /** - * @return JsonAnnotationDriver - */ - public function getJsonDriverInstance() - { - if (!isset($this->_jsonDriver)) { - $driver = new JsonAnnotationDriver($this->getAnnotationReaderFactoryInstance()); - $this->_autowire($driver); - $this->_jsonDriver = $driver; - } - return $this->_jsonDriver; - } - - /** - * @return JsonMarshaller\JsonMapper - */ - public function getJsonMapperInstance() - { - if (!isset($this->_jsonMapper)) { - $this->_jsonMapper = new JsonMapper($this->getJsonDriverInstance(), $this->_strict); - } - return $this->_jsonMapper; - } - - protected function _autowire($object) - { - $this->_configureLogger($object); - $this->_configureCache($object); - } - - protected function _configureLogger($object) - { - if ($object instanceof LoggerAwareInterface) { - if (isset($this->_logger)) { - $object->setLogger($this->_logger); - } - } - } - - protected function _configureCache($object) - { - if ($object instanceof CacheAwareInterface) { - if (isset($this->_cache)) { - $object->setCache($this->_cache); - } - } - } - - /** - * Sets a logger instance on the object - * - * @param LoggerInterface $logger - * @return null - */ - public function setLogger(LoggerInterface $logger) - { - $this->_logger = $logger; - } - - public function setCache(Cache $cache) - { - $this->_cache = $cache; - } -} diff --git a/lib/Weasel/WeaselDoctrineAnnotationDrivenFactory.php b/lib/Weasel/WeaselDoctrineAnnotationDrivenFactory.php deleted file mode 100644 index c5c350d..0000000 --- a/lib/Weasel/WeaselDoctrineAnnotationDrivenFactory.php +++ /dev/null @@ -1,197 +0,0 @@ -setCache(new ArrayCache()); - $this->_strict = $strict; - } - - /** - * @return AnnotationReader - */ - public function getDoctrineAnnotationReaderInstance() - { - if (!isset($this->annotationReader)) { - $reader = new AnnotationReader(); - if (isset($this->_cache)) { - $reader = new CachedReader($reader, new WeaselCacheAdapter($this->_cache)); - } - $this->_autowire($reader); - $this->annotationReader = $reader; - } - return $this->annotationReader; - } - - /** - * @return Annotation\AnnotationReaderFactory - */ - public function getAnnotationReaderFactoryInstance() - { - if (!isset($this->_annotationReaderFactory)) { - $factory = new DoctrineAnnotationReaderFactory($this->getDoctrineAnnotationReaderInstance()); - $this->_autowire($factory); - $this->_annotationReaderFactory = $factory; - } - return $this->_annotationReaderFactory; - } - - /** - * @return JsonAnnotationDriver - */ - public function getJsonDriverInstance() - { - if (!isset($this->_jsonDriver)) { - $driver = new JsonAnnotationDriver($this->getAnnotationReaderFactoryInstance()); - $driver->setAnnotationNamespace('\Weasel\JsonMarshaller\Config\DoctrineAnnotations'); - $this->_autowire($driver); - $this->_jsonDriver = $driver; - } - return $this->_jsonDriver; - } - - /** - * @return JsonMarshaller\JsonMapper - */ - public function getJsonMapperInstance() - { - if (!isset($this->_jsonMapper)) { - $this->_jsonMapper = new JsonMapper($this->getJsonDriverInstance(), $this->_strict); - } - return $this->_jsonMapper; - } - - protected function _autowire($object) - { - $this->_configureLogger($object); - $this->_configureCache($object); - } - - protected function _configureLogger($object) - { - if ($object instanceof LoggerAwareInterface) { - if (isset($this->_logger)) { - $object->setLogger($this->_logger); - } - } - } - - protected function _configureCache($object) - { - if ($object instanceof CacheAwareInterface) { - if (isset($this->_cache)) { - $object->setCache($this->_cache); - } - } - } - - /** - * Sets a logger instance on the object. - * This logger will be passed into any LoggerAware instances created by this class. - * - * @param LoggerInterface $logger - * @return null - */ - public function setLogger(LoggerInterface $logger) - { - $this->_logger = $logger; - } - - /** - * Sets a cache instance on the object. - * This cache will be passed into any CacheAware instances created by this class. - * @param Cache $cache - */ - public function setCache(Cache $cache) - { - $this->_cache = $cache; - } - - /** - * @return XmlAnnotationDriver - */ - public function getXmlDriverInstance() - { - if (!isset($this->_xmlDriver)) { - $driver = new XmlAnnotationDriver($this->getAnnotationReaderFactoryInstance()); - $driver->setAnnotationNamespace('\Weasel\XmlMarshaller\Config\DoctrineAnnotations'); - $this->_autowire($driver); - $this->_xmlDriver = $driver; - } - return $this->_xmlDriver; - } - - /** - * @return XmlMapper - */ - public function getXmlMapperInstance() - { - if (!isset($this->_xmlMapper)) { - $this->_xmlMapper = new XmlMapper($this->getXmlDriverInstance()); - } - return $this->_xmlMapper; - } -} diff --git a/lib/Weasel/WeaselFactory.php b/lib/Weasel/WeaselFactory.php deleted file mode 100644 index bca8a7a..0000000 --- a/lib/Weasel/WeaselFactory.php +++ /dev/null @@ -1,30 +0,0 @@ -_jsonConfigFile = $jsonConfigFile; - $this->_xmlConfigFile = $xmlConfigFile; - $this->setCache(new ArrayCache()); - } - - private function _getJsonConfigMapper() - { - return new JsonMapper(new SerializedConfigProvider(__DIR__ . '/JsonMarshaller/Config/bootstrap.cnf')); - } - - /** - * @return JsonConfigProvider - */ - private function _getJsonConfigDriver() - { - $mapper = $this->_getJsonConfigMapper(); - $configString = file_get_contents($this->_jsonConfigFile); - $config = $mapper->readString($configString, '\Weasel\JsonMarshaller\Config\ClassMarshaller[string]'); - return new JsonPropertyConfigProvider($config); - } - - /** - * @return ConfigProvider - */ - private function _getXmlConfigDriver() - { - $mapper = $this->_getJsonConfigMapper(); - $configString = file_get_contents($this->_xmlConfigFile); - $config = $mapper->readString($configString, '\Weasel\XmlMarshaller\Config\ClassMarshaller[string]'); - return new XmlPropertyConfigProvider($config); - } - - /** - * @return JsonMarshaller\JsonMapper - */ - public function getJsonMapperInstance() - { - if (!isset($this->_jsonMapper)) { - $this->_jsonMapper = new JsonMapper($this->_getJsonConfigDriver()); - } - return $this->_jsonMapper; - } - - protected function _autowire($object) - { - $this->_configureLogger($object); - $this->_configureCache($object); - } - - protected function _configureLogger($object) - { - if ($object instanceof LoggerAwareInterface) { - if (isset($this->_logger)) { - $object->setLogger($this->_logger); - } - } - } - - protected function _configureCache($object) - { - if ($object instanceof CacheAwareInterface) { - if (isset($this->_cache)) { - $object->setCache($this->_cache); - } - } - } - - /** - * Sets a logger instance on the object. - * This logger will be passed into any LoggerAware instances created by this class. - * - * @param LoggerInterface $logger - * @return null - */ - public function setLogger(LoggerInterface $logger) - { - $this->_logger = $logger; - } - - /** - * Sets a cache instance on the object. - * This cache will be passed into any CacheAware instances created by this class. - * @param Cache $cache - */ - public function setCache(Cache $cache) - { - $this->_cache = $cache; - } - - /** - * Get a fully configured XmlMapper instance. - * @return XmlMapper - */ - public function getXmlMapperInstance() - { - if (!isset($this->_xmlMapper)) { - $this->_xmlMapper = new XmlMapper($this->_getXmlConfigDriver()); - } - return $this->_xmlMapper; - } -} diff --git a/lib/Weasel/XmlMarshaller/Config/AnnotationDriver.php b/lib/Weasel/XmlMarshaller/Config/AnnotationDriver.php deleted file mode 100644 index 4ee6632..0000000 --- a/lib/Weasel/XmlMarshaller/Config/AnnotationDriver.php +++ /dev/null @@ -1,93 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config; - -use Weasel\XmlMarshaller\Config\Annotations as Annotations; -use Weasel\Annotation\AnnotationConfigurator; -use Weasel\Common\Cache\CacheAwareInterface; -use Weasel\Common\Cache\Cache; -use Weasel\Common\Annotation\IAnnotationReaderFactory; - -class AnnotationDriver implements ConfigProvider, CacheAwareInterface -{ - - protected $classPaths = array(); - - protected $annotationNamespace = '\Weasel\XmlMarshaller\Config\Annotations'; - - /** - * @var \Weasel\Common\Annotation\IAnnotationReaderFactory - */ - public $annotationReaderFactory; - - /** - * @var \Weasel\Common\Cache\Cache - */ - protected $cache; - - public function __construct(IAnnotationReaderFactory $annotationReaderFactory) - { - $this->annotationReaderFactory = $annotationReaderFactory; - } - - /** - * @param string $class - * @return \Weasel\XmlMarshaller\Config\ClassMarshaller - */ - public function getConfig($class) - { - $key = strtolower($class); - if (isset($this->cache)) { - $found = false; - $cached = $this->cache->get($key, "XmlConfig", $found); - if ($found) { - return $cached; - } - } - $config = $this->_getConfig($class); - - if (isset($this->cache)) { - $this->cache->set($key, $config, "XmlConfig"); - } - return $config; - } - - /** - * @param string $class - * @return \Weasel\XmlMarshaller\Config\ClassMarshaller - */ - protected function _getConfig($class) - { - $rClass = new \ReflectionClass($class); - - $classDriver = new ClassAnnotationDriver($rClass, $this->annotationReaderFactory, $this->annotationNamespace); - - return $classDriver->getConfig(); - - } - - public function setCache(Cache $cache) - { - $this->cache = $cache; - } - - /** - * @param \Weasel\Common\Annotation\IAnnotationReaderFactory $annotationReaderFactory - */ - public function setAnnotationReaderFactory(IAnnotationReaderFactory $annotationReaderFactory) - { - $this->annotationReaderFactory = $annotationReaderFactory; - } - - /** - * @param string $annotationNamespace - */ - public function setAnnotationNamespace($annotationNamespace) - { - $this->annotationNamespace = $annotationNamespace; - } -} diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlAttribute.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlAttribute.php deleted file mode 100644 index 6b638a3..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlAttribute.php +++ /dev/null @@ -1,65 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlAttribute; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation(on={"property", "method"}) - */ -class XmlAttribute extends NoUndeclaredProperties implements IXmlAttribute -{ - - protected $name; - protected $type; - protected $namespace; - protected $required; - - /** - * @param string $name - * @param string $type - * @param string $namespace - * @param bool $required - * @AnnotationCreator({@Parameter(name="name", type="string", required=false), - @Parameter(name="type", type="string", required=false), - @Parameter(name="namespace", type="string", required=false), - @Parameter(name="required", type="bool", required=false)}) - */ - public function __construct($name = null, $type = null, $namespace = null, $required = null) - { - $this->name = isset($name) ? $name : null; - $this->type = isset($type) ? $type : "string"; - $this->namespace = isset($namespace) ? $namespace : null; - $this->required = isset($required) && $required; - } - - public function getName() - { - return $this->name; - } - - public function getType() - { - return $this->type; - } - - public function getNamespace() - { - return $this->namespace; - } - - public function getRequired() - { - return $this->required; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminator.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminator.php deleted file mode 100644 index c1251fd..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminator.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlDiscriminator; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation(on={"class"}) - */ -class XmlDiscriminator extends NoUndeclaredProperties implements IXmlDiscriminator -{ - - /** - * @var string - */ - protected $value; - - /** - * @param string $value; - * @AnnotationCreator({@Parameter(name="value", type="string", required=true)}) - */ - public function __construct($value = null) - { - $this->value = $value; - } - - /** - * @return string - */ - public function getValue() - { - return $this->value; - } - - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminatorValue.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminatorValue.php deleted file mode 100644 index 26e9a8b..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminatorValue.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlDiscriminatorValue; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation(on={"class"}) - */ -class XmlDiscriminatorValue extends NoUndeclaredProperties implements IXmlDiscriminatorValue -{ - - /** - * @var string - */ - protected $value; - - /** - * @param string $value; - * @AnnotationCreator({@Parameter(name="value", type="string", required=true)}) - */ - public function __construct($value = null) - { - $this->value = $value; - } - - /** - * @return string - */ - public function getValue() - { - return $this->value; - } - - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElement.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElement.php deleted file mode 100644 index b9c0597..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElement.php +++ /dev/null @@ -1,74 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElement; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation(on={"property", "method"}) - */ -class XmlElement extends NoUndeclaredProperties implements IXmlElement -{ - - protected $name; - protected $type; - protected $namespace; - protected $required; - protected $nillable; - - /** - * @param string $name - * @param string $type - * @param $nillable - * @param string $namespace - * @param bool $required - * @AnnotationCreator({@Parameter(name="name", type="string", required=false), - @Parameter(name="type", type="string", required=false), - @Parameter(name="nillable", type="bool", required=false), - @Parameter(name="namespace", type="string", required=false), - @Parameter(name="required", type="bool", required=false)}) - */ - public function __construct($name = null, $type = null, $nillable = null, $namespace = null, $required = null) - { - $this->name = isset($name) ? $name : null; - $this->type = isset($type) ? $type : "string"; - $this->namespace = isset($namespace) ? $namespace : null; - $this->required = isset($required) && $required; - $this->nillable = isset($nillable) && $nillable; - } - - public function getName() - { - return $this->name; - } - - public function getType() - { - return $this->type; - } - - public function getNamespace() - { - return $this->namespace; - } - - public function getRequired() - { - return $this->required; - } - - public function getNillable() - { - return $this->nillable; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRef.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRef.php deleted file mode 100644 index 169cbc0..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRef.php +++ /dev/null @@ -1,56 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRef; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation(on={"property", "method", "\Weasel\XmlMarshaller\Config\Annotations\XmlElementRefs"}) - */ -class XmlElementRef extends NoUndeclaredProperties implements IXmlElementRef -{ - - protected $name; - protected $type; - protected $namespace; - - /** - * @param string $name - * @param string $type - * @param string $namespace - * @AnnotationCreator({@Parameter(name="name", type="string", required=false), - @Parameter(name="type", type="string", required=true), - @Parameter(name="namespace", type="string", required=false)}) - */ - public function __construct($name = null, $type = null, $namespace = null) - { - $this->name = isset($name) ? $name : null; - $this->type = isset($type) ? $type : null; - $this->namespace = isset($namespace) ? $namespace : null; - } - - public function getName() - { - return $this->name; - } - - public function getType() - { - return $this->type; - } - - public function getNamespace() - { - return $this->namespace; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRefs.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRefs.php deleted file mode 100644 index d0142ba..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRefs.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRefs; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation(on={"property", "method"}) - */ -class XmlElementRefs extends NoUndeclaredProperties implements IXmlElementRefs -{ - - protected $values; - protected $type; - - /** - * @param \Weasel\XmlMarshaller\Config\Annotations\XmlElementRef[] $values - * @param string $type - * @AnnotationCreator({@Parameter(name="type", type="string", required=true), @Parameter(name="values", type="\Weasel\XmlMarshaller\Config\Annotations\XmlElementRef[]", required=true)}) - */ - public function __construct($type = null, array $values = array()) - { - $this->values = $values; - $this->type = $type; - } - - public function getValues() - { - return $this->values; - } - - public function getType() - { - return $this->type; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementWrapper.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementWrapper.php deleted file mode 100644 index a7bf256..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementWrapper.php +++ /dev/null @@ -1,65 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementWrapper; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation(on={"property", "method"}) - */ -class XmlElementWrapper extends NoUndeclaredProperties implements IXmlElementWrapper -{ - - protected $name; - protected $namespace; - protected $required; - protected $nillable; - - /** - * @param string $name - * @param $nillable - * @param string $namespace - * @param bool $required - * @AnnotationCreator({@Parameter(name="name", type="string", required=false), - @Parameter(name="nillable", type="bool", required=false), - @Parameter(name="namespace", type="string", required=false), - @Parameter(name="required", type="bool", required=false)}) - */ - public function __construct($name = null, $nillable = null, $namespace = null, $required = null) - { - $this->name = isset($name) ? $name : null; - $this->namespace = isset($namespace) ? $namespace : null; - $this->required = isset($required) && $required; - $this->nillable = isset($nillable) && $nillable; - } - - public function getName() - { - return $this->name; - } - - public function getNamespace() - { - return $this->namespace; - } - - public function getRequired() - { - return $this->required; - } - - public function getNillable() - { - return $this->nillable; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlRootElement.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlRootElement.php deleted file mode 100644 index f0e64f1..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlRootElement.php +++ /dev/null @@ -1,46 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlRootElement; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation(on={"class"}) - */ -class XmlRootElement extends NoUndeclaredProperties implements IXmlRootElement -{ - - protected $name; - protected $namespace; - - /** - * @param $name - * @param string $namespace - * @AnnotationCreator({@Parameter(name="name", type="string", required=false), @Parameter(name="namespace", type="string", required=false)}) - */ - public function __construct($name = null, $namespace = null) - { - $this->name = $name; - $this->namespace = $namespace; - } - - public function getName() - { - return $this->name; - } - - public function getNamespace() - { - return $this->namespace; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlSeeAlso.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlSeeAlso.php deleted file mode 100644 index 2274ede..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlSeeAlso.php +++ /dev/null @@ -1,42 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlSeeAlso; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * The list of subtypes of this base class - * @Annotation(on={"class"}) - */ -class XmlSeeAlso extends NoUndeclaredProperties implements IXmlSeeAlso -{ - - protected $value; - - /** - * @param string[] $value - * @AnnotationCreator({@Parameter(name="value", type="string[]", required=true)}) - */ - public function __construct($value = null) - { - $this->value = $value; - } - - /** - * @return string[] - */ - public function getValue() - { - return $this->value; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlType.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlType.php deleted file mode 100644 index 6e8bbeb..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlType.php +++ /dev/null @@ -1,105 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Annotations; - -use Weasel\Annotation\Config\Annotations\Annotation; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlType; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation(on={"property", "method", "class"}) - */ -class XmlType extends NoUndeclaredProperties implements IXmlType -{ - - /** - * @var string - */ - protected $factoryClass; - - /** - * @var string - */ - protected $factoryMethod; - - /** - * @var string - */ - protected $name; - - /** - * @var string - */ - protected $namespace; - - /** - * @var string[] - */ - protected $propOrder; - - /** - * @param string $factoryClass - * @param string $factoryMethod - * @param string $name - * @param string $namespace - * @param string[] $propOrder - * @AnnotationCreator({@Parameter(name="factoryClass", type="string", required=false), - @Parameter(name="factoryMethod", type="string", required=false), - @Parameter(name="name", type="string", required=false), - @Parameter(name="namespace", type="string", required=false), - @Parameter(name="propOrder", type="string[]", required=false)}) - */ - public function __construct($factoryClass = null, $factoryMethod = null, $name = null, $namespace = null, $propOrder = null) - { - $this->factoryClass = $factoryClass; - $this->factoryMethod = $factoryMethod; - $this->name = $name; - $this->namespace = $namespace; - $this->propOrder = empty($propOrder) ? null : $propOrder; - } - - /** - * @return string - */ - public function getFactoryClass() - { - return $this->factoryClass; - } - - /** - * @return string - */ - public function getFactoryMethod() - { - return $this->factoryMethod; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * @return string - */ - public function getNamespace() - { - return $this->namespace; - } - - public function getPropOrder() - { - return $this->propOrder; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/ClassAnnotationDriver.php b/lib/Weasel/XmlMarshaller/Config/ClassAnnotationDriver.php deleted file mode 100644 index 9ad130b..0000000 --- a/lib/Weasel/XmlMarshaller/Config/ClassAnnotationDriver.php +++ /dev/null @@ -1,448 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config; - -use Weasel\XmlMarshaller\Config\Annotations as Annotations; -use Weasel\XmlMarshaller\Config as Config; -use Weasel\Annotation\AnnotationReader; -use Psr\Log\LoggerAwareInterface; -use Psr\Log\LoggerInterface; -use Weasel\Annotation\AnnotationReaderFactory; -use Weasel\Annotation\AnnotationConfigurator; -use Weasel\Common\Annotation\IAnnotationReaderFactory; - -class ClassAnnotationDriver implements LoggerAwareInterface -{ - /** - * @var \Weasel\Common\Annotation\IAnnotationReader - */ - protected $annotationReader; - - /** - * @var \Weasel\Annotation\AnnotationReaderFactory - */ - protected $annotationReaderFactory; - - /** - * @var \ReflectionClass - */ - protected $rClass; - - /** - * @var \Weasel\Annotation\AnnotationConfigurator - */ - protected $configurator; - - /** - * @var ClassMarshaller - */ - protected $config; - - /** - * @var string - */ - protected $annotationNamespace = '\Weasel\XmlMarshaller\Config\Annotations\\'; - - /** - * @param \ReflectionClass $rClass A reflection for the class we're configuring - * @param \Weasel\Common\Annotation\IAnnotationReaderFactory $annotationReaderFactory A factory for annotation readers - * @param string $annotationNamespace namespace in which we can find the annotations. - */ - public function __construct(\ReflectionClass $rClass, IAnnotationReaderFactory $annotationReaderFactory, $annotationNamespace = '\Weasel\XmlMarshaller\Config\Annotations') - { - $this->annotationReaderFactory = $annotationReaderFactory; - $this->rClass = $rClass; - $this->annotationNamespace = $annotationNamespace . '\\'; - } - - /** - * @return AnnotationReader - */ - public function getAnnotationReader() - { - if (!isset($this->annotationReader)) { - $this->annotationReader = $this->annotationReaderFactory->getReaderForClass($this->rClass); - } - return $this->annotationReader; - } - - protected function _configureSetter(\ReflectionMethod $method, $namespace) - { - $name = $method->getName(); - - $setterConfig = new Deserialization\SetterDeserialization(); - $setterConfig->method = $name; - $setterConfig->id = $method->getName(); - - /** - * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlAttribute $attributeConfig - */ - $attributeConfig = $this->getAnnotationReader()->getSingleMethodAnnotation($name, - $this->annotationNamespace . 'XmlAttribute'); - if (isset($attributeConfig)) { - $defaultName = lcfirst(substr($name, 3)); - $this->_configureAttributeDeserialization($attributeConfig, $setterConfig, $defaultName, $namespace); - return; - } - - $defaultName = ucfirst(substr($name, 3)); - - /** - * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElement $elementConfig - */ - $elementConfig = $this->getAnnotationReader()->getSingleMethodAnnotation($name, - $this->annotationNamespace . 'XmlElement'); - - if (isset($elementConfig)) { - $element = $this->_configureElementDeserialization($elementConfig, $setterConfig, $defaultName, $namespace); - } - - /** - * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRef $refConfig - */ - $refConfig = $this->getAnnotationReader()->getSingleMethodAnnotation($name, - $this->annotationNamespace . 'XmlElementRef'); - - if (isset($refConfig)) { - $element = $this->_configureElementRefDeserialization($refConfig, $setterConfig, $defaultName, $namespace); - } - - /** - * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRefs $refsConfig - */ - $refsConfig = $this->getAnnotationReader()->getSingleMethodAnnotation($name, - $this->annotationNamespace . 'XmlElementRefs'); - - if (isset($refsConfig)) { - $element = - $this->_configureElementRefsDeserialization($refsConfig, $setterConfig, $defaultName, $namespace); - } - - /** - * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementWrapper $wrapperConfig - */ - $wrapperConfig = $this->getAnnotationReader()->getSingleMethodAnnotation($name, - $this->annotationNamespace . 'XmlElementWrapper'); - if (isset($element) && isset($wrapperConfig)) { - $wrapper = new Config\Deserialization\ElementWrapper(); - // TODO locate real namespace - $wrapperNamespace = $wrapperConfig->getNamespace(); - if (!isset($wrapperNamespace)) { - $wrapperNamespace = $namespace; - } - $wrapperName = $wrapperConfig->getName(); - if (!isset($wrapperName)) { - $wrapperName = $defaultName; - } - - $wrapperFullName = (!empty($wrapperNamespace) ? $wrapperNamespace . ":" : "") . $wrapperName; - - $wrapper->name = $wrapperName; - $wrapper->namespace = $wrapperNamespace; - $wrapper->nillable = $wrapperConfig->getNillable(); - $wrapper->wraps = $element; - - if ($wrapperConfig->getRequired()) { - $this->config->deserialization->requiredElements[] = $setterConfig->id; - } - $this->config->deserialization->elementWrappers[$wrapperFullName] = $wrapper; - - } elseif (isset($element)) { - $this->config->deserialization->elements[] = $element; - } - - } - - protected function _configureElementRefDeserialization(IAnnotations\IXmlElementRef $annot, - Config\Deserialization\PropertyDeserialization $prop, - $defaultName, $defaultNamespace) - { - $elementConfig = new Config\Deserialization\ElementDeserialization(); - $prop->type = $annot->getType(); - $elementConfig->property = $prop; - - $elementConfig->ref = true; - - return $elementConfig; - } - - protected function _configureElementRefsDeserialization(IAnnotations\IXmlElementRefs $annot, - Config\Deserialization\PropertyDeserialization $prop, - $defaultName, $defaultNamespace) - { - $elementConfig = new Config\Deserialization\ElementDeserialization(); - $prop->type = $annot->getType(); - $elementConfig->property = $prop; - - $elementConfig->ref = true; - - $elementConfig->refNameToTypeMap = array(); - foreach ($annot->getValues() as $value) { - // TODO locate real namespace - $namespace = $value->getNamespace(); - if (!isset($namespace)) { - $namespace = $defaultNamespace; - } - $name = $value->getName(); - if (!isset($name)) { - $name = $defaultName; - } - $fullName = (!empty($namespace) ? $namespace . ":" : "") . $name; - $elementConfig->refNameToTypeMap[$fullName] = $value->getType(); - } - - return $elementConfig; - } - - protected function _configureElementDeserialization(IAnnotations\IXmlElement $annot, - Config\Deserialization\PropertyDeserialization $prop, - $defaultName, $defaultNamespace) - { - $elementConfig = new Config\Deserialization\ElementDeserialization(); - $prop->type = $annot->getType(); - $elementConfig->property = $prop; - $elementConfig->nillable = $annot->getNillable(); - - // TODO locate real namespace - $namespace = $annot->getNamespace(); - if (!isset($namespace)) { - $namespace = $defaultNamespace; - } - $name = $annot->getName(); - if (!isset($name)) { - $name = $defaultName; - } - - $elementConfig->name = $name; - $elementConfig->namespace = $namespace; - - if ($annot->getRequired()) { - $this->config->deserialization->requiredElements[] = $prop->id; - } - - return $elementConfig; - } - - protected function _configureAttributeDeserialization(IAnnotations\IXmlAttribute $annot, - Config\Deserialization\PropertyDeserialization $prop, - $defaultName, $defaultNamespace) - { - $attributeConfig = new Config\Deserialization\AttributeDeserialization(); - $prop->type = $annot->getType(); - $attributeConfig->property = $prop; - - // TODO locate real namespace - $namespace = $annot->getNamespace(); - if (!isset($namespace)) { - $namespace = $defaultNamespace; - } - $name = $annot->getName(); - if (!isset($name)) { - $name = $defaultName; - } - - $fullName = (!empty($namespace) ? $namespace . ":" : "") . $name; - - if ($annot->getRequired()) { - $this->config->deserialization->requiredAttributes[] = $prop->id; - } - - $this->config->deserialization->attributes[$fullName] = $attributeConfig; - } - - protected function _configureMethod(\ReflectionMethod $method, $namespace) - { - $name = $method->getName(); - if ($method->isStatic()) { -// $this->_configureCreator($method, $namespace); -// } elseif ($method->isConstructor()) { -// $this->_configureCreator($method, $namespace); -// } elseif (substr($name, 0, 3) === 'get') { -// $this->_configureGetter($method, $namespace); - } elseif (substr($name, 0, 3) === 'set') { - $this->_configureSetter($method, $namespace); - } - } - - protected function _configureProperty(\ReflectionProperty $property, $namespace) - { - $name = $property->getName(); - - $directConfig = new Deserialization\DirectDeserialization(); - $directConfig->property = $name; - $directConfig->id = '$' . $name; - - /** - * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlAttribute $attributeConfig - */ - $attributeConfig = $this->getAnnotationReader()->getSinglePropertyAnnotation($name, - $this->annotationNamespace . 'XmlAttribute'); - if (isset($attributeConfig)) { - $defaultName = lcfirst($name); - $this->_configureAttributeDeserialization($attributeConfig, $directConfig, $defaultName, $namespace); - return; - } - - $defaultName = ucfirst($name); - - /** - * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElement $elementConfig - */ - $elementConfig = $this->getAnnotationReader()->getSinglePropertyAnnotation($name, - $this->annotationNamespace . 'XmlElement'); - - if (isset($elementConfig)) { - $element = $this->_configureElementDeserialization($elementConfig, $directConfig, $defaultName, $namespace); - } - - /** - * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRef $refConfig - */ - $refConfig = $this->getAnnotationReader()->getSinglePropertyAnnotation($name, - $this->annotationNamespace . 'XmlElementRef'); - - if (isset($refConfig)) { - $element = $this->_configureElementRefDeserialization($refConfig, $directConfig, $defaultName, $namespace); - } - - /** - * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRefs $refsConfig - */ - $refsConfig = $this->getAnnotationReader()->getSinglePropertyAnnotation($name, - $this->annotationNamespace . 'XmlElementRefs'); - - if (isset($refConfig)) { - $element = - $this->_configureElementRefsDeserialization($refsConfig, $directConfig, $defaultName, $namespace); - } - - /** - * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementWrapper $wrapperConfig - */ - $wrapperConfig = $this->getAnnotationReader()->getSinglePropertyAnnotation($name, - $this->annotationNamespace . 'XmlElementWrapper'); - if (isset($element) && isset($wrapperConfig)) { - $wrapper = new Config\Deserialization\ElementWrapper(); - // TODO locate real namespace - $wrapperNamespace = $wrapperConfig->getNamespace(); - if (!isset($wrapperNamespace)) { - $wrapperNamespace = $namespace; - } - $wrapperName = $wrapperConfig->getName(); - if (!isset($wrapperName)) { - $wrapperName = $defaultName; - } - - $wrapperFullName = (!empty($wrapperNamespace) ? $wrapperNamespace . ":" : "") . $wrapperName; - - $wrapper->name = $wrapperName; - $wrapper->namespace = $wrapperNamespace; - $wrapper->nillable = $wrapperConfig->getNillable(); - $wrapper->wraps = $element; - - if ($wrapperConfig->getRequired()) { - $this->config->deserialization->requiredElements[] = $directConfig->id; - } - $this->config->deserialization->elementWrappers[$wrapperFullName] = $wrapper; - - } elseif (isset($element)) { - $this->config->deserialization->elements[] = $element; - } - - } - - public function getConfig() - { - - $this->config = new ClassMarshaller(); - $this->config->serialization = new Serialization\ClassSerialization(); - $this->config->deserialization = new Deserialization\ClassDeserialization(); - - /** - * @var IAnnotations\IXmlDiscriminatorValue $discrimValueA - */ - $discrimValueA = $this->getAnnotationReader()->getSingleClassAnnotation($this->annotationNamespace . 'XmlDiscriminatorValue'); - if (isset($discrimValueA)) { - $this->config->deserialization->discriminatorValue = $discrimValueA->getValue(); - } - - /** - * @var IAnnotations\IXmlDiscriminator $discrimA - */ - $discrimA = $this->getAnnotationReader()->getSingleClassAnnotation($this->annotationNamespace . 'XmlDiscriminator'); - if (isset($discrimA)) { - $this->config->deserialization->discriminator = $discrimA->getValue(); - } - - $name = $this->rClass->getName(); - $parts = explode('\\', $name); - $name = end($parts); - // TODO default namespace - $namespace = null; - - /** - * @var IAnnotations\IXmlType $xmlTypeA - */ - $xmlTypeA = $this->getAnnotationReader()->getSingleClassAnnotation($this->annotationNamespace . 'XmlType'); - if (isset($xmlTypeA)) { - // TODO work out wtf name and namespace mean. - - $factoryMethod = $xmlTypeA->getFactoryMethod(); - if (isset($factoryMethod)) { - $this->config->deserialization->factoryMethod = $factoryMethod; - $factoryClass = $xmlTypeA->getFactoryMethod(); - if (isset($factoryClass)) { - $this->config->deserialization->factoryClass = $factoryClass; - } - } - } - - /** - * @var IAnnotations\IXmlRootElement $rootA - */ - $rootA = $this->getAnnotationReader()->getSingleClassAnnotation($this->annotationNamespace . 'XmlRootElement'); - if (isset($rootA)) { - $name = ($rootA->getName() !== null) ? $rootA->getName() : $name; - $namespace = ($rootA->getNameSpace() !== null) ? $rootA->getNameSpace() : $namespace; - } - $this->config->deserialization->name = $name; - $this->config->deserialization->namespace = $namespace; - - /** - * @var IAnnotations\IXmlSeeAlso $seeAlsoA - */ - $seeAlsoA = $this->getAnnotationReader()->getSingleClassAnnotation($this->annotationNamespace . 'XmlSeeAlso'); - if (isset($seeAlsoA)) { - $this->config->deserialization->subClasses = $seeAlsoA->getValue(); - } - - $methods = $this->rClass->getMethods(\ReflectionMethod::IS_PUBLIC); - - foreach ($methods as $method) { - $this->_configureMethod($method, $namespace); - } - - $properties = $this->rClass->getProperties(\ReflectionProperty::IS_PUBLIC & ~\ReflectionProperty::IS_STATIC); - foreach ($properties as $property) { - $this->_configureProperty($property, $namespace); - } - - return $this->config; - - } - - /** - * Sets a logger instance on the object - * - * @param LoggerInterface $logger - * @return null - */ - public function setLogger(LoggerInterface $logger) - { - $this->annotationReaderFactory->setLogger($logger); - } -} diff --git a/lib/Weasel/XmlMarshaller/Config/ClassMarshaller.php b/lib/Weasel/XmlMarshaller/Config/ClassMarshaller.php deleted file mode 100644 index ba565d4..0000000 --- a/lib/Weasel/XmlMarshaller/Config/ClassMarshaller.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config; - -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class ClassMarshaller -{ - - /** - * @var \Weasel\XmlMarshaller\Config\Serialization\ClassSerialization - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Serialization\ClassSerialization") - */ - public $serialization; - - /** - * @var \Weasel\XmlMarshaller\Config\Deserialization\ClassDeserialization - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\ClassDeserialization") - */ - public $deserialization; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/ConfigProvider.php b/lib/Weasel/XmlMarshaller/Config/ConfigProvider.php deleted file mode 100644 index 1e92eb4..0000000 --- a/lib/Weasel/XmlMarshaller/Config/ConfigProvider.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config; - -interface ConfigProvider -{ - - /** - * @param string $class - * @return \Weasel\XmlMarshaller\Config\ClassMarshaller - */ - public function getConfig($class); - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/AttributeDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/AttributeDeserialization.php deleted file mode 100644 index 475134d..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Deserialization/AttributeDeserialization.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Deserialization; - -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class AttributeDeserialization -{ - - /** - * @var \Weasel\XmlMarshaller\Config\Deserialization\PropertyDeserialization - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\PropertyDeserialization") - */ - public $property; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/ClassDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/ClassDeserialization.php deleted file mode 100644 index 6b6018f..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Deserialization/ClassDeserialization.php +++ /dev/null @@ -1,85 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class ClassDeserialization -{ - - /** - * @var \Weasel\XmlMarshaller\Config\Deserialization\ElementDeserialization[] - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\ElementDeserialization[]") - */ - public $elements = array(); - - /** - * @var \Weasel\XmlMarshaller\Config\Deserialization\ElementWrapper[] - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\ElementWrapper[string]") - */ - public $elementWrappers = array(); - - /** - * @var \Weasel\XmlMarshaller\Config\Deserialization\AttributeDeserialization[] - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\AttributeDeserialization[string]") - */ - public $attributes = array(); - - /** - * @var string[] - * @JsonProperty(type="string[]") - */ - public $requiredElements = array(); - - /** - * @var string[] - * @JsonProperty(type="string[]") - */ - public $requiredAttributes = array(); - - /** - * @var string - * @JsonProperty(type="string") - */ - public $name; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $namespace; - - /** - * @var string[] - * @JsonProperty(type="string[]") - */ - public $subClasses; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $discriminator; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $discriminatorValue; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $factoryClass; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $factoryMethod; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/DirectDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/DirectDeserialization.php deleted file mode 100644 index a26973e..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Deserialization/DirectDeserialization.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class DirectDeserialization - * @package Weasel\XmlMarshaller\Config\Deserialization - * @JsonTypeName("direct") - */ -class DirectDeserialization extends PropertyDeserialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $property; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementDeserialization.php deleted file mode 100644 index a4e5d6d..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementDeserialization.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class ElementDeserialization -{ - - /** - * @var \Weasel\XmlMarshaller\Config\Deserialization\PropertyDeserialization - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\PropertyDeserialization") - */ - public $property; - - /** - * @var bool - * @JsonProperty(type="bool") - */ - public $nillable = false; - - /** - * @var bool - * @JsonProperty(type="bool") - */ - public $ref = false; - - /** - * @var string[] - * @JsonProperty(type="string[string]") - */ - public $refNameToTypeMap = null; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $name; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $namespace; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementWrapper.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementWrapper.php deleted file mode 100644 index bd4b113..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementWrapper.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class ElementWrapper -{ - - /** - * @var bool - * @JsonProperty(type="bool") - */ - public $nillable = false; - - - /** - * @var \Weasel\XmlMarshaller\Config\Deserialization\ElementDeserialization - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\ElementDeserialization") - */ - public $wraps; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $name; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $namespace; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/Param.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/Param.php deleted file mode 100644 index ab80258..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Deserialization/Param.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class Param - * @package Weasel\XmlMarshaller\Config\Deserialization - * @JsonTypeName("param") - */ -class Param extends PropertyDeserialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $name; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/PropertyDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/PropertyDeserialization.php deleted file mode 100644 index d7c0106..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Deserialization/PropertyDeserialization.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; - -/** - * Class PropertyDeserialization - * @package Weasel\XmlMarshaller\Config\Deserialization - * @JsonSubTypes({ - * @JsonSubTypes\Type("\Weasel\XmlMarshaller\Config\Deserialization\Param"), - * @JsonSubTypes\Type("\Weasel\XmlMarshaller\Config\Deserialization\SetterDeserialization"), - * @JsonSubTypes\Type("\Weasel\XmlMarshaller\Config\Deserialization\DirectDeserialization"), - * }) - * @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="how") - */ -abstract class PropertyDeserialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $id; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $type; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/SetterDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/SetterDeserialization.php deleted file mode 100644 index 2890c87..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Deserialization/SetterDeserialization.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class SetterDeserialization - * @package Weasel\XmlMarshaller\Config\Deserialization - * @JsonTypeName("setter") - */ -class SetterDeserialization extends PropertyDeserialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $method; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/TypeInfo.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/TypeInfo.php deleted file mode 100644 index 1207c8a..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Deserialization/TypeInfo.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Deserialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class TypeInfo -{ - const TI_USE_CLASS = 1; - const TI_USE_CUSTOM = 2; - const TI_USE_MINIMAL_CLASS = 3; - const TI_USE_NAME = 4; - const TI_USE_NONE = 5; - - const TI_AS_PROPERTY = 1; - const TI_AS_WRAPPER_OBJECT = 2; - const TI_AS_WRAPPER_ARRAY = 3; - const TI_AS_EXTERNAL_PROPERTY = 4; - - /** - * @var string[] - * @JsonProperty(type="string[]") - */ - public $subTypes; - - /** - * @var int - * @JsonProperty(type="int") - */ - public $typeInfo = self::TI_USE_NONE; - - /** - * @var int - * @JsonProperty(type="int") - */ - public $typeInfoAs = self::TI_AS_PROPERTY; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $defaultImpl; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $typeInfoProperty; - - /** - * @var bool - * @JsonProperty(type="bool") - */ - public $typeInfoVisible = false; -} diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlAttribute.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlAttribute.php deleted file mode 100644 index 85f75e1..0000000 --- a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlAttribute.php +++ /dev/null @@ -1,61 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlAttribute; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation - * @Target({"PROPERTY", "METHOD"}) - */ -class XmlAttribute extends NoUndeclaredProperties implements IXmlAttribute -{ - - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $type = "string"; - - /** - * @var string - */ - public $namespace; - - /** - * @var bool - */ - public $required = false; - - public function getName() - { - return $this->name; - } - - public function getType() - { - return $this->type; - } - - public function getNamespace() - { - return $this->namespace; - } - - public function getRequired() - { - return $this->required; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminator.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminator.php deleted file mode 100644 index 59f90a6..0000000 --- a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminator.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlDiscriminator; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation - * @Target({"CLASS"}) - */ -class XmlDiscriminator extends NoUndeclaredProperties implements IXmlDiscriminator -{ - - /** - * @var string - */ - public $value; - - /** - * @return string - */ - public function getValue() - { - return $this->value; - } - - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminatorValue.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminatorValue.php deleted file mode 100644 index b03784d..0000000 --- a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminatorValue.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlDiscriminatorValue; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation - * @Target({"CLASS"}) - */ -class XmlDiscriminatorValue extends NoUndeclaredProperties implements IXmlDiscriminatorValue -{ - - /** - * @var string - */ - public $value; - - /** - * @return string - */ - public function getValue() - { - return $this->value; - } - - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElement.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElement.php deleted file mode 100644 index 4a7185f..0000000 --- a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElement.php +++ /dev/null @@ -1,71 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElement; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation - * @Target({"PROPERTY", "METHOD"}) - */ -class XmlElement extends NoUndeclaredProperties implements IXmlElement -{ - - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $type = "string"; - - /** - * @var string - */ - public $namespace; - - /** - * @var bool - */ - public $required = false; - - /** - * @var bool - */ - public $nillable = false; - - public function getName() - { - return $this->name; - } - - public function getType() - { - return $this->type; - } - - public function getNamespace() - { - return $this->namespace; - } - - public function getRequired() - { - return $this->required; - } - - public function getNillable() - { - return $this->nillable; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRef.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRef.php deleted file mode 100644 index 903e039..0000000 --- a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRef.php +++ /dev/null @@ -1,51 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRef; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation - * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) - */ -class XmlElementRef extends NoUndeclaredProperties implements IXmlElementRef -{ - - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $type; - - /** - * @var string - */ - public $namespace; - - public function getName() - { - return $this->name; - } - - public function getType() - { - return $this->type; - } - - public function getNamespace() - { - return $this->namespace; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRefs.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRefs.php deleted file mode 100644 index 65b02de..0000000 --- a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRefs.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRefs; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation - * @Target({"PROPERTY", "METHOD"}) - */ -class XmlElementRefs extends NoUndeclaredProperties implements IXmlElementRefs -{ - - /** - * @var array - */ - public $values; - - /** - * @var string - */ - public $type; - - public function getValues() - { - return $this->values; - } - - public function getType() - { - return $this->type; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementWrapper.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementWrapper.php deleted file mode 100644 index 1cb2cee..0000000 --- a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementWrapper.php +++ /dev/null @@ -1,62 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementWrapper; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation - * @Target({"PROPERTY", "METHOD"}) - */ -class XmlElementWrapper extends NoUndeclaredProperties implements IXmlElementWrapper -{ - - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $namespace; - - /** - * @var bool - */ - public $required = false; - - /** - * @var bool - */ - public $nillable = false; - - - public function getName() - { - return $this->name; - } - - public function getNamespace() - { - return $this->namespace; - } - - public function getRequired() - { - return $this->required; - } - - public function getNillable() - { - return $this->nillable; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlRootElement.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlRootElement.php deleted file mode 100644 index 6d848d4..0000000 --- a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlRootElement.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlRootElement; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation - * @Target({"CLASS"}) - */ -class XmlRootElement extends NoUndeclaredProperties implements IXmlRootElement -{ - - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $namespace; - - public function getName() - { - return $this->name; - } - - public function getNamespace() - { - return $this->namespace; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlSeeAlso.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlSeeAlso.php deleted file mode 100644 index 93e59ad..0000000 --- a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlSeeAlso.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlSeeAlso; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * The list of subtypes of this base class - * @Annotation - * @Target({"CLASS"}) - */ -class XmlSeeAlso extends NoUndeclaredProperties implements IXmlSeeAlso -{ - - /** - * @var array - */ - public $value; - - /** - * @return string[] - */ - public function getValue() - { - return $this->value; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlType.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlType.php deleted file mode 100644 index a30dc1a..0000000 --- a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlType.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\Annotation; -use Weasel\XmlMarshaller\Config\IAnnotations\IXmlType; -use Weasel\Common\Utils\NoUndeclaredProperties; - -/** - * @Annotation - * @Target({"PROPERTY", "METHOD", "CLASS"}) - */ -class XmlType extends NoUndeclaredProperties implements IXmlType -{ - - /** - * @var string - */ - public $factoryClass; - - /** - * @var string - */ - public $factoryMethod; - - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $namespace; - - /** - * @var array - */ - public $propOrder; - - /** - * @return string - */ - public function getFactoryClass() - { - return $this->factoryClass; - } - - /** - * @return string - */ - public function getFactoryMethod() - { - return $this->factoryMethod; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * @return string - */ - public function getNamespace() - { - return $this->namespace; - } - - public function getPropOrder() - { - return $this->propOrder; - } - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlAttribute.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlAttribute.php deleted file mode 100644 index 32f1676..0000000 --- a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlAttribute.php +++ /dev/null @@ -1,19 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\IAnnotations; - -interface IXmlAttribute -{ - public function getName(); - - public function getType(); - - public function getNamespace(); - - public function getRequired(); -} - diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminator.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminator.php deleted file mode 100644 index 22a78b1..0000000 --- a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminator.php +++ /dev/null @@ -1,15 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\IAnnotations; - -interface IXmlDiscriminator -{ - - public function getValue(); - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminatorValue.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminatorValue.php deleted file mode 100644 index 0a96840..0000000 --- a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminatorValue.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\IAnnotations; - -interface IXmlDiscriminatorValue -{ - - /** - * @return string - */ - public function getValue(); - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElement.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElement.php deleted file mode 100644 index bfd17d6..0000000 --- a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElement.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\IAnnotations; - -interface IXmlElement -{ - - public function getName(); - - public function getType(); - - public function getNamespace(); - - public function getRequired(); - - public function getNillable(); - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRef.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRef.php deleted file mode 100644 index f2ca9f8..0000000 --- a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRef.php +++ /dev/null @@ -1,19 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\IAnnotations; - -interface IXmlElementRef -{ - - public function getName(); - - public function getType(); - - public function getNamespace(); - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRefs.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRefs.php deleted file mode 100644 index 4a3314d..0000000 --- a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRefs.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\IAnnotations; - -interface IXmlElementRefs -{ - - /** - * @return IXmlElementRef[] - */ - public function getValues(); - - public function getType(); - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementWrapper.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementWrapper.php deleted file mode 100644 index 642f83c..0000000 --- a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementWrapper.php +++ /dev/null @@ -1,21 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\IAnnotations; - -interface IXmlElementWrapper -{ - - public function getName(); - - public function getNamespace(); - - public function getRequired(); - - public function getNillable(); - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlRootElement.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlRootElement.php deleted file mode 100644 index 1bf5696..0000000 --- a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlRootElement.php +++ /dev/null @@ -1,17 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\IAnnotations; - -interface IXmlRootElement -{ - - public function getName(); - - public function getNamespace(); - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlSeeAlso.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlSeeAlso.php deleted file mode 100644 index b1791c8..0000000 --- a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlSeeAlso.php +++ /dev/null @@ -1,18 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\IAnnotations; - -interface IXmlSeeAlso -{ - - /** - * @return string[] - */ - public function getValue(); - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/XmlType.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/XmlType.php deleted file mode 100644 index 0950a11..0000000 --- a/lib/Weasel/XmlMarshaller/Config/IAnnotations/XmlType.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\IAnnotations; - -interface IXmlType -{ - - /** - * @return string - */ - public function getFactoryClass(); - - /** - * @return string - */ - public function getFactoryMethod(); - - /** - * @return string - */ - public function getName(); - - /** - * @return string - */ - public function getNamespace(); - - public function getPropOrder(); - -} - diff --git a/lib/Weasel/XmlMarshaller/Config/PropertyConfigProvider.php b/lib/Weasel/XmlMarshaller/Config/PropertyConfigProvider.php deleted file mode 100644 index 330e66d..0000000 --- a/lib/Weasel/XmlMarshaller/Config/PropertyConfigProvider.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ - -namespace Weasel\XmlMarshaller\Config; - -/** - * Class PropertyConfigProvider - * A really boring config provider which works off a public property containing a config object structure. - * This might be suitable for building a configuration from some DI framework or something. - * @package Weasel\XmlMarshaller\Config - */ -class PropertyConfigProvider implements ConfigProvider -{ - - /** - * @var ClassMarshaller[] Map of class names to ClassMarshallers - */ - public $config = array(); - - /** - * @param ClassMarshaller[] $config Map of class names to ClassMarshallers - */ - public function __construct(array $config = array()) - { - $this->config = $config; - } - - /** - * Obtain the config for a named class - * @param string $class The class to get the config for - * @return \Weasel\XmlMarshaller\Config\ClassMarshaller The config, or null if not found - */ - public function getConfig($class) - { - $class = ltrim($class, '\\'); - if (isset($this->config[$class])) { - return $this->config[$class]; - } - return null; - } -} \ No newline at end of file diff --git a/lib/Weasel/XmlMarshaller/Config/Serialization/ClassSerialization.php b/lib/Weasel/XmlMarshaller/Config/Serialization/ClassSerialization.php deleted file mode 100644 index 70fd48f..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Serialization/ClassSerialization.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Serialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class ClassSerialization -{ - - const INCLUDE_ALWAYS = 1; - const INCLUDE_NON_DEFAULT = 2; - const INCLUDE_NON_EMPTY = 3; - const INCLUDE_NON_NULL = 4; - - /** - * @var \Weasel\XmlMarshaller\Config\Serialization\PropertySerialization[] - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Serialization\PropertySerialization[string]") - */ - public $properties = array(); - - /** - * @var int - * @JsonProperty(type="int") - */ - public $include = self::INCLUDE_ALWAYS; - - /** - * @var \Weasel\XmlMarshaller\Config\Serialization\TypeInfo - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Serialization\TypeInfo") - */ - public $typeInfo; -} diff --git a/lib/Weasel/XmlMarshaller/Config/Serialization/DirectSerialization.php b/lib/Weasel/XmlMarshaller/Config/Serialization/DirectSerialization.php deleted file mode 100644 index 5fe499a..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Serialization/DirectSerialization.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Serialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class DirectSerialization - * @package Weasel\XmlMarshaller\Config\Serialization - * @JsonTypeName("direct") - */ -class DirectSerialization extends PropertySerialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $property; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Serialization/GetterSerialization.php b/lib/Weasel/XmlMarshaller/Config/Serialization/GetterSerialization.php deleted file mode 100644 index 6bb6270..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Serialization/GetterSerialization.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Serialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; - -/** - * Class GetterSerialization - * @package Weasel\XmlMarshaller\Config\Serialization - * @JsonTypeName("getter") - */ -class GetterSerialization extends PropertySerialization -{ - - /** - * @var string - * @JsonProperty(type="string") - */ - public $method; - -} diff --git a/lib/Weasel/XmlMarshaller/Config/Serialization/PropertySerialization.php b/lib/Weasel/XmlMarshaller/Config/Serialization/PropertySerialization.php deleted file mode 100644 index 42d7102..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Serialization/PropertySerialization.php +++ /dev/null @@ -1,41 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Serialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; - -/** - * Class PropertySerialization - * @package Weasel\XmlMarshaller\Config\Serialization - * @JsonSubTypes({ - * @JsonSubTypes\Type("\Weasel\XmlMarshaller\Config\Serialization\GetterSerialization"), - * @JsonSubTypes\Type("\Weasel\XmlMarshaller\Config\Serialization\DirectSerialization"), - * }) - * @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="how") - */ -class PropertySerialization -{ - - /** - * @var integer - * @JsonProperty(type="int") - */ - public $include; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $type; - - /** - * @var \Weasel\XmlMarshaller\Config\Serialization\TypeInfo - * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Serialization\TypeInfo") - */ - public $typeInfo; -} diff --git a/lib/Weasel/XmlMarshaller/Config/Serialization/TypeInfo.php b/lib/Weasel/XmlMarshaller/Config/Serialization/TypeInfo.php deleted file mode 100644 index 579c7b9..0000000 --- a/lib/Weasel/XmlMarshaller/Config/Serialization/TypeInfo.php +++ /dev/null @@ -1,47 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller\Config\Serialization; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; - -class TypeInfo -{ - const TI_USE_CLASS = 1; - const TI_USE_CUSTOM = 2; - const TI_USE_MINIMAL_CLASS = 3; - const TI_USE_NAME = 4; - const TI_USE_NONE = 5; - - const TI_AS_PROPERTY = 1; - const TI_AS_WRAPPER_OBJECT = 2; - const TI_AS_WRAPPER_ARRAY = 3; - const TI_AS_EXTERNAL_PROPERTY = 4; - - /** - * @var string[] - * @JsonProperty(type="string[]") - */ - public $subTypes; - - /** - * @var int - * @JsonProperty(type="int") - */ - public $typeInfo = self::TI_USE_NONE; - - /** - * @var int - * @JsonProperty(type="int") - */ - public $typeInfoAs = self::TI_AS_PROPERTY; - - /** - * @var string - * @JsonProperty(type="string") - */ - public $typeInfoProperty; - -} diff --git a/lib/Weasel/XmlMarshaller/XmlMapper.php b/lib/Weasel/XmlMarshaller/XmlMapper.php deleted file mode 100644 index 90b3126..0000000 --- a/lib/Weasel/XmlMarshaller/XmlMapper.php +++ /dev/null @@ -1,476 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\XmlMarshaller; - -use Weasel\XmlMarshaller\Config\ConfigProvider; - -class XmlMapper -{ - - /** - * @var \Weasel\XmlMarshaller\Config\ConfigProvider - */ - protected $configProvider; - - public function __construct(ConfigProvider $configProvider) - { - $this->configProvider = $configProvider; - } - - public function readString($string, $class) - { - $reader = new \XMLReader(); -// $reader->setParserProperty(\XMLReader::VALIDATE, true); - $reader->xml($string); - $ret = $this->readXml($reader, $class); - $reader->close(); - return $ret; - } - - public function readXml(\XmlReader $xml, $class) - { - $xml->read(); - - return $this->_readObject($xml, $class, true); - - // TODO check end of file? - } - - protected function _readObject(\XMLReader $xml, $class, $root = false) - { - $deConfig = $this->configProvider->getConfig($class)->deserialization; - if (!isset($deConfig)) { - throw new \Exception("No config count for $class"); - } - // TODO handle simple value objecty things (XmlValue) - - $ignorableAttributes = array(); - - if (!empty($deConfig->subClasses)) { - if (!empty($deConfig->discriminator)) { - if (substr($deConfig->discriminator, 0, 1) !== '@') { - throw new \Exception( - "Unsupported discriminator, currently only attributes (denoted with @) are supported. Found: " . - $deConfig->discriminator); - } - $discrimName = substr($deConfig->discriminator, 1); - $attrNS = ($xml->namespaceURI) ? $xml->namespaceURI . ':' : ''; - $ignorableAttributes[$attrNS . $discrimName] = true; - - $discrimValue = $xml->getAttribute($discrimName); - foreach ($deConfig->subClasses as $subClass) { - $subConfig = $this->configProvider->getConfig($subClass)->deserialization; - if ($subConfig->discriminatorValue == $discrimValue) { - $class = $subClass; - $deConfig = $subConfig; - break; - } - } - } elseif ($root && ($xml->name != $deConfig->name || $xml->namespaceURI != $deConfig->namespace)) { - $matchName = $xml->name; - $matchNS = $xml->namespaceURI; - - foreach ($deConfig->subClasses as $subClass) { - $subConfig = $this->configProvider->getConfig($subClass)->deserialization; - if ($subConfig->name == $matchName && $subConfig->namespace == $matchNS) { - $class = $subClass; - $deConfig = $subConfig; - break; - } - } - } - - } - - $fullName = $xml->namespaceURI . ':' . $xml->name; - - if ($root && ($xml->name != $deConfig->name || $xml->namespaceURI != $deConfig->namespace)) { - throw new \Exception("Unable to resolve root node for {$fullName}"); - } - - $creatorClass = $class; - if (!empty($deConfig->factoryClass)) { - $creatorClass = $deConfig->factoryClass; - } - - if (!empty($deConfig->factoryMethod)) { - $creatorMethod = $deConfig->factoryMethod; - $object = $creatorClass::$creatorMethod(); - } else { - $object = new $class(); - } - - $seenAttributes = array(); - $seenElements = array(); - - $namespace = $xml->namespaceURI; - - if ($xml->hasAttributes) { - while ($xml->moveToNextAttribute()) { - $attrNS = - (($xml->namespaceURI) ? $xml->namespaceURI . ':' : (isset($namespace) ? $namespace . ':' : '')); - $fullName = $attrNS . $xml->name; - if ($xml->name === 'xmlns') { - continue; - } - if (isset($ignorableAttributes[$fullName])) { - continue; - } - if (!isset($deConfig->attributes[$fullName])) { - throw new \Exception("Unknown attribute found in {$class}: {$fullName}"); - } - $val = $this->_readAttribute($xml, $deConfig->attributes[$fullName]); - $this->_setProperty($object, $deConfig->attributes[$fullName]->property, $val); - $seenAttributes[] = $deConfig->attributes[$fullName]->property->id; - } - $xml->moveToElement(); - } - - $knownValues = array(); - - if (!$xml->isEmptyElement) { - while (true) { - if (!$xml->read()) { - throw new \Exception("XML read error"); - } - switch ($xml->nodeType) { - case \XMLReader::ELEMENT: - list($propType, $val) = $this->_readElement($xml, $deConfig); - $seenElements[] = $propType->id; - if (is_array($val)) { - if (!isset($knownValues[$propType->id])) { - $knownValues[$propType->id] = - array($propType, - array() - ); - } - $knownValues[$propType->id][1] = array_merge($knownValues[$propType->id][1], $val); - } else { - $this->_setProperty($object, $propType, $val); - } - break; - case \XMLReader::END_ELEMENT: - break 2; - case \XMLReader::WHITESPACE: - case \XMLReader::COMMENT: - case \XMLReader::SIGNIFICANT_WHITESPACE: - break; - default: - throw new \Exception("XML Parsing error, found unexpected {$xml->nodeType} while parsing for {$class}"); - } - } - } - - $notSeenAtts = array_diff($deConfig->requiredAttributes, $seenAttributes); - $notSeenElements = array_diff($deConfig->requiredElements, $seenElements); - if (!empty($notSeenAtts) || !empty($notSeenElements)) { - // TODO fix. - throw new \Exception("Missing required elements: " . implode(', ', $notSeenElements) . " and attributes: " . - implode(',', $notSeenAtts) . "on $class"); - } - - foreach ($knownValues as $typeval) { - list ($property, $values) = $typeval; - $this->_setProperty($object, $property, $values); - } - - return $object; - - } - - protected function _setProperty($object, Config\Deserialization\PropertyDeserialization $propConfig, $value) - { - if ($propConfig instanceof Config\Deserialization\DirectDeserialization) { - /** - * @var Config\Deserialization\DirectDeserialization $propConfig - */ - - $prop = $propConfig->property; - $object->$prop = $value; - - } elseif ($propConfig instanceof Config\Deserialization\SetterDeserialization) { - /** - * @var Config\Deserialization\SetterDeserialization $propConfig - */ - - $meth = $propConfig->method; - $object->$meth($value); - } - } - - protected function _readElementWrapper(\XMLReader $xml, Config\Deserialization\ElementWrapper $wrapperConfig) - { - - $elementConfig = $wrapperConfig->wraps; - - $collection = array(); - - while (true) { - if (!$xml->read()) { - throw new \Exception("XML Read failure parsing wrapper"); - } - $fullName = $xml->namespaceURI . ':' . $xml->name; - switch ($xml->nodeType) { - case \XMLReader::ELEMENT: - if ($elementConfig->ref) { - $type = $this->_getRef($elementConfig, $fullName); - } else { - $type = $elementConfig->property->type; - } - if (empty($type)) { - throw new \Exception( - "Unable to resolve wrapped type for " . $wrapperConfig->name . " base type " . - $wrapperConfig->wraps->property->type . " looking for " . $fullName); - } - $collection[] = $this->_readElementAsType($xml, $type); - break; - case \XMLReader::END_ELEMENT: - break 2; - case \XMLReader::WHITESPACE: - case \XMLReader::SIGNIFICANT_WHITESPACE: - case \XMLReader::COMMENT: - break; - default: - throw new \Exception("XML Parsing error, found unexpected {$xml->nodeType}"); - - } - } - - return array($elementConfig->property, - $collection - ); - } - - /** - * @param \Weasel\XmlMarshaller\Config\Deserialization\ElementDeserialization $ref - * @param string $fullName - * @return string the type - */ - protected function _getRef(Config\Deserialization\ElementDeserialization $ref, $fullName) - { - if (isset($ref->refNameToTypeMap)) { - if (isset($ref->refNameToTypeMap[$fullName])) { - return $ref->refNameToTypeMap[$fullName]; - } else { - return null; - } - } - $superConfig = $this->configProvider->getConfig($ref->property->type)->deserialization; - $superFullName = (isset($superConfig->namespace) ? $superConfig->namespace . ":" : "") . $superConfig->name; - $ref->refNameToTypeMap[$superFullName] = $ref->property->type; - foreach ($superConfig->subClasses as $subClass) { - $subConfig = $this->configProvider->getConfig($subClass)->deserialization; - $subFullName = (isset($subConfig->namespace) ? $subConfig->namespace . ":" : "") . $subConfig->name; - $ref->refNameToTypeMap[$subFullName] = $subClass; - } - if (isset($ref->refNameToTypeMap[$fullName])) { - return $ref->refNameToTypeMap[$fullName]; - } - return null; - } - - protected function _readElement(\XMLReader $xml, Config\Deserialization\ClassDeserialization $deConfig) - { - $fullName = $xml->namespaceURI . ':' . $xml->name; - if (isset($deConfig->elementWrappers[$fullName])) { - return $this->_readElementWrapper($xml, $deConfig->elementWrappers[$fullName], $deConfig); - } - - $type = null; - $element = null; - - foreach ($deConfig->elements as $el) { - if (!$el->ref && $el->name == $xml->name && $el->namespace == $xml->namespaceURI) { - $element = $el; - $type = $el->property->type; - break; - } - } - if (!isset($element)) { - foreach ($deConfig->elements as $el) { - if ($el->ref) { - if ($type = $this->_getRef($el, $fullName)) { - $element = $el; - break; - } - } - } - } - if (!isset($element)) { - throw new \Exception("Unknown element found in {$deConfig->name}: {$fullName}"); - } - - return array($element->property, - $this->_readElementAsType($xml, $type) - ); - } - - private static $_knownSimpleTypes = array( - "int" => "int", - "integer" => "integer", - "bool" => "bool", - "boolean" => "boolean", - "float" => "float", - "string" => "string" - ); - - /** - * @param \XMLReader $xml - * @param string $type - * @param bool $root - * @throws \Exception - * @return mixed - */ - protected function _readElementAsType($xml, $type, $root = false) - { - if (isset(self::$_knownSimpleTypes[$type])) { - $ret = $this->_decodeSimpleValue($xml->readInnerXml(), $type); - if (!$xml->isEmptyElement) { - $open = 1; - while ($open > 0) { - if (!$xml->read()) { - throw new \Exception("XML Read failure parsing simple value"); - } - if ($xml->nodeType == \XMLReader::ELEMENT && !$xml->isEmptyElement) { - $open++; - } elseif ($xml->nodeType == \XMLReader::END_ELEMENT) { - $open--; - } - } - } - return $ret; - } - - // Assume type strings are well formed: look for the last [ to see if it's an array or map. - // Note that this might be an array of arrays, and we're after the outermost type, so we're after the last [! - $pos = strrpos($type, '['); - if ($pos === false) { - // If there wasn't a [ then this must be an object. - return $this->_readObject($xml, $type, $root); - } - - // Extract the base type, and whatever's between the [...] as the index type. - // Potentially the type string is actually badly formed: - // e.g. this code will accept string[int! as being an array of string with index int. - // Bah. I'll ignore that case for now. This bit of code gets called a lot, I'd rather not add another substr. - $elementType = substr($type, 0, $pos); - $indexType = substr($type, $pos + 1, -1); - - // We return an array of the element(s) we've read. - // This will be merged if necessary by whoever we return it to. - if ($indexType === "") { - // It's an array element, not a map. - return array($this->_readElementAsType($xml, $elementType)); - } else { - return $this->_readMap($xml, $indexType, $elementType); - } - - } - - protected function _readMap(\XMLReader $xml, $indexType, $elementType) - { - - $array = array(); - - $inEntry = false; - - $key = null; - $value = null; - - do { - if (!$xml->read()) { - throw new \Exception("XML Read failure parsing array"); - } - switch ($xml->nodeType) { - case \XMLReader::ELEMENT: - if (!$inEntry && $xml->name !== 'entry') { - throw new \Exception("Expected map entry, got: " . $xml->name); - } - if ($xml->name === 'entry') { - $inEntry = true; - } elseif ($xml->name === 'key') { - if (isset($key)) { - throw new \Exception("Found multiple keys for entry"); - } - $key = $this->_readElementAsType($xml, $indexType); - } elseif ($xml->name === 'value') { - if (isset($key)) { - throw new \Exception("Found multiple values for entry"); - } - $key = $this->_readElementAsType($xml, $elementType); - } else { - throw new \Exception("Found unexpected node {$xml->name} when reading map"); - } - break; - case \XMLReader::END_ELEMENT: - if ($xml->name === 'entry') { - $xml->next(); - $inEntry = false; - } - break; - case \XMLReader::WHITESPACE: - case \XMLReader::COMMENT: - break; - default: - throw new \Exception("XML Parsing error, found unexpected {$xml->nodeType}"); - - } - } while ($xml->nodeType != \XMLReader::END_ELEMENT); - - return $array; - } - - protected function _readAttribute(\XMLReader $xml, Config\Deserialization\AttributeDeserialization $config) - { - return $this->_decodeSimpleValue($xml->value, $config->property->type); - } - - public function writeString($object, $class = null) - { - throw new \Exception("Not implemented yet"); - } - - protected function _decodeSimpleValue($value, $type) - { - switch ($type) { - case "bool": - case "boolean": - if (is_bool($value)) { - return (bool)$value; - } - if ($value === "true" || $value === 1) { - return true; - } - if ($value === "false" || $value === 0) { - return false; - } - throw new \Exception("Type error"); - break; - case "int": - case "integer": - if (!is_numeric($value)) { - throw new \Exception("Type error, expected numeric but got " . $value); - } - return (int)$value; - break; - case "string": - if (!is_string($value)) { - throw new \Exception("Type error, expected string but got " . gettype($value)); - } - return (string)$value; - case "float": - if (!is_numeric($value)) { - throw new \Exception("Type error, expected numeric but got " . $value); - } - return (float)$value; - default: - throw new \Exception("Invalid simple type: " . $type); - } - - } - -} diff --git a/lib/WeaselAutoloader.php b/lib/WeaselAutoloader.php deleted file mode 100644 index 404f259..0000000 --- a/lib/WeaselAutoloader.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel; - -/** - * @param string $name Class to load - * @return void - * @deprecated Install the package using composer, and use the composer autoloader! - */ -function autoLoad($name) -{ - if (class_exists($name) || interface_exists($name)) { - return; - } - $exploded = explode("\\", $name); - $vendor = $exploded[0]; - if ($vendor != "Weasel") { - return; - } - $path = implode('/', $exploded); - /** @noinspection PhpIncludeInspection */ - include(__DIR__ . '/' . $path . '.php'); - return; -} - -spl_autoload_register('\Weasel\autoLoad'); - diff --git a/tests/Weasel/Annotation/AnnotationConfiguratorTest.php b/tests/Weasel/Annotation/AnnotationConfiguratorTest.php deleted file mode 100644 index 8b541a3..0000000 --- a/tests/Weasel/Annotation/AnnotationConfiguratorTest.php +++ /dev/null @@ -1,667 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation; - -class AnnotationConfiguratorTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - */ - public function testBuiltIns() - { - - $mock = $this->getMock('\Weasel\Annotation\AnnotationReaderFactory', array(), array(), '', false); - $mock->expects($this->never())->method('getReaderForClass'); - $instance = new AnnotationConfigurator(null, null, $mock); - - $annotation = $instance->get('\Weasel\Annotation\Config\Annotations\Annotation'); - - $builtins = \Weasel\Annotation\Config\BuiltInsProvider::getConfig(); - $this->assertSame($builtins->getAnnotation('\Weasel\Annotation\Config\Annotations\Annotation'), $annotation); - - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - */ - public function testBasicAnnotation() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array( - "__construct", - array() - ), - array( - "setA", - array() - ), - array( - "getA", - array() - ), - array( - "creator", - array() - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - - $this->assertEquals($expected, $result); - - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - */ - public function testCreator() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $constructorParams = array(); - $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); - $constructorParams[] = new Config\Annotations\Parameter("bar", "integer", true); - $constructorParams[] = new Config\Annotations\Parameter(null, "boolean", false); - - $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); - - $constructorAnnotations = - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - $constructorAnnotations - ), - array("setA", - array() - ), - array("getA", - array() - ), - array("creator", - array() - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - $expected->setCreatorMethod('__construct'); - $expected->addCreatorParam(new Config\Param("foo", "string", true)); - $expected->addCreatorParam(new Config\Param("bar", "integer", true)); - $expected->addCreatorParam(new Config\Param("c", "boolean", false)); - - $this->assertEquals($expected, $result, "Got " . print_r($result, true)); - - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - */ - public function testStaticCreator() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $constructorParams = array(); - $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); - - $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); - - $constructorAnnotations = - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - array() - ), - array("setA", - array() - ), - array("getA", - array() - ), - array("creator", - $constructorAnnotations - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - $expected->setCreatorMethod('creator'); - $expected->addCreatorParam(new Config\Param("foo", "string", true)); - - $this->assertEquals($expected, $result); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - */ - public function testProperties() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValue(array())); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValueMap(array( - array("a", - array('\Weasel\Annotation\Config\Annotations\Property' => array(new Config\Annotations\Property("string"))), - ), - array("b", - array('\Weasel\Annotation\Config\Annotations\Property' => array(new Config\Annotations\Property("float"))), - ), - ) - ) - ); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - $expected->addProperty(new Config\Property("a", "string")); - $expected->addProperty(new Config\Property("b", "float")); - - $this->assertEquals($expected, $result, "Got " . print_r($result, true)); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - */ - public function testEnum() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValue(array())); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValueMap(array( - array("a", - array() - ), - array("b", - array() - ), - array("enumTest", - array('\Weasel\Annotation\Config\Annotations\Enum' => array( - new Config\Annotations\Enum("toast") - ) - ) - ) - ) - ) - ); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - $expected->addEnum(new Config\Enum("toast", array("FOO" => 1, - "BAR" => 2 - )) - ); - - $this->assertEquals($expected, $result, "Got " . print_r($result, true)); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - */ - public function testEnumDefaultName() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValue(array())); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValueMap(array( - array("a", - array() - ), - array("b", - array() - ), - array("enumTest", - array('\Weasel\Annotation\Config\Annotations\Enum' => array( - new Config\Annotations\Enum(null) - ) - ) - ) - ) - ) - ); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - $expected->addEnum(new Config\Enum("enumTest", array("FOO" => 1, - "BAR" => 2 - )) - ); - - $this->assertEquals($expected, $result, "Got " . print_r($result, true)); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Enums must be static properties - */ - public function testNonStaticEnum() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValue(array())); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValueMap(array( - array("a", - array('\Weasel\Annotation\Config\Annotations\Enum' => array( - new Config\Annotations\Enum(null) - ) - ) - ), - ) - ) - ); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Enum must be an array - */ - public function testNonArrayEnum() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValue(array())); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValueMap(array( - array("b", - array('\Weasel\Annotation\Config\Annotations\Enum' => array( - new Config\Annotations\Enum(null) - ) - ) - ), - ) - ) - ); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Did not find an @Annotation annotation on - */ - public function testThatsNoAnnotation() - { - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue(array())); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - array() - ), - array("setA", - array() - ), - array("getA", - array() - ), - array("creator", - array() - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Non-static methods cannot be configured as creators - */ - public function testNonStaticCreatorFail() - { - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $constructorParams = array(); - $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); - - $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); - - $constructorAnnotations = - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - array() - ), - array("setA", - $constructorAnnotations - ), - array("getA", - array() - ), - array("creator", - array() - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Creator args don't match with method args - */ - public function testTooManyCreatorArgs() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $constructorParams = array(); - $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); - $constructorParams[] = new Config\Annotations\Parameter("bar", "string", true); - - $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); - - $constructorAnnotations = - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - array() - ), - array("setA", - array() - ), - array("getA", - array() - ), - array("creator", - $constructorAnnotations - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Creator args don't match with method args - */ - public function testTooFewCreatorArgs() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $constructorParams = array(); - $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); - $constructorParams[] = new Config\Annotations\Parameter("bar", "string", true); - - $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); - - $constructorAnnotations = - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - $constructorAnnotations - ), - array("setA", - array() - ), - array("getA", - array() - ), - array("creator", - array() - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - } -} - -class MockAnnotationReaderFactory extends AnnotationReaderFactory -{ - - public $mock; - - public function __construct($mock = null) - { - $this->mock = $mock; - } - - public function getReaderForClass(\ReflectionClass $class) - { - return $this->mock; - } -} - -class BoringAnnotation -{ - public $a; - - public static $b = 666; - - public static $enumTest = array( - "FOO" => 1, - "BAR" => 2, - ); - - public function __construct($a = null, $b = null, $c = null) - { - $this->a = - array($a, - $b, - $c - ); - } - - public static function creator($a = null) - { - return new BoringAnnotation($a); - } - - public function setA($a) - { - $this->a = $a; - return $this; - } - - public function getA() - { - return $this->a; - } - -} diff --git a/tests/Weasel/Annotation/AnnotationReaderTest.php b/tests/Weasel/Annotation/AnnotationReaderTest.php deleted file mode 100644 index 5e80b7b..0000000 --- a/tests/Weasel/Annotation/AnnotationReaderTest.php +++ /dev/null @@ -1,33 +0,0 @@ -shouldReceive('get')->with('\HelloWorld')->andReturn(new Annotation('\stdClass', array(), 1)); - - require __DIR__ . '/resources/AnnotatedClass.php'; - $reader = new AnnotationReader(new \ReflectionClass('\Weasel_Annotation_TestResources_AnnotatedClass'), $mockConfigProvider); - $read = $reader->getClassAnnotations(); - - // Ordering is important. We need to require the NoDocBlock file immediately to ensure that the last thing - // parsed was the AnnotatedClass - require __DIR__ . '/resources/NoDocBlock.php'; - $this->assertNotEmpty($read); - - $reader = new AnnotationReader(new \ReflectionClass('\Weasel_Annotation_TestResources_NoDocBlock'), $mockConfigProvider); - - $this->assertEmpty($reader->getClassAnnotations()); - - } - -} diff --git a/tests/Weasel/Annotation/DocblockLexerTest.php b/tests/Weasel/Annotation/DocblockLexerTest.php deleted file mode 100644 index 80d1b30..0000000 --- a/tests/Weasel/Annotation/DocblockLexerTest.php +++ /dev/null @@ -1,255 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Tests; - -use Weasel\Annotation\DocblockLexer; - -class DocblockLexerTest extends \PHPUnit_Framework_TestCase -{ - - public function provideSimpleType() - { - return array( - array(' 123 +942 -954 1 0 +0 -0 +5-1 ', - array_fill(0, 9, DocblockLexer::T_INTEGER) - ), - array('123 +942 -954 1 0 +0 -0 +5-1 ', - array_fill(0, 9, DocblockLexer::T_INTEGER) - ), - array(' 12.3+9.42 -95.4 1.0 0.0 +0.0-0.0 5e5 12E75 -23e93 94e-12', - array_fill(0, 11, DocblockLexer::T_FLOAT) - ), - array(' true false - true', - array_fill(0, 3, DocblockLexer::T_BOOLEAN) - ), - array(' @ @ @@', - array_fill(0, 4, DocblockLexer::T_AT) - ), - array(' \\\\ \\\\\\', - array_fill(0, 5, DocblockLexer::T_BACKSLASH) - ), - array(' "foo bar" """w he e" "w @oo""ar gh""me h 123" "hello - world"', - array_fill(0, 4, DocblockLexer::T_QUOTED_STRING) - ), - array(':: :', - array_fill(0, 3, DocblockLexer::T_COLON) - ), - array('} }}', - array_fill(0, 3, DocblockLexer::T_CLOSE_BRACE) - ), - array('{ { {', - array_fill(0, 3, DocblockLexer::T_OPEN_BRACE) - ), - array(') ))', - array_fill(0, 3, DocblockLexer::T_CLOSE_PAREN) - ), - array('(( (', - array_fill(0, 3, DocblockLexer::T_OPEN_PAREN) - ), - array(', ,,', - array_fill(0, 3, DocblockLexer::T_COMMA) - ), - array('.. .', - array_fill(0, 3, DocblockLexer::T_DOT) - ), - array(' = = =', - array_fill(0, 3, DocblockLexer::T_EQUAL) - ), - array(' foo bar baz', - array_fill(0, 3, DocblockLexer::T_IDENTIFIER) - ), - array(' null null null', - array_fill(0, 3, DocblockLexer::T_NULL) - ), - array(' + # ~', - array_fill(0, 3, DocblockLexer::T_MEH) - ), - ); - - } - - /** - * @param $in - * @param $expectedTypes - * @dataProvider provideSimpleType - * @covers \Weasel\Annotation\DocblockLexer - */ - public function testSimpleType($in, $expectedTypes) - { - $lexer = new DocblockLexer($in); - $got = array(); - $toks = array(); - $peeked[] = $lexer->peek(1, true); - $cur = $lexer->skip(); - do { - $this->assertEquals($cur, $lexer->get()); - if ($peek = $lexer->peek(1, true)) { - $peeked[] = $peek; - } - $got[] = $cur['type']; - $toks[] = $cur['token']; - } while ($cur = $lexer->next(true)); - $this->assertEquals($expectedTypes, $got, 'Type failure on array ' . print_r($toks, true)); - $this->assertEquals($expectedTypes, $peeked, 'Type failure on array ' . print_r($toks, true)); - } - - /** - * @covers \Weasel\Annotation\DocblockLexer - */ - public function testWhiteSpace() - { - $lexer = new DocblockLexer(" "); - - $cur = $lexer->get(); - $peek = $lexer->peek(); - $next = $lexer->next(); - - $this->assertEquals(DocblockLexer::T_WHITESPACE, $cur["type"]); - $this->assertNull($peek); - $this->assertNull($next); - - } - - /** - * @covers \Weasel\Annotation\DocblockLexer - */ - public function testEOL() - { - $lexer = new DocblockLexer("\n\n\r\n\n"); - - $cur = $lexer->get(); - $peek = $lexer->peek(); - $next = $lexer->next(); - - $this->assertEquals(DocblockLexer::T_EOL, $cur["type"]); - $this->assertNull($peek); - $this->assertNull($next); - - } - - /** - * @covers \Weasel\Annotation\DocblockLexer - */ - public function testPreamble() - { - $lexer = new DocblockLexer("\n * \r\n *\t"); - - $cur = $lexer->get(); - $peek = $lexer->peek(); - $next = $lexer->next(); - - $this->assertEquals(DocblockLexer::T_PREAMBLE, $cur["type"]); - $this->assertEquals(DocblockLexer::T_PREAMBLE, $peek); - $this->assertEquals(DocblockLexer::T_PREAMBLE, $next["type"]); - - } - - /** - * @covers \Weasel\Annotation\DocblockLexer::peek - * @covers \Weasel\Annotation\DocblockLexer::cur - * @covers \Weasel\Annotation\DocblockLexer::_wsSkippingPeek - */ - public function testPeek() - { - - $testIn = '@ 1 \ true "foo" bar'; - $lexer = new DocblockLexer($testIn); - - $cur = $lexer->cur(); - $this->assertEquals(DocblockLexer::T_AT, $lexer->peek(0)); - $this->assertEquals(DocblockLexer::T_WHITESPACE, $lexer->peek(1)); - $this->assertEquals(DocblockLexer::T_INTEGER, $lexer->peek(2)); - $this->assertEquals(DocblockLexer::T_IDENTIFIER, $lexer->peek(10)); - $this->assertNull($lexer->peek(11)); - - $this->assertEquals(DocblockLexer::T_AT, $lexer->peek(0, true)); - $this->assertEquals(DocblockLexer::T_INTEGER, $lexer->peek(1, true)); - $this->assertEquals(DocblockLexer::T_BACKSLASH, $lexer->peek(2, true)); - $this->assertEquals(DocblockLexer::T_BOOLEAN, $lexer->peek(3, true)); - - $this->assertEquals(DocblockLexer::T_IDENTIFIER, $lexer->peek(5, true)); - $this->assertNull($lexer->peek(6, true)); - $this->assertEquals(DocblockLexer::T_INTEGER, $lexer->peek(1, true)); - $this->assertEquals($cur, $lexer->cur()); - - $lexer->next(); - $this->assertEquals(DocblockLexer::T_INTEGER, $lexer->peek(0, true)); - - } - - /** - * @covers \Weasel\Annotation\DocblockLexer::peek - * @expectedException \InvalidArgumentException - */ - public function testBadPeek() - { - $testIn = '@ 1 \ true "foo" bar'; - $lexer = new DocblockLexer($testIn); - $lexer->peek(-1); - } - - /** - * @covers \Weasel\Annotation\DocblockLexer::seek - * @covers \Weasel\Annotation\DocblockLexer::cur - */ - public function testSeek() - { - $testIn = '@ 1 \ true "foo" bar'; - $lexer = new DocblockLexer($testIn); - - $this->assertEquals(0, $lexer->cur()); - $cur = $lexer->seek(4); - $this->assertEquals(4, $lexer->cur()); - $this->assertEquals(DocblockLexer::T_BACKSLASH, $cur["type"]); - $this->assertEquals($lexer->get(), $cur); - $cur = $lexer->seek(-3); - $this->assertEquals(8, $lexer->cur()); - $this->assertEquals(DocblockLexer::T_QUOTED_STRING, $cur["type"]); - $this->assertEquals($lexer->get(), $cur); - $this->assertNull($lexer->seek(12)); - $this->assertEquals(8, $lexer->cur()); - $cur = $lexer->seek(0); - $this->assertEquals(0, $lexer->cur()); - $this->assertEquals(DocblockLexer::T_AT, $cur["type"]); - $this->assertEquals($lexer->get(), $cur); - } - - /** - * @covers \Weasel\Annotation\DocblockLexer::skipToType - */ - public function testSkipToType() - { - $testIn = '@ 1 \ true "foo" bar'; - $lexer = new DocblockLexer($testIn); - - $cur = $lexer->skipToType(DocblockLexer::T_AT); - $this->assertEquals(DocblockLexer::T_AT, $cur["type"]); - $this->assertEquals($lexer->get(), $cur); - - $cur = $lexer->skipToType(DocblockLexer::T_QUOTED_STRING); - $this->assertEquals(DocblockLexer::T_QUOTED_STRING, $cur["type"]); - $this->assertEquals($lexer->get(), $cur); - - $this->assertNull($lexer->skipToType(DocblockLexer::T_COLON)); - - } - - /** - * @covers \Weasel\Annotation\DocblockLexer::skipToType - */ - public function testSkipToTypeEmpty() - { - $lexer = new DocblockLexer(""); - - $this->assertNull($lexer->skipToType(DocblockLexer::T_AT)); - - } - - -} diff --git a/tests/Weasel/Annotation/DocblockParserTest.php b/tests/Weasel/Annotation/DocblockParserTest.php deleted file mode 100644 index 8259155..0000000 --- a/tests/Weasel/Annotation/DocblockParserTest.php +++ /dev/null @@ -1,612 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\Annotation\Tests; - -use Weasel\Annotation\DocblockParser; -use Weasel\Annotation\AnnotationConfigurator; -use Weasel\Annotation\Config\AnnotationConfig; - -class DocblockParserTest extends \PHPUnit_Framework_TestCase -{ - - public function provideSimpleClassAnnotation() - { - return array( - array('flibble fish', - 'string' - ), - array('test "some" quotes', - 'string' - ), - array(12356, - 'integer' - ), - array(5.23, - 'float' - ), - array(true, - 'boolean' - ), - array(false, - 'boolean' - ), - ); - } - - protected function _phpTypeToAnnotationType($type, $value) - { - if ($type === 'string') { - return '"' . str_replace('"', '""', $value) . '"'; - } - if ($type === 'boolean') { - return $value ? "true" : "false"; - } - return $value; - } - - - /** - * @param $value - * @param $type - * @dataProvider provideSimpleClassAnnotation - * @covers \Weasel\Annotation\DocblockParser - */ - public function testSimpleClassAnnotation($value, $type) - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', $type)); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $valueQuoted = $this->_phpTypeToAnnotationType($type, $value); - - $parsed = $parser->parse( - '/** - * @Gloop(foo=' . $valueQuoted . ') - */', - "class", - array('Gloop' => 'Weasel\Annotation\Tests\Gloop') - ); - - $gloop = new Gloop(); - $gloop->foo = $value; - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); - - } - - /** - * @covers \Weasel\Annotation\DocblockParser - */ - public function testNoArgsAnnotation() - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @Gloop - */', - "class", - array('Gloop' => 'Weasel\Annotation\Tests\Gloop') - ); - - $gloop = new Gloop(); - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); - - } - - /** - * @covers \Weasel\Annotation\DocblockParser - */ - public function testTwoAnnotations() - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @Gloop - * @Gloop - */', - "class", - array('Gloop' => 'Weasel\Annotation\Tests\Gloop') - ); - - $gloop = new Gloop(); - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop, - $gloop - ) - ), $parsed - ); - - } - - /** - * @covers \Weasel\Annotation\DocblockParser - */ - public function testEmptyArgsAnnotation() - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @Gloop() - */', - "class", - array('Gloop' => 'Weasel\Annotation\Tests\Gloop') - ); - - $gloop = new Gloop(); - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); - - } - - /** - * @covers \Weasel\Annotation\DocblockParser - */ - public function testFullyNamespacedAnnotation() - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @\Weasel\Annotation\Tests\Gloop - */', - "class", - array() - ); - - $gloop = new Gloop(); - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); - - } - - /** - * @covers \Weasel\Annotation\DocblockParser - */ - public function testMissingWhitespaceNoArgs() - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @\Weasel\Annotation\Tests\Gloop@glarp - */', - "class", - array() - ); - - $this->assertEmpty($parsed); - - } - - /** - * @covers \Weasel\Annotation\DocblockParser - */ - public function testMissingWhitespaceArgs() - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @\Weasel\Annotation\Tests\Gloop()@glarp - */', - "class", - array() - ); - - $this->assertEmpty($parsed); - - } - - /** - * @covers \Weasel\Annotation\DocblockParser - */ - public function testArrayClassAnnotation() - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', 'string[][]')); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @Gloop(foo={{"ab", "cd"}, {"ef"}, {}}) - */', - "class", - array('Gloop' => 'Weasel\Annotation\Tests\Gloop') - ); - - $gloop = new Gloop(); - $gloop->foo = - array(array("ab", - "cd" - ), - array("ef"), - array() - ); - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); - - } - - /** - * @covers \Weasel\Annotation\DocblockParser - */ - public function testArraySingleElementClassAnnotation() - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', 'string[]')); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @Gloop(foo="bar") - */', - "class", - array('Gloop' => 'Weasel\Annotation\Tests\Gloop') - ); - - $gloop = new Gloop(); - $gloop->foo = array("bar"); - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); - - } - - /** - * @param $value - * @param $type - * @dataProvider provideSimpleClassAnnotation - * @covers \Weasel\Annotation\DocblockParser - */ - public function testNestedClassAnnotation($value, $type) - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', '\Weasel\Annotation\Tests\Glarp')); - $mockConfigurator->addAnnotation($annotation); - $annotation = - new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Glarp', array('\Weasel\Annotation\Tests\Gloop')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('bar', $type)); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $valueQuoted = $this->_phpTypeToAnnotationType($type, $value); - - $parsed = $parser->parse( - '/** - * @Gloop(foo=@Glarp(bar=' . $valueQuoted . ')) - */', - "class", - array( - 'Gloop' => 'Weasel\Annotation\Tests\Gloop', - 'Glarp' => 'Weasel\Annotation\Tests\Glarp' - ) - - ); - - $gloop = new Gloop(); - $gloop->foo = new Glarp(); - $gloop->foo->bar = $value; - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); - - } - - /** - * @covers \Weasel\Annotation\DocblockParser - */ - public function testMultiNestedArgs() - { - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Multi', array('class')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('a', '\Weasel\Annotation\Tests\Glarp')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('b', '\Weasel\Annotation\Tests\Glarp')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('c', '\Weasel\Annotation\Tests\Gloop')); - $mockConfigurator->addAnnotation($annotation); - $annotation = - new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Glarp', array('\Weasel\Annotation\Tests\Multi')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('bar', 'string')); - $mockConfigurator->addAnnotation($annotation); - $annotation = - new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('\Weasel\Annotation\Tests\Multi')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', 'string')); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @Multi(a=@Glarp(bar="foo"), b=@Glarp(bar="baa"), c=@Gloop(foo="fnord")) - * @Multi(a=@Glarp(bar="foo") , b=@Glarp(bar="baa") , c=@Gloop(foo="fnord")) - * @Multi(a=@Glarp(bar="foo"),b=@Glarp(bar="baa"),c=@Gloop(foo="fnord")) - */', - "class", - array( - 'Gloop' => 'Weasel\Annotation\Tests\Gloop', - 'Glarp' => 'Weasel\Annotation\Tests\Glarp', - 'Multi' => 'Weasel\Annotation\Tests\Multi' - ) - - ); - - $multi = new Multi(); - $multi->a = new Glarp(); - $multi->a->bar = "foo"; - $multi->b = new Glarp(); - $multi->b->bar = "baa"; - $multi->c = new Gloop(); - $multi->c->foo = "fnord"; - - $results = array_fill(0, 3, $multi); - - $this->assertEquals(array('\Weasel\Annotation\Tests\Multi' => $results), $parsed); - - } - - /** - * @param $value - * @param $type - * @dataProvider provideSimpleClassAnnotation - * @covers \Weasel\Annotation\DocblockParser - */ - public function testSimpleClassAnnotationCreator($value, $type) - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $annotation->setCreatorMethod('__construct'); - $annotation->addCreatorParam( - new \Weasel\Annotation\Config\Param('foo', $type, false) - ); - $annotation->addCreatorParam( - new \Weasel\Annotation\Config\Param('baz', $type, false) - ); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $valueQuoted = $this->_phpTypeToAnnotationType($type, $value); - - $parsed = $parser->parse( - '/** - * @Gloop(foo=' . $valueQuoted . ') - * @Gloop(' . $valueQuoted . ') - * @Gloop(' . $valueQuoted . ', ' . $valueQuoted . ') - * @Gloop(baz=' . $valueQuoted . ') - */', - "class", - array('Gloop' => 'Weasel\Annotation\Tests\Gloop') - ); - - $expected = array(); - - $gloop = new Gloop(); - $gloop->fromca = $value; - $expected[] = $gloop; - - $gloop = new Gloop(); - $gloop->fromca = $value; - $expected[] = $gloop; - - $gloop = new Gloop(); - $gloop->fromca = $gloop->fromcb = $value; - $expected[] = $gloop; - - $gloop = new Gloop(); - $gloop->fromcb = $value; - $expected[] = $gloop; - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => $expected), $parsed); - - } - - /** - * @return void - * @covers \Weasel\Annotation\DocblockParser - */ - public function testUnknownAnnotations() - { - - $mockConfigurator = new MockConfigurator(); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @author Jonathan Oddy - * @param string $value Wheeeeee - * @param string[] $type Wobble Kerping Splat - * @returns your mum - */', - "method", - array() - ); - - $this->assertEquals(array(), $parsed); - - } - - /** - * @return void - * @covers \Weasel\Annotation\DocblockParser - */ - public function testEnumAnnotation() - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', 'integer')); - $annotation->addEnum(new \Weasel\Annotation\Config\Enum('Snorks', array("FOO" => 1, - "BAR" => 2, - "BAZ" => 3 - )) - ); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @Gloop(foo=Gloop.Snorks.BAR) - */', - "class", - array('Gloop' => 'Weasel\Annotation\Tests\Gloop') - ); - - $gloop = new Gloop(); - $gloop->foo = 2; - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); - - } - - /** - * @return void - * @covers \Weasel\Annotation\DocblockParser - */ - public function testEnumAnnotationNoName() - { - - $mockConfigurator = new MockConfigurator(); - $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); - $annotation->setCreatorMethod('__construct'); - $annotation->addCreatorParam(new \Weasel\Annotation\Config\Param('foo', 'integer', false)); - $annotation->addCreatorParam(new \Weasel\Annotation\Config\Param('baz', 'integer', false)); - $annotation->addEnum(new \Weasel\Annotation\Config\Enum('Snorks', array("FOO" => 1, - "BAR" => 2, - "BAZ" => 3 - )) - ); - $mockConfigurator->addAnnotation($annotation); - - $parser = new DocblockParser($mockConfigurator); - - $parsed = $parser->parse( - '/** - * @Gloop(Gloop.Snorks.BAR) - */', - "class", - array('Gloop' => 'Weasel\Annotation\Tests\Gloop') - ); - - $gloop = new Gloop(); - $gloop->fromca = 2; - - $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); - - } -} - -class Gloop -{ - - public $foo; - - public $fromca; - public $fromcb; - - public function __construct($foo = null, $baz = null) - { - $this->fromca = $foo; - $this->fromcb = $baz; - } -} - -class Multi -{ - - public $a; - public $b; - public $c; - -} - -class Glarp -{ - - public $bar; - - public $fromca; - public $fromcb; - - public function __construct($bar = null, $baz = null) - { - $this->fromca = $bar; - $this->fromcb = $baz; - } - -} - -class MockConfigurator extends AnnotationConfigurator -{ - - protected $config; - - public function addAnnotation($annotation) - { - $this->config->addAnnotation($annotation); - } - - public function __construct() - { - $this->config = new AnnotationConfig(); - } - - public function get($type) - { - return $this->config->getAnnotation($type); - } - -} - diff --git a/tests/Weasel/Annotation/PHPParserTest.php b/tests/Weasel/Annotation/PHPParserTest.php deleted file mode 100644 index e52685a..0000000 --- a/tests/Weasel/Annotation/PHPParserTest.php +++ /dev/null @@ -1,80 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ - -use ReflectionClass; -use PHPUnit_Framework_TestCase; - -class PHPParserTest extends PHPUnit_Framework_TestCase -{ - - - public function provideClasses() - { - return array( - array('\Weasel\Annotation\TestResources\SimpleNamespaced', 'SimpleNamespaced', array( - '' => 'Weasel\Annotation\TestResources', - 'TestA' => 'Weasel\Annotation\TestResources\TestA', - 'TestB' => 'Weasel\Annotation\TestResources\TestB', - 'Test' => 'Weasel\Annotation\TestResources\BlahFoo', - )), - array('\Weasel\Annotation\TestResources\SimpleNamespacedSibling', 'SimpleNamespaced', array( - '' => 'Weasel\Annotation\TestResources', - 'TestA' => 'Weasel\Annotation\TestResources\TestA', - 'TestB' => 'Weasel\Annotation\TestResources\TestB', - 'Test' => 'Weasel\Annotation\TestResources\BlahFoo', - )), - array('\Weasel\Annotation\TestResources\SimpleNamespacedExtender', 'SimpleNamespacedExtends', array( - '' => 'Weasel\Annotation\TestResources', - 'TestA' => 'Weasel\Annotation\TestResources\TestA', - 'TestB' => 'Weasel\Annotation\TestResources\TestB', - 'Test' => 'Weasel\Annotation\TestResources\BlahFoo', - )), - array('\Weasel\Annotation\TestResources\NamespacedFirst', 'MultipleNamespace', array( - '' => 'Weasel\Annotation\TestResources', - 'TestA' => 'Weasel\Annotation\TestResources\TestA', - 'TestB' => 'Weasel\Annotation\TestResources\TestB', - 'Test' => 'Weasel\Annotation\TestResources\BlahFoo', - )), - array('\Weasel\Annotation\TestResourcesToo\NamespacedSecond', 'MultipleNamespace', array( - '' => 'Weasel\Annotation\TestResourcesToo', - 'TestC' => 'Weasel\Annotation\TestResources\TestC', - )), - array('\Weasel\Annotation\TestResources\NamespacedShorthand', 'NamespacedShorthand', array( - '' => 'Weasel\Annotation\TestResources', - 'TestD' => 'Weasel\Annotation\TestResources\TestD', - 'TestE' => 'Weasel\Annotation\TestResources\TestE', - 'Test' => 'Weasel\Annotation\TestResources\TestF', - )), - array('NoNamespaceTest', 'NoNamespace', array( - 'TestA' => 'Weasel\Annotation\TestResources\TestA', - '' => '', - )), - array('\Weasel\Annotation\TestResources\PHPGolfNamespace', 'PHPGolfNamespace', array( - 'TestA' => 'Weasel\Annotation\TestResources\TestA', - '' => 'Weasel\Annotation\TestResources', - )), - array('\Weasel\Annotation\TestResourcesToo\PHPGolfNamespaceTwo', 'PHPGolfNamespace', array( - 'TestB' => 'Weasel\Annotation\TestResources\TestB', - '' => 'Weasel\Annotation\TestResourcesToo', - )), - ); - } - - /** - * @dataProvider provideClasses - */ - public function testParse($class, $import, $expected) - { - /** @noinspection PhpIncludeInspection */ - require_once(__DIR__ . '/resources/' . $import . '.php'); - $rClass = new ReflectionClass($class); - $parser = new PhpParser(); - $this->assertEquals($expected, $parser->parseClass($rClass)); - } - -} diff --git a/tests/Weasel/Annotation/TestDocblock.txt b/tests/Weasel/Annotation/TestDocblock.txt deleted file mode 100644 index a952ad2..0000000 --- a/tests/Weasel/Annotation/TestDocblock.txt +++ /dev/null @@ -1,9 +0,0 @@ -/** - * This is a test to see how badly the lexer works - * 41411 6665 -1 +5 - * 1.511 -12.5 +0.55 -0 +0 14114e-1 123E55 - * "groats" "I really like ""groats""" - * - * - * - */ \ No newline at end of file diff --git a/tests/Weasel/Annotation/resources/AnnotatedClass.php b/tests/Weasel/Annotation/resources/AnnotatedClass.php deleted file mode 100644 index 4324e81..0000000 --- a/tests/Weasel/Annotation/resources/AnnotatedClass.php +++ /dev/null @@ -1,8 +0,0 @@ -getReaderForClass($rClass); - $reader->getClassAnnotations(); - } - - /** - * Test what the registered annotation autoloading does when faced with a use with a leading \ - * Must be run in a separate process to ensure the annotation hasn't already been loaded. - * @runInSeparateProcess - */ - public function testAutoloaderWithLeadingSlash() - { - $factory = new DoctrineAnnotationReaderFactory(new AnnotationReader()); - - $rClass = new \ReflectionClass('\Weasel\DoctrineAnnotation\DoctrineAnnotationReaderFactoryTestB\Test'); - - $reader = $factory->getReaderForClass($rClass); - $reader->getClassAnnotations(); - } - - - } -} - -namespace Weasel\DoctrineAnnotation\DoctrineAnnotationReaderFactoryTestA { - use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties; - - /** - * Denotes that there was a problem while accessing the builder service. - * - * @JsonIgnoreProperties() - */ - class Test - { - - } -} - -namespace Weasel\DoctrineAnnotation\DoctrineAnnotationReaderFactoryTestB { - use \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties; - - /** - * Denotes that there was a problem while accessing the builder service. - * - * @JsonIgnoreProperties() - */ - class Test - { - - } -} \ No newline at end of file diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php deleted file mode 100644 index 368c5dd..0000000 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php +++ /dev/null @@ -1,101 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -use Weasel\Annotation\AnnotationReader; -use Weasel\Annotation\AnnotationConfigurator; -use Weasel\Annotation\Config\Annotations\AnnotationCreator; -use Weasel\Annotation\Config\Annotations\Parameter; - -class JsonCreatorTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonCreator - */ - public function testParseClassAnnotations() - { - - $annotationReader = - new AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonCreator'), new AnnotationConfigurator()); - - $expected = array( - '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("method"), 1)), - ); - - $this->assertEquals($expected, $annotationReader->getClassAnnotations()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonCreator - */ - public function testParsePropertyAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonCreator'); - $annotationReader = - new AnnotationReader($rClass, new AnnotationConfigurator()); - - - $found = array(); - foreach ($rClass->getProperties() as $property) { - $name = $property->getName(); - $found[$name] = $annotationReader->getPropertyAnnotations($name); - } - - $this->assertEquals(array("params" => array()), $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonCreator - */ - public function testParseMethodAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonCreator'); - $annotationReader = - new AnnotationReader($rClass, new AnnotationConfigurator()); - - $found = array(); - foreach ($rClass->getMethods() as $method) { - /** - * @var \ReflectionMethod $method - */ - $name = $method->getName(); - if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { - continue; - } - $found[$name] = $annotationReader->getMethodAnnotations($name); - } - - $expected = array("__construct" => - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( - new AnnotationCreator( - array( - new Parameter("params", '\Weasel\JsonMarshaller\Config\Annotations\JsonProperty[]', false), - ) - ) - ) - ), - "getParams" => array(), - ); - - $this->assertEquals($expected, $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonCreator - */ - public function testCreate() - { - $test = new JsonCreator(array()); - $this->assertEmpty($test->getParams()); - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php deleted file mode 100644 index 2021094..0000000 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php +++ /dev/null @@ -1,103 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -class JsonIgnorePropertiesTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties - */ - public function testParseClassAnnotations() - { - - $annotationReader = - new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties'), new \Weasel\Annotation\AnnotationConfigurator()); - - $expected = array( - '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("class"), null)), - ); - - $this->assertEquals($expected, $annotationReader->getClassAnnotations()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties - */ - public function testParsePropertyAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - - $found = array(); - foreach ($rClass->getProperties() as $property) { - $name = $property->getName(); - $found[$name] = $annotationReader->getPropertyAnnotations($name); - } - - $this->assertEquals(array("names" => array(), - "ignoreUnknown" => array() - ), - $found - ); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties - */ - public function testParseMethodAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - $found = array(); - foreach ($rClass->getMethods() as $method) { - /** - * @var \ReflectionMethod $method - */ - $name = $method->getName(); - if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { - continue; - } - $found[$name] = $annotationReader->getMethodAnnotations($name); - } - - $expected = array("__construct" => - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( - new \Weasel\Annotation\Config\Annotations\AnnotationCreator( - array( - new \Weasel\Annotation\Config\Annotations\Parameter("names", 'string[]', false), - new \Weasel\Annotation\Config\Annotations\Parameter("ignoreUnknown", 'boolean', false), - ) - ) - ) - ), - "getNames" => array(), - "getIgnoreUnknown" => array(), - ); - - $this->assertEquals($expected, $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties - */ - public function testCreate() - { - $test = new JsonIgnoreProperties(array("test"), true); - $this->assertEquals(array("test"), $test->getNames()); - $this->assertTrue($test->getIgnoreUnknown()); - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php deleted file mode 100644 index ec1739b..0000000 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php +++ /dev/null @@ -1,106 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -class JsonIncludeTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonInclude - */ - public function testParseClassAnnotations() - { - - $annotationReader = - new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonInclude'), new \Weasel\Annotation\AnnotationConfigurator()); - - $expected = array( - '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("class", - "method", - "property" - ), 1) - ), - ); - - $this->assertEquals($expected, $annotationReader->getClassAnnotations()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonInclude - */ - public function testParsePropertyAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonInclude'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - - $found = array(); - foreach ($rClass->getProperties() as $property) { - $name = $property->getName(); - $found[$name] = $annotationReader->getPropertyAnnotations($name); - } - - $expectedEnumInclude = new \Weasel\Annotation\Config\Annotations\Enum("Include"); - - $this->assertEquals(array("enumInclude" => array('\Weasel\Annotation\Config\Annotations\Enum' => array($expectedEnumInclude)), - "value" => array() - ), - $found - ); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonInclude - */ - public function testParseMethodAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonInclude'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - $found = array(); - foreach ($rClass->getMethods() as $method) { - /** - * @var \ReflectionMethod $method - */ - $name = $method->getName(); - if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { - continue; - } - $found[$name] = $annotationReader->getMethodAnnotations($name); - } - - $expected = array("__construct" => - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( - new \Weasel\Annotation\Config\Annotations\AnnotationCreator( - array( - new \Weasel\Annotation\Config\Annotations\Parameter("value", 'integer', true), - ) - ) - ) - ), - "getValue" => array(), - ); - - $this->assertEquals($expected, $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonInclude - */ - public function testCreate() - { - $test = new JsonInclude(JsonInclude::$enumInclude["NON_NULL"]); - $this->assertEquals(JsonInclude::$enumInclude["NON_NULL"], $test->getValue()); - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php deleted file mode 100644 index f09bc3b..0000000 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php +++ /dev/null @@ -1,112 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -class JsonPropertyTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonProperty - */ - public function testParseClassAnnotations() - { - - $annotationReader = - new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonProperty'), new \Weasel\Annotation\AnnotationConfigurator()); - - $expected = array( - '\Weasel\Annotation\Config\Annotations\Annotation' => array( - new \Weasel\Annotation\Config\Annotations\Annotation(array("property", - "method", - '\Weasel\JsonMarshaller\Config\Annotations\JsonCreator' - ), null) - ), - ); - - $this->assertEquals($expected, $annotationReader->getClassAnnotations()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonProperty - */ - public function testParsePropertyAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonProperty'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - - $found = array(); - foreach ($rClass->getProperties() as $property) { - $name = $property->getName(); - $found[$name] = $annotationReader->getPropertyAnnotations($name); - } - - $this->assertEquals(array("name" => array(), - "type" => array(), - "strict" => array() - ), - $found - ); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonProperty - */ - public function testParseMethodAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonProperty'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - $found = array(); - foreach ($rClass->getMethods() as $method) { - /** - * @var \ReflectionMethod $method - */ - $name = $method->getName(); - if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { - continue; - } - $found[$name] = $annotationReader->getMethodAnnotations($name); - } - - $expected = array("__construct" => - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( - new \Weasel\Annotation\Config\Annotations\AnnotationCreator( - array( - new \Weasel\Annotation\Config\Annotations\Parameter("name", 'string', false), - new \Weasel\Annotation\Config\Annotations\Parameter("type", 'string', false), - new \Weasel\Annotation\Config\Annotations\Parameter("strict", 'bool', false), - ) - ) - ) - ), - 'getName' => array(), - 'getType' => array(), - 'getStrict' => array(), - ); - - $this->assertEquals($expected, $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonProperty - */ - public function testCreate() - { - $test = new JsonProperty("foo", "bar", true); - $this->assertEquals("foo", $test->getName()); - $this->assertEquals("bar", $test->getType()); - $this->assertEquals(true, $test->getStrict()); - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php deleted file mode 100644 index 00fcadb..0000000 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php +++ /dev/null @@ -1,103 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes; - -class TypeTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type - */ - public function testParseClassAnnotations() - { - - $annotationReader = - new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type'), new \Weasel\Annotation\AnnotationConfigurator()); - - $expected = array( - '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes'), null)), - ); - - $this->assertEquals($expected, $annotationReader->getClassAnnotations()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type - */ - public function testParsePropertyAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - - $found = array(); - foreach ($rClass->getProperties() as $property) { - $name = $property->getName(); - $found[$name] = $annotationReader->getPropertyAnnotations($name); - } - - $this->assertEquals(array("value" => array(), - "name" => array() - ), - $found - ); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type - */ - public function testParseMethodAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - $found = array(); - foreach ($rClass->getMethods() as $method) { - /** - * @var \ReflectionMethod $method - */ - $name = $method->getName(); - if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { - continue; - } - $found[$name] = $annotationReader->getMethodAnnotations($name); - } - - $expected = array("__construct" => - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( - new \Weasel\Annotation\Config\Annotations\AnnotationCreator( - array( - new \Weasel\Annotation\Config\Annotations\Parameter("value", 'string', true), - new \Weasel\Annotation\Config\Annotations\Parameter("name", 'string', false), - ) - ) - ) - ), - "getValue" => array(), - "getName" => array(), - ); - - $this->assertEquals($expected, $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type - */ - public function testCreate() - { - $test = new Type("testValue", "testName"); - $this->assertEquals("testValue", $test->getValue()); - $this->assertEquals("testName", $test->getName()); - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php deleted file mode 100644 index 8ac599d..0000000 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php +++ /dev/null @@ -1,100 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -class JsonSubTypesTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes - */ - public function testParseClassAnnotations() - { - - $annotationReader = - new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes'), new \Weasel\Annotation\AnnotationConfigurator()); - - $expected = array( - '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("class", - "method", - "property" - ), null) - ), - ); - - $this->assertEquals($expected, $annotationReader->getClassAnnotations()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes - */ - public function testParsePropertyAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - - $found = array(); - foreach ($rClass->getProperties() as $property) { - $name = $property->getName(); - $found[$name] = $annotationReader->getPropertyAnnotations($name); - } - - $this->assertEquals(array("value" => array()), $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes - */ - public function testParseMethodAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - $found = array(); - foreach ($rClass->getMethods() as $method) { - /** - * @var \ReflectionMethod $method - */ - $name = $method->getName(); - if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { - continue; - } - $found[$name] = $annotationReader->getMethodAnnotations($name); - } - - $expected = array("__construct" => - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( - new \Weasel\Annotation\Config\Annotations\AnnotationCreator( - array( - new \Weasel\Annotation\Config\Annotations\Parameter("value", '\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type[]', true), - ) - ) - ) - ), - "getValue" => array(), - ); - - $this->assertEquals($expected, $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes - */ - public function testCreate() - { - $test = new JsonSubTypes(array()); - $this->assertEmpty($test->getValue()); - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php deleted file mode 100644 index b12c964..0000000 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php +++ /dev/null @@ -1,126 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -class JsonTypeInfoTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo - */ - public function testParseClassAnnotations() - { - - $annotationReader = - new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo'), new \Weasel\Annotation\AnnotationConfigurator()); - - $expected = array( - '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("class", - "method", - "property" - ), null) - ), - ); - - $this->assertEquals($expected, $annotationReader->getClassAnnotations()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo - */ - public function testParsePropertyAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - - $found = array(); - foreach ($rClass->getProperties() as $property) { - $name = $property->getName(); - $found[$name] = $annotationReader->getPropertyAnnotations($name); - } - - $expectedEnumId = new \Weasel\Annotation\Config\Annotations\Enum("Id"); - $expectedEnumAs = new \Weasel\Annotation\Config\Annotations\Enum("As"); - - $this->assertEquals(array("enumId" => array('\Weasel\Annotation\Config\Annotations\Enum' => array($expectedEnumId),), - "enumAs" => array('\Weasel\Annotation\Config\Annotations\Enum' => array($expectedEnumAs),), - "use" => array(), - "include" => array(), - "property" => array(), - "visible" => array(), - "defaultImpl" => array() - ), - $found - ); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo - */ - public function testParseMethodAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - $found = array(); - foreach ($rClass->getMethods() as $method) { - /** - * @var \ReflectionMethod $method - */ - $name = $method->getName(); - if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { - continue; - } - $found[$name] = $annotationReader->getMethodAnnotations($name); - } - - $expected = array("__construct" => - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( - new \Weasel\Annotation\Config\Annotations\AnnotationCreator( - array( - new \Weasel\Annotation\Config\Annotations\Parameter("use", 'integer', true), - new \Weasel\Annotation\Config\Annotations\Parameter("include", 'integer', false), - new \Weasel\Annotation\Config\Annotations\Parameter("property", 'string', false), - new \Weasel\Annotation\Config\Annotations\Parameter("visible", 'bool', false), - new \Weasel\Annotation\Config\Annotations\Parameter("defaultImpl", 'string', false), - ) - ) - ) - ), - "getUse" => array(), - "getInclude" => array(), - "getProperty" => array(), - "getVisible" => array(), - "getDefaultImpl" => array(), - - ); - - $this->assertEquals($expected, $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo - */ - public function testCreate() - { - $test = - new JsonTypeInfo(JsonTypeInfo::$enumAs["PROPERTY"], JsonTypeInfo::$enumId["NAME"], "testProp", true, "FooBar"); - $this->assertEquals(JsonTypeInfo::$enumAs["PROPERTY"], $test->getUse()); - $this->assertEquals(JsonTypeInfo::$enumId["NAME"], $test->getInclude()); - $this->assertEquals("testProp", $test->getProperty()); - $this->assertEquals(true, $test->getVisible()); - $this->assertEquals("FooBar", $test->getDefaultImpl()); - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php deleted file mode 100644 index 74952c5..0000000 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php +++ /dev/null @@ -1,96 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\Annotations; - -class JsonTypeNameTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeName - */ - public function testParseClassAnnotations() - { - - $annotationReader = - new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeName'), new \Weasel\Annotation\AnnotationConfigurator()); - - $expected = array( - '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("class"), null)), - ); - - $this->assertEquals($expected, $annotationReader->getClassAnnotations()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeName - */ - public function testParsePropertyAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeName'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - - $found = array(); - foreach ($rClass->getProperties() as $property) { - $name = $property->getName(); - $found[$name] = $annotationReader->getPropertyAnnotations($name); - } - - $this->assertEquals(array("name" => array()), $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeName - */ - public function testParseMethodAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeName'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - $found = array(); - foreach ($rClass->getMethods() as $method) { - /** - * @var \ReflectionMethod $method - */ - $name = $method->getName(); - if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { - continue; - } - $found[$name] = $annotationReader->getMethodAnnotations($name); - } - - $expected = array("__construct" => - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( - new \Weasel\Annotation\Config\Annotations\AnnotationCreator( - array( - new \Weasel\Annotation\Config\Annotations\Parameter("name", 'string', true), - ) - ) - ) - ), - "getName" => array(), - ); - - $this->assertEquals($expected, $found); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeName - */ - public function testCreate() - { - $test = new JsonTypeName("testName"); - $this->assertEquals("testName", $test->getName()); - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php b/tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php deleted file mode 100644 index 3869f0e..0000000 --- a/tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php +++ /dev/null @@ -1,106 +0,0 @@ -shouldReceive('getSingleClassAnnotation')->withAnyArgs()->andReturnNull(); - $mockReader->shouldReceive('getSingleMethodAnnotation')->with('getStuff', - '\Weasel\JsonMarshaller\Config\Annotations\JsonProperty')->andReturn( - new JsonProperty(null, "string", null) - ); - $mockReader->shouldReceive('getSingleMethodAnnotation')->with('isGood', - '\Weasel\JsonMarshaller\Config\Annotations\JsonProperty')->andReturn( - new JsonProperty(null, "bool", null) - ); - $mockReader->shouldReceive('getSingleMethodAnnotation')->withAnyArgs()->andReturnNull(); - - $mockReaderFactory = m::mock('\Weasel\Annotation\AnnotationReaderFactory'); - $mockReaderFactory->shouldReceive('getReaderForClass')->with($rClass)->andReturn($mockReader); - - /** - * @var \Weasel\Annotation\AnnotationReaderFactory $mockReaderFactory - */ - $driver = new ClassAnnotationDriver($rClass, $mockReaderFactory); - - $config = $driver->getConfig(); - - $eProperties = array( - "stuff" => new GetterSerialization("getStuff", "string", 1), - "good" => new GetterSerialization("isGood", "bool", 1), - ); - - $this->assertEquals($eProperties, $config->serialization->properties); - } - - /** - * @covers \Weasel\JsonMarshaller\Config\ClassAnnotationDriver::_configureGetter - */ - public function testGetterNameIsNoBool() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\ClassAnnotationDriverTestClassA'); - - $mockReader = m::mock('\Weasel\Common\Annotation\IAnnotationReader'); - $mockReader->shouldReceive('getSingleClassAnnotation')->withAnyArgs()->andReturnNull(); - $mockReader->shouldReceive('getSingleMethodAnnotation')->with('getStuff', - '\Weasel\JsonMarshaller\Config\Annotations\JsonProperty')->andReturn( - new JsonProperty(null, "string", null) - ); - $mockReader->shouldReceive('getSingleMethodAnnotation')->with('isGood', - '\Weasel\JsonMarshaller\Config\Annotations\JsonProperty')->andReturn( - new JsonProperty(null, "string", null) - ); - $mockReader->shouldReceive('getSingleMethodAnnotation')->withAnyArgs()->andReturnNull(); - - $mockReaderFactory = m::mock('\Weasel\Annotation\AnnotationReaderFactory'); - $mockReaderFactory->shouldReceive('getReaderForClass')->with($rClass)->andReturn($mockReader); - - /** - * @var \Weasel\Annotation\AnnotationReaderFactory $mockReaderFactory - */ - $driver = new ClassAnnotationDriver($rClass, $mockReaderFactory); - - $config = $driver->getConfig(); - - $eProperties = array( - "stuff" => new GetterSerialization("getStuff", "string", 1), - "isGood" => new GetterSerialization("isGood", "string", 1), - ); - - $this->assertEquals($eProperties, $config->serialization->properties); - - } - -} - -class ClassAnnotationDriverTestClassA -{ - - public function getStuff() - { - - } - - public function isGood() - { - - } - -} diff --git a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetterTest.php b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetterTest.php deleted file mode 100644 index ab51669..0000000 --- a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetterTest.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\AnnotationReader; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonAnyGetter; -use Doctrine\Common\Annotations\AnnotationRegistry; - -class JsonAnyGetterTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonAnyGetter - */ - public function testBasicClassAnnotations() - { - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetter.php'); - - $annotationReader = new AnnotationReader(); - $got = $annotationReader->getMethodAnnotations(new \ReflectionMethod(__NAMESPACE__ . '\JsonAnyGetterTestVictim', 'basic')); - - $this->assertEquals(array( - new JsonAnyGetter() - ), - $got); - - } - -} - -class JsonAnyGetterTestVictim -{ - - /** - * @JsonAnyGetter - */ - public static function basic() - { - - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetterTest.php b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetterTest.php deleted file mode 100644 index fd9c8d2..0000000 --- a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetterTest.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\AnnotationReader; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonAnySetter; -use Doctrine\Common\Annotations\AnnotationRegistry; - -class JsonAnySetterTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonAnySetter - */ - public function testBasicClassAnnotations() - { - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetter.php'); - - $annotationReader = new AnnotationReader(); - $got = $annotationReader->getMethodAnnotations(new \ReflectionMethod(__NAMESPACE__ . '\JsonAnySetterTestVictim', 'basic')); - - $this->assertEquals(array( - new JsonAnySetter() - ), - $got); - - } - -} - -class JsonAnySetterTestVictim -{ - - /** - * @JsonAnySetter - */ - public static function basic() - { - - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreatorTest.php b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreatorTest.php deleted file mode 100644 index 8ea3ca2..0000000 --- a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreatorTest.php +++ /dev/null @@ -1,106 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\AnnotationReader; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonCreator; -use Doctrine\Common\Annotations\AnnotationRegistry; - -class JsonCreatorTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonCreator - */ - public function testBasicClassAnnotations() - { - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php'); - - $annotationReader = new AnnotationReader(); - $got = $annotationReader->getMethodAnnotations(new \ReflectionMethod(__NAMESPACE__ . '\JsonCreatorTestVictim', 'basic')); - - $this->assertEquals(array( - new JsonCreator(array()) - ), - $got); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonCreator - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty - */ - public function testComplexClassAnnotations() - { - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php'); - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php'); - - $annotationReader = new AnnotationReader(); - $got = $annotationReader->getMethodAnnotations(new \ReflectionMethod(__NAMESPACE__ . '\JsonCreatorTestVictim', 'complex')); - - $this->assertEquals(array( - new JsonCreator(array("params" => array( - new JsonProperty(array("name" => "foo", "type" => "int")), - new JsonProperty(array("name" => "bar", "type" => "int")), - ))) - ), - $got); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonCreator - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty - */ - public function testConstructorClassAnnotations() - { - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php'); - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php'); - - $annotationReader = new AnnotationReader(); - $got = $annotationReader->getMethodAnnotations(new \ReflectionMethod(__NAMESPACE__ . '\JsonCreatorTestVictim', '__construct')); - - $this->assertEquals(array( - new JsonCreator(array("params" => array( - new JsonProperty(array("name" => "foo", "type" => "int")), - new JsonProperty(array("name" => "bar", "type" => "int")), - ))) - ), - $got); - - } - -} - -class JsonCreatorTestVictim -{ - - /** - * @JsonCreator - */ - public static function basic() - { - - } - - /** - * @JsonCreator({@JsonProperty(name="foo", type="int"), @JsonProperty(name="bar", type="int")}) - */ - public static function complex() - { - - } - - - /** - * @JsonCreator(params={@JsonProperty(name="foo", type="int"), @JsonProperty(name="bar", type="int")}) - */ - public function __construct() - { - - } -} diff --git a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnorePropertiesTest.php b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnorePropertiesTest.php deleted file mode 100644 index 234bd52..0000000 --- a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnorePropertiesTest.php +++ /dev/null @@ -1,114 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\AnnotationReader; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties; -use Doctrine\Common\Annotations\AnnotationRegistry; - -class JsonIgnorePropertiesTest extends \PHPUnit_Framework_TestCase -{ - - /** - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties - */ - public function testBasicUsage() - { - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php'); - - $annotationReader = new AnnotationReader(); - $got = $annotationReader->getClassAnnotation(new \ReflectionClass(__NAMESPACE__ . '\JsonIgnorePropertiesTestVictimA'), - __NAMESPACE__ . '\JsonIgnoreProperties'); - - $this->assertInstanceOf(__NAMESPACE__ . '\JsonIgnoreProperties', $got); - $this->assertEquals(array("blork"), $got->getNames()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties - */ - public function testListUsage() - { - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php'); - - $annotationReader = new AnnotationReader(); - $got = $annotationReader->getClassAnnotation(new \ReflectionClass(__NAMESPACE__ . '\JsonIgnorePropertiesTestVictimB'), - __NAMESPACE__ . '\JsonIgnoreProperties'); - - $this->assertInstanceOf(__NAMESPACE__ . '\JsonIgnoreProperties', $got); - $this->assertEquals(array("blork", "blark"), $got->getNames()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties - */ - public function testNamedListUsage() - { - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php'); - - $annotationReader = new AnnotationReader(); - $got = $annotationReader->getClassAnnotation(new \ReflectionClass(__NAMESPACE__ . '\JsonIgnorePropertiesTestVictimC'), - __NAMESPACE__ . '\JsonIgnoreProperties'); - - $this->assertInstanceOf(__NAMESPACE__ . '\JsonIgnoreProperties', $got); - $this->assertEquals(array("blork", "blark"), $got->getNames()); - - } - - /** - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties - */ - public function testIgnoreUsage() - { - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php'); - - $annotationReader = new AnnotationReader(); - $got = $annotationReader->getClassAnnotation(new \ReflectionClass(__NAMESPACE__ . '\JsonIgnorePropertiesTestVictimD'), - __NAMESPACE__ . '\JsonIgnoreProperties'); - - $this->assertInstanceOf(__NAMESPACE__ . '\JsonIgnoreProperties', $got); - $this->assertEquals(array(), $got->getNames()); - $this->assertTrue($got->getIgnoreUnknown()); - - } -} - -/** - * @JsonIgnoreProperties("blork") - */ -class JsonIgnorePropertiesTestVictimA -{ - -} - -/** - * @JsonIgnoreProperties({"blork", "blark"}) - */ -class JsonIgnorePropertiesTestVictimB -{ - -} - -/** - * @JsonIgnoreProperties(names={"blork", "blark"}) - */ -class JsonIgnorePropertiesTestVictimC -{ - -} - - -/** - * @JsonIgnoreProperties(ignoreUnknown=true) - */ -class JsonIgnorePropertiesTestVictimD -{ - -} - diff --git a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIncludeTest.php b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIncludeTest.php deleted file mode 100644 index 1530418..0000000 --- a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIncludeTest.php +++ /dev/null @@ -1,38 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; - -use Doctrine\Common\Annotations\AnnotationReader; -use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude; -use Doctrine\Common\Annotations\AnnotationRegistry; - -class JsonIncludeTest extends \PHPUnit_Framework_TestCase -{ - /** - * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude - */ - public function testBasic() - { - AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonInclude.php'); - - $annotationReader = new AnnotationReader(); - $got = $annotationReader->getClassAnnotation(new \ReflectionClass(__NAMESPACE__ . '\JsonIncludeTestVictim'), - __NAMESPACE__ . '\JsonInclude'); - - $this->assertInstanceOf(__NAMESPACE__ . '\JsonInclude', $got); - $this->assertEquals(JsonInclude::INCLUDE_ALWAYS, $got->getValue()); - - } -} - -/** - * @JsonInclude(JsonInclude::INCLUDE_ALWAYS) - */ -class JsonIncludeTestVictim -{ - -} diff --git a/tests/Weasel/JsonMarshaller/JsonMapperTest.php b/tests/Weasel/JsonMarshaller/JsonMapperTest.php deleted file mode 100644 index b45864f..0000000 --- a/tests/Weasel/JsonMarshaller/JsonMapperTest.php +++ /dev/null @@ -1,802 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller; - -use Weasel\JsonMarshaller\Config\JsonConfigProvider; - -class JsonMapperTest extends \PHPUnit_Framework_TestCase -{ - - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testReadStringBasicObject() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->readString(json_encode(array( - "blah" => "foo" - ) - ), - $mtc - ); - - $this->assertInstanceOf($mtc, $result); - $this->assertEquals(new MockTestClass("foo"), $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testChangeStrictDefault() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider, false); - - $result = $mapper->readString(json_encode(array( - "blah" => 1.0 - ) - ), - $mtc - ); - - $this->assertInstanceOf($mtc, $result); - $this->assertEquals(new MockTestClass("1"), $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testReadStringNull() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->readString(json_encode(null), - $mtc - ); - $this->assertEquals(null, $result); - - $result = $mapper->readString("", - $mtc - ); - - $this->assertEquals(null, $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testReadStringPrimitive() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->readString(json_encode("foo"), "string"); - - $this->assertInternalType("string", $result); - $this->assertEquals("foo", $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testReadStringArrayPrimitive() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->readString(json_encode(array("foo", "bar", "baz")), "string[]"); - - $this->assertInternalType("array", $result); - $this->assertEquals(array("foo", "bar", "baz"), $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testReadStringMapPrimitive() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->readString(json_encode(array("a" => 123, "b" => 34, "c" => 99)), "int[string]"); - - $this->assertInternalType("array", $result); - $this->assertEquals(array("a" => 123, "b" => 34, "c" => 99), $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testReadStringMapIntKeys() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->readString('{"77": 123, "33": 34, "22": 99}', "int[int]"); - - $this->assertInternalType("array", $result); - $this->assertEquals(array(77 => 123, 33 => 34, 22 => 99), $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testReadStringArrayOfBasicObject() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->readString(json_encode( - array( - array( - "blah" => "foo" - ), - array( - "blah" => "bar" - ), - array( - "blah" => "baz" - ), - ) - ), - $mtc . '[]' - ); - - $this->assertInternalType("array", $result); - $this->assertEquals(array(new MockTestClass("foo"), new MockTestClass("bar"), new MockTestClass("baz")), - $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testWriteStringBasicObject() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->writeArray(new MockTestClass("foo")); - - $this->assertEquals(array("blah" => "foo"), $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testWriteStringPrimitive() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->writeArray("blah"); - - $this->assertEquals("blah", $result); - } - - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testWriteStringArrayPrimitive() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->writeString(array("foo", "bar", "baz"), 'string[]'); - - $this->assertEquals('["foo", "bar", "baz"]', $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testWriteStringMapPrimitive() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->writeArray(array("a" => 123, "b" => 34, "c" => 99), 'int[string]'); - - $this->assertInternalType("array", $result); - $this->assertEquals(array("a" => 123, "b" => 34, "c" => 99), $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testWriteStringMapIntKeys() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->writeString(array(77 => 123, 42 => 34, 99 => 99), 'int[int]'); - - $expected = '{"77": 123, "42": 34, "99": 99}'; - - $this->assertEquals($expected, $result); - } - - /** - * Test to show that something that PHP would normally think is an "array" gets encoded as a map when we ask for that. - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testWriteStringMapIntKeysLooksLikeArray() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->writeString(array(123, 34, 99), 'int[int]'); - - $expected = '{"0": 123, "1": 34, "2": 99}'; - - $this->assertEquals($expected, $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testWriteStringArrayOfBasicObject() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->writeArray( - array( - new MockTestClass("foo"), - new MockTestClass("bar"), - new MockTestClass("baz"), - ), - $mtc . '[]' - ); - - $this->assertEquals(array(array("blah" => "foo"), array("blah" => "bar"), array("blah" => "baz")), $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testReadArrayOfBasicObject() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "blah", "string"); - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->readArray(json_encode( - array( - array( - "blah" => "foo" - ), - array( - "blah" => "bar" - ), - array( - "blah" => "baz" - ), - ) - ), - $mtc - ); - - $this->assertInternalType("array", $result); - $this->assertEquals(array(new MockTestClass("foo"), new MockTestClass("bar"), new MockTestClass("baz")), - $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testAnySetter() - { - - - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $config->deserialization = new Config\Deserialization\ClassDeserialization(); - $config->deserialization->anySetter = "anySetter"; - - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $result = $mapper->readString(json_encode(array( - "cows" => "blork", - ) - ), - $mtc - ); - - $this->assertInstanceOf($mtc, $result); - $this->assertEquals(array("cows" => "blork"), $result->any); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testAnyGetter() - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - - $config = new Config\ClassMarshaller(); - $config->serialization = new Config\Serialization\ClassSerialization(); - $config->serialization->anyGetter = "anyGetter"; - - $configProvider->fakeConfig[$mtc] = $config; - - $mapper = new JsonMapper($configProvider); - - $object = new MockTestClass(); - $object->any = array("cows" => "blork"); - - $result = $mapper->writeArray($object); - $this->assertInternalType("array", $result); - $this->assertEquals(array("cows" => "blork"), $result); - } - - protected function addPropConfig(Config\ClassMarshaller $config, $name, $type) - { - $prop = new Config\Serialization\DirectSerialization(); - $prop->type = $type; - $prop->property = $name; - $config->serialization->properties[$name] = $prop; - - $prop = new Config\Deserialization\DirectDeserialization(); - $prop->type = $type; - $prop->property = $name; - $config->deserialization->properties[$name] = $prop; - - return $config; - } - - /** - * Build a handy configuration for testing object inheritance using TypeInfo. - * - * @param string $typeInfoAs A string containing the name of one of the TypeInfo TI_AS_ constants. - * @param string $typeInfoUse A string containing the name of one of the TypeInfo TI_USE_ constants. - * @return MockedConfigProvider A config provider with a useful config for testing TypeInfo. - */ - protected function buildTypeInfoTestConfig($typeInfoAs, $typeInfoUse = "TI_USE_CLASS") - { - $configProvider = new MockedConfigProvider(); - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - $mtcb = 'Weasel\JsonMarshaller\MockTestClassB'; - $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; - $mtcd = 'Weasel\JsonMarshaller\MockTestClassD'; - - $config = new Config\ClassMarshaller(); - $config->serialization->typeInfo = new Config\Serialization\TypeInfo(); - $config->serialization->typeInfo->typeInfoAs = constant('\Weasel\JsonMarshaller\Config\Serialization\TypeInfo::' . $typeInfoAs); - $config->serialization->typeInfo->typeInfo = constant('\Weasel\JsonMarshaller\Config\Serialization\TypeInfo::' . $typeInfoUse); - $config->serialization->typeInfo->typeInfoProperty = "type"; - $config->serialization->typeInfo->subTypes[$mtcc] = $mtcc; - $config->serialization->typeInfo->subTypes[$mtcd] = $mtcd; - $config->deserialization->typeInfo = new Config\Deserialization\TypeInfo(); - $config->deserialization->typeInfo->typeInfoAs = constant('\Weasel\JsonMarshaller\Config\Deserialization\TypeInfo::' . $typeInfoAs); - $config->deserialization->typeInfo->typeInfo = constant('\Weasel\JsonMarshaller\Config\Deserialization\TypeInfo::' . $typeInfoUse); - $config->deserialization->typeInfo->typeInfoProperty = "type"; - $config->deserialization->typeInfo->subTypes[$mtcc] = $mtcc; - $config->deserialization->typeInfo->subTypes[$mtcd] = $mtcd; - $configProvider->fakeConfig[$mtcb] = $config; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "hi", "string"); - $configProvider->fakeConfig[$mtcc] = $config; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, "bi", "string"); - $configProvider->fakeConfig[$mtcd] = $config; - - $config = new Config\ClassMarshaller(); - $this->addPropConfig($config, 'blah', $mtcb); - $configProvider->fakeConfig[$mtc] = $config; - - return $configProvider; - - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testEncodeWrapperObject() - { - $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; - - $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_WRAPPER_OBJECT')); - - $object = new MockTestClass(); - $object->blah = new MockTestClassC("dog"); - - $expected = array( - "blah" => - array($mtcc => array("hi" => "dog")) - ); - $result = $mapper->writeArray($object); - $this->assertInternalType("array", $result); - $this->assertEquals($expected, $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testEncodeWrapperArray() - { - $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; - - $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_WRAPPER_ARRAY')); - - $object = new MockTestClass(); - $object->blah = new MockTestClassC("dog"); - - $expected = array( - "blah" => array( - $mtcc, - array("hi" => "dog") - ) - ); - $result = $mapper->writeArray($object); - $this->assertInternalType("array", $result); - $this->assertEquals($expected, $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testEncodeTypeinfoAsPropertyInArray() - { - $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; - $mtcd = 'Weasel\JsonMarshaller\MockTestClassD'; - - $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_PROPERTY')); - - $input = array(); - $arr = array(); - $object = new MockTestClass(); - $object->blah = new MockTestClassC("dog"); - $arr[] = $object; - $object = new MockTestClass(); - $object->blah = new MockTestClassD("car"); - $arr[] = $object; - $input[] = $arr; - $arr = array(); - $object = new MockTestClass(); - $object->blah = new MockTestClassD("wobble"); - $arr[] = $object; - $input[] = $arr; - $input[] = array(); - - $expected = array( - array( - array( - "blah" => array( - "hi" => "dog", - "type" => $mtcc, - ) - ), - array( - "blah" => array( - "bi" => "car", - "type" => $mtcd, - ) - ) - ), - array( - array( - "blah" => array( - "bi" => "wobble", - "type" => $mtcd, - ) - ), - ), - array() - ); - $result = $mapper->writeArray($input, $mtcc . '[][]'); - $this->assertEquals($expected, $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testEncodeTypeinfoAsProperty() - { - $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; - - $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_PROPERTY')); - - $object = new MockTestClass(); - $object->blah = new MockTestClassC("dog"); - - $expected = array( - "blah" => array( - "type" => $mtcc, - "hi" => "dog" - ) - ); - $result = $mapper->writeArray($object); - $this->assertInternalType("array", $result); - $this->assertEquals($expected, $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testDecodeTypeinfoAsProperty() - { - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; - - $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_PROPERTY')); - - $json = json_encode(array( - "blah" => array( - "type" => $mtcc, - "hi" => "dog" - ) - )); - - $expected = new MockTestClass(); - $expected->blah = new MockTestClassC("dog"); - - $result = $mapper->readString($json, $mtc); - $this->assertEquals($expected, $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testDecodeTypeinfoAsWrapperObject() - { - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; - - $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_WRAPPER_OBJECT')); - - $json = json_encode(array( - "blah" => array( - "$mtcc" => array("hi" => "dog") - ) - )); - - $expected = new MockTestClass(); - $expected->blah = new MockTestClassC("dog"); - - $result = $mapper->readString($json, $mtc); - $this->assertEquals($expected, $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - */ - public function testDecodeTypeinfoAsWrapperArray() - { - $mtc = 'Weasel\JsonMarshaller\MockTestClass'; - $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; - - $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_WRAPPER_ARRAY')); - - $json = json_encode(array( - "blah" => array( - $mtcc, - array("hi" => "dog") - ) - )); - - $expected = new MockTestClass(); - $expected->blah = new MockTestClassC("dog"); - - $result = $mapper->readString($json, $mtc); - $this->assertEquals($expected, $result); - } - - /** - * @covers \Weasel\JsonMarshaller\JsonMapper - * @expectedException \Weasel\JsonMarshaller\Exception\BadConfigurationException - * @expectedExceptionMessage is not an instantiable class - */ - public function testBadSubtypeOfInterface() - { - $configProvider = new MockedConfigProvider(); - $mti = 'Weasel\JsonMarshaller\MockTestInterface'; - - $config = new Config\ClassMarshaller(); - - $configProvider->fakeConfig[$mti] = $config; - - $mapper = new JsonMapper($configProvider); - - $mapper->readString(json_encode(array( - "blah" => "foo" - ) - ), - $mti - ); - - } - -} - -interface MockTestInterface -{ - -} - -class MockTestClass implements MockTestInterface -{ - public $any = array(); - - public $blah; - - public function anyGetter() - { - return $this->any; - } - - public function anySetter($key, $value) - { - $this->any[$key] = $value; - } - - public function __construct($blah = null) - { - $this->blah = $blah; - } -} - -class MockTestClassB -{ -} - -class MockTestClassC extends MockTestClassB -{ - public $hi; - - public function __construct($hi = "cat") - { - $this->hi = $hi; - } - -} - -class MockTestClassD extends MockTestClassB -{ - public $bi; - - public function __construct($bi = "stoat") - { - $this->bi = $bi; - } - -} - -class MockedConfigProvider implements JsonConfigProvider -{ - - /** - * @var Config\ClassMarshaller[] - */ - public $fakeConfig = array(); - - /** - * Obtain the config for a named class - * @param string $class The class to get the config for - * @throws \ReflectionException - * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found - */ - public function getConfig($class) - { - if (isset($this->fakeConfig[$class])) { - return $this->fakeConfig[$class]; - } - return null; - - } - - public function setCache($cache) - { - // TODO: Implement setCache() method. - } -} \ No newline at end of file diff --git a/tests/Weasel/JsonMarshaller/Types/BoolTypeTest.php b/tests/Weasel/JsonMarshaller/Types/BoolTypeTest.php deleted file mode 100644 index e38530e..0000000 --- a/tests/Weasel/JsonMarshaller/Types/BoolTypeTest.php +++ /dev/null @@ -1,139 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; - -use Weasel\JsonMarshaller\Exception\InvalidTypeException; -use Weasel\WeaselDefaultAnnotationDrivenFactory; - -class BoolTypeTest extends \PHPUnit_Framework_TestCase -{ - - - public function provideDataForEncode() - { - return array( - array(true, "true"), - array(false, "false") - ); - } - - protected $_mapper; - - protected function setUp() - { - parent::setUp(); - $factory = new WeaselDefaultAnnotationDrivenFactory(); - $this->_mapper = $factory->getJsonMapperInstance(); - } - - - /** - * @dataProvider provideDataForEncode - * @covers \Weasel\JsonMarshaller\Types\BoolType - */ - public function testEncodeBool($value, $expected) - { - - $handler = new BoolType(); - - $encoded = - $handler->encodeValue($value, - $this->_mapper - ); - - $this->assertInternalType("string", $encoded); - $this->assertEquals($expected, $encoded); - - } - - public function provideDataForDecode() - { - return array( - array(true, - true - ), - array(false, - false - ), - array("true", - true - ), - array("false", - false - ), - array(1, - true - ), - array(0, - false - ) - ); - } - - /** - * @dataProvider provideDataForDecode - * @covers \Weasel\JsonMarshaller\Types\BoolType - */ - public function testDecodeBool($value, $expected) - { - $handler = new BoolType(); - - $encoded = - $handler->decodeValue($value, - $this->_mapper, - true - ); - - $this->assertInternalType("bool", $encoded); - $this->assertEquals($expected, $encoded); - } - - public function provideBrokenDataForEncode() - { - return array_map(function ($a) { - return array($a); - }, - array( - "hi mum!", - "f00ff0f0abc", - "0xzz", - 7, - null - ) - ); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\BoolType - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotABoolEncode($value) - { - $handler = new BoolType(); - $handler->encodeValue($value, - $this->_mapper - ); - $this->fail("Should not get here"); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\BoolType - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotABoolDecode($value) - { - $handler = new BoolType(); - $handler->decodeValue($value, - $this->_mapper, - true - ); - $this->fail("Should not get here"); - } - -} diff --git a/tests/Weasel/JsonMarshaller/Types/DateTimeTypeTest.php b/tests/Weasel/JsonMarshaller/Types/DateTimeTypeTest.php deleted file mode 100644 index f96a2db..0000000 --- a/tests/Weasel/JsonMarshaller/Types/DateTimeTypeTest.php +++ /dev/null @@ -1,138 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; - -use Weasel\JsonMarshaller\Exception\InvalidTypeException; -use Weasel\WeaselDefaultAnnotationDrivenFactory; - -class DateTimeTypeTest extends \PHPUnit_Framework_TestCase -{ - - public function provideDataForEncode() - { - return array( - array(new \DateTime("2012-11-12 12:12:12", new \DateTimeZone("UTC")), - '"2012-11-12T12:12:12+0000"' - ), - ); - } - - protected $_mapper; - - protected function setUp() - { - parent::setUp(); - $factory = new WeaselDefaultAnnotationDrivenFactory(); - $this->_mapper = $factory->getJsonMapperInstance(); - } - - /** - * @dataProvider provideDataForEncode - * @covers \Weasel\JsonMarshaller\Types\DateTimeType - */ - public function testEncodeDateTime($value, $expected) - { - - $handler = new DateTimeType(); - - $encoded = - $handler->encodeValue($value, - $this->_mapper - ); - - $this->assertInternalType("string", $encoded); - $this->assertEquals($expected, $encoded); - - } - - public function provideDataForDecode() - { - return array( - array("2012-11-12T12:12:12+0000", - new \DateTime("2012-11-12 12:12:12", new \DateTimeZone("UTC")) - ), - ); - } - - /** - * @dataProvider provideDataForDecode - * @covers \Weasel\JsonMarshaller\Types\DateTimeType - * @param string $value - * @param \DateTime $expected - * @return void - */ - public function testDecodeDateTime($value, \DateTime $expected) - { - $handler = new DateTimeType(); - - $encoded = - $handler->decodeValue($value, - $this->_mapper, - true - ); - - $this->assertInstanceOf('\DateTime', $encoded); - $this->assertEquals($expected->format("U"), $encoded->format("U")); - } - - public function provideBrokenDataForEncode() - { - return array_map(function ($a) { - return array($a); - }, - array( - null, - 1, - "foo" - ) - ); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\DateTimeType - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotADateTimeEncode($value) - { - $handler = new DateTimeType(); - $handler->encodeValue($value, - $this->_mapper - ); - $this->fail("Should not get here"); - } - - public function provideBrokenDataForDecode() - { - return array_map(function ($a) { - return array($a); - }, - array( - null, - 1, - "foo", - "2012-01-02 11:11:11" - ) - ); - } - - /** - * @dataProvider provideBrokenDataForDecode - * @covers \Weasel\JsonMarshaller\Types\DateTimeType - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotADateTimeDecode($value) - { - $handler = new DateTimeType(); - $handler->decodeValue($value, - $this->_mapper, - true - ); - $this->fail("Should not get here"); - } - -} diff --git a/tests/Weasel/JsonMarshaller/Types/FloatTypeTest.php b/tests/Weasel/JsonMarshaller/Types/FloatTypeTest.php deleted file mode 100644 index 8b8ed00..0000000 --- a/tests/Weasel/JsonMarshaller/Types/FloatTypeTest.php +++ /dev/null @@ -1,132 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; - -use Weasel\JsonMarshaller\Exception\InvalidTypeException; -use Weasel\WeaselDefaultAnnotationDrivenFactory; - -class FloatTypeTest extends \PHPUnit_Framework_TestCase -{ - - public function provideDataForEncode() - { - return array( - array(2, '2', true), - array(1.2123123123, '1.2123123123', true), - array(3, '3', true), - array(1e8, '100000000', true), - array("123", '123', false), - array("0xaa", '170', false), - array("1e8", '100000000', false), - ); - } - - protected $_mapper; - - protected function setUp() - { - parent::setUp(); - $factory = new WeaselDefaultAnnotationDrivenFactory(); - $this->_mapper = $factory->getJsonMapperInstance(); - } - - /** - * @dataProvider provideDataForEncode - * @covers \Weasel\JsonMarshaller\Types\FloatType - */ - public function testEncodeFloat($value, $expected) - { - - $handler = new FloatType(); - - $encoded = - $handler->encodeValue($value, - $this->_mapper - ); - - $this->assertInternalType("string", $encoded); - $this->assertEquals($expected, $encoded); - - } - - /** - * @dataProvider provideDataForEncode - * @covers \Weasel\JsonMarshaller\Types\FloatType - */ - public function testDecodeFloat($value, $unused, $strict) - { - $handler = new FloatType(); - - $encoded = - $handler->decodeValue($value, - $this->_mapper, - false - ); - - $this->assertInternalType("float", $encoded); - $this->assertEquals($value, $encoded); - - try { - $handler->decodeValue($value, - $this->_mapper, - true - ); - if (!$strict) { - $this->fail("This should not have parsed with strict mode on"); - } - $this->assertInternalType("float", $encoded); - $this->assertEquals($value, $encoded); - } catch (InvalidTypeException $e) { - if ($strict) { - $this->fail("This should have parsed with strict mode on"); - } - } - } - - public function provideBrokenDataForEncode() - { - return array_map(function ($a) { - return array($a); - }, - array( - "hi mum!", - "f00ff0f0abc", - "0xzz" - ) - ); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\FloatType - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotAFloatEncode($value) - { - $handler = new FloatType(); - $handler->encodeValue($value, - $this->_mapper - ); - $this->fail("Should not get here"); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\FloatType - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotAFloatDecode($value) - { - $handler = new FloatType(); - $handler->decodeValue($value, - $this->_mapper, - true - ); - $this->fail("Should not get here"); - } - -} diff --git a/tests/Weasel/JsonMarshaller/Types/IntTypeTest.php b/tests/Weasel/JsonMarshaller/Types/IntTypeTest.php deleted file mode 100644 index b5b6967..0000000 --- a/tests/Weasel/JsonMarshaller/Types/IntTypeTest.php +++ /dev/null @@ -1,138 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; - -use Weasel\JsonMarshaller\Exception\InvalidTypeException; -use Weasel\WeaselDefaultAnnotationDrivenFactory; - -class IntTypeTest extends \PHPUnit_Framework_TestCase -{ - - public function provideDataForEncode() - { - return array( - array(2, '2'), - array(3, '3'), - array("123", '123'), - ); - } - - protected $_mapper; - - protected function setUp() - { - parent::setUp(); - $factory = new WeaselDefaultAnnotationDrivenFactory(); - $this->_mapper = $factory->getJsonMapperInstance(); - } - - /** - * @dataProvider provideDataForEncode - * @covers \Weasel\JsonMarshaller\Types\IntType - */ - public function testEncodeInt($value, $expected) - { - - $handler = new IntType(); - - $encoded = - $handler->encodeValue($value, - $this->_mapper - ); - - $this->assertInternalType("string", $encoded); - $this->assertEquals($expected, $encoded); - - } - - public function provideDataForDecode() - { - return array( - array(2, true), - array(3, true), - array("123", false), - ); - } - - /** - * @dataProvider provideDataForDecode - * @covers \Weasel\JsonMarshaller\Types\IntType - */ - public function testDecodeInt($value, $strict) - { - $handler = new IntType(); - - $encoded = - $handler->decodeValue($value, - $this->_mapper, - false - ); - - $this->assertInternalType("int", $encoded); - $this->assertEquals($value, $encoded); - - try { - $handler->decodeValue($value, - $this->_mapper, - true - ); - if (!$strict) { - $this->fail("This should not have parsed with strict mode on"); - } - $this->assertInternalType("int", $encoded); - $this->assertEquals($value, $encoded); - } catch (InvalidTypeException $e) { - if ($strict) { - $this->fail("This should have parsed with strict mode on"); - } - } - } - - public function provideBrokenDataForEncode() - { - return array_map(function ($a) { - return array($a); - }, - array( - "hi mum!", - "f00ff0f0abc", - "0xzz", - 1.2 - ) - ); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\IntType - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotAIntEncode($value) - { - $handler = new IntType(); - $handler->encodeValue($value, - $this->_mapper - ); - $this->fail("Should not get here"); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\IntType - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotAIntDecode($value) - { - $handler = new IntType(); - $handler->decodeValue($value, - $this->_mapper, - true - ); - $this->fail("Should not get here"); - } - -} diff --git a/tests/Weasel/JsonMarshaller/Types/OldTypeWrapperTest.php b/tests/Weasel/JsonMarshaller/Types/OldTypeWrapperTest.php deleted file mode 100644 index c315f3a..0000000 --- a/tests/Weasel/JsonMarshaller/Types/OldTypeWrapperTest.php +++ /dev/null @@ -1,150 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; - -use Weasel\JsonMarshaller\Exception\InvalidTypeException; -use Weasel\JsonMarshaller\JsonMapper; -use Weasel\WeaselDefaultAnnotationDrivenFactory; - -class OldTypeWrapperTest extends \PHPUnit_Framework_TestCase -{ - - public function provideDataForEncode() - { - return array( - array(2, '2'), - array(3, '3'), - array("123", '123'), - ); - } - - protected $_mapper; - - protected function setUp() - { - parent::setUp(); - $factory = new WeaselDefaultAnnotationDrivenFactory(); - $this->_mapper = $factory->getJsonMapperInstance(); - } - - /** - * @dataProvider provideDataForEncode - * @covers \Weasel\JsonMarshaller\Types\OldTypeWrapper - */ - public function testEncodeInt($value, $expected) - { - - $handler = new OldTypeWrapper(new OldIntType()); - - $encoded = - $handler->encodeValue($value, - $this->_mapper - ); - - $this->assertInternalType("string", $encoded); - $this->assertEquals($expected, $encoded); - - } - - public function provideDataForDecode() - { - return array_map(function ($a) { - return array($a); - }, - array( - 2, - 3, - "123", - ) - ); - } - - /** - * @dataProvider provideDataForDecode - * @covers \Weasel\JsonMarshaller\Types\OldTypeWrapper - */ - public function testDecodeInt($value) - { - $handler = new OldTypeWrapper(new OldIntType()); - - $encoded = - $handler->decodeValue($value, - $this->_mapper, - true - ); - - $this->assertInternalType("int", $encoded); - $this->assertEquals($value, $encoded); - } - - public function provideBrokenDataForEncode() - { - return array_map(function ($a) { - return array($a); - }, - array( - "hi mum!", - "f00ff0f0abc", - "0xzz", - 1.2 - ) - ); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\OldTypeWrapper - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotAIntEncode($value) - { - $handler = new OldTypeWrapper(new OldIntType()); - $handler->encodeValue($value, - $this->_mapper - ); - $this->fail("Should not get here"); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\OldTypeWrapper - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotAIntDecode($value) - { - $handler = new OldTypeWrapper(new OldIntType()); - $handler->decodeValue($value, - $this->_mapper, - true - ); - $this->fail("Should not get here"); - } - -} - -class OldIntType implements Type -{ - - protected function checkAndCastValue($value) - { - if (!is_int($value) && !ctype_digit($value)) { - throw new InvalidTypeException("integer", $value); - } - return (int)$value; - } - - public function decodeValue($value, JsonMapper $mapper) - { - return $this->checkAndCastValue($value); - } - - public function encodeValue($value, JsonMapper $mapper) - { - return $this->checkAndCastValue($value); - } - -} diff --git a/tests/Weasel/JsonMarshaller/Types/StringTypeTest.php b/tests/Weasel/JsonMarshaller/Types/StringTypeTest.php deleted file mode 100644 index 690a45c..0000000 --- a/tests/Weasel/JsonMarshaller/Types/StringTypeTest.php +++ /dev/null @@ -1,110 +0,0 @@ - - * @copyright Copyright (c) 2012, Moo Print Ltd. - * @license ISC - */ -namespace Weasel\JsonMarshaller\Types; - -use Weasel\JsonMarshaller\Exception\InvalidTypeException; -use Weasel\WeaselDefaultAnnotationDrivenFactory; - -class StringTypeTest extends \PHPUnit_Framework_TestCase -{ - - public function provideDataForEncode() - { - return array( - array("foo", '"foo"'), - array("fubar", '"fubar"'), - array('flibble"flobble', '"flibble\"flobble"') - ); - } - - protected $_mapper; - - protected function setUp() - { - parent::setUp(); - $factory = new WeaselDefaultAnnotationDrivenFactory(); - $this->_mapper = $factory->getJsonMapperInstance(); - } - - /** - * @dataProvider provideDataForEncode - * @covers \Weasel\JsonMarshaller\Types\StringType - */ - public function testEncodeString($value, $expected) - { - - $handler = new StringType(); - - $encoded = - $handler->encodeValue($value, - $this->_mapper - ); - - $this->assertInternalType("string", $encoded); - $this->assertEquals($expected, $encoded); - - } - - /** - * @dataProvider provideDataForEncode - * @covers \Weasel\JsonMarshaller\Types\StringType - */ - public function testDecodeString($value) - { - $handler = new StringType(); - - $encoded = - $handler->decodeValue($value, - $this->_mapper, - true - ); - - $this->assertInternalType("string", $encoded); - $this->assertEquals($value, $encoded); - } - - public function provideBrokenDataForEncode() - { - return array( - array(1.2, '"1.2"'), - array(7, '"7"'), - array(false, '""'), - array(true, '"1"'), - array(null, '""') - ); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\StringType - */ - public function testNotAStringEncode($value, $expected) - { - $handler = new StringType(); - $encoded = $handler->encodeValue($value, - $this->_mapper - ); - $this->assertInternalType("string", $encoded); - $this->assertEquals($expected, $encoded); - } - - /** - * @dataProvider provideBrokenDataForEncode - * @covers \Weasel\JsonMarshaller\Types\StringType - * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException - */ - public function testNotAStringDecode($value) - { - $handler = new StringType(); - $handler->decodeValue($value, - $this->_mapper, - true - ); - $this->fail("Should not get here"); - } - -} diff --git a/tests/benchmark.php b/tests/benchmark.php deleted file mode 100644 index bb5cb5a..0000000 --- a/tests/benchmark.php +++ /dev/null @@ -1,21 +0,0 @@ -getJsonMapperInstance(); -$testString = $weasel->writeString($testData, '\Weasel\JsonMarshaller\Config\ClassMarshaller[string]'); - -$st = microtime(true); -for ($i = 0; $i < 100; $i++) { - $weasel->writeString($testData, '\Weasel\JsonMarshaller\Config\ClassMarshaller[string]'); -} -print "Writes took: " . (microtime(true) - $st) . "ms\n"; - -$st = microtime(true); -for ($i = 0; $i < 100; $i++) { - $weasel->readString($testString, '\Weasel\JsonMarshaller\Config\ClassMarshaller[string]'); -} -print "Reads took: " . (microtime(true) - $st) . "ms\n"; diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index 897cde1..0000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,12 +0,0 @@ - Date: Mon, 8 Apr 2019 11:11:51 +0100 Subject: [PATCH 2/7] attempt for 7.x --- .gitignore | 5 + .travis.yml | 9 + LICENSE | 13 + README.md | 42 + bin/BuildBootstrapConfigs.php | 63 ++ bin/buildJsonConfig.php | 19 + composer.json | 28 + .../Annotation/AnnotationConfigProvider.php | 18 + .../Annotation/AnnotationConfigurator.php | 203 +++++ lib/Weasel/Annotation/AnnotationReader.php | 251 ++++++ .../Annotation/AnnotationReaderFactory.php | 63 ++ .../ArrayCachingAnnotationConfigurator.php | 29 + lib/Weasel/Annotation/Config/Annotation.php | 223 +++++ .../Annotation/Config/AnnotationConfig.php | 50 ++ .../Config/Annotations/Annotation.php | 42 + .../Config/Annotations/AnnotationCreator.php | 40 + .../Annotation/Config/Annotations/Enum.php | 36 + .../Config/Annotations/Parameter.php | 50 ++ .../Config/Annotations/Property.php | 41 + .../Annotation/Config/BuiltInsProvider.php | 62 ++ lib/Weasel/Annotation/Config/Enum.php | 48 ++ lib/Weasel/Annotation/Config/Param.php | 62 ++ lib/Weasel/Annotation/Config/Property.php | 47 + lib/Weasel/Annotation/DocblockLexer.php | 263 ++++++ lib/Weasel/Annotation/DocblockParser.php | 473 +++++++++++ lib/Weasel/Annotation/PhpParser.php | 255 ++++++ .../WeaslDefaultAnnotationDrivenContext.xml | 38 + .../BuildJsonMapperJsonConfigCommand.php | 104 +++ .../BuildXmlMapperJsonConfigCommand.php | 104 +++ .../Common/Annotation/IAnnotationReader.php | 72 ++ .../Annotation/IAnnotationReaderFactory.php | 24 + lib/Weasel/Common/Cache/ApcCache.php | 53 ++ lib/Weasel/Common/Cache/ArrayCache.php | 50 ++ lib/Weasel/Common/Cache/Cache.php | 80 ++ .../Common/Cache/CacheAwareInterface.php | 12 + lib/Weasel/Common/Cache/CacheException.php | 22 + .../Common/Cache/Exception/BackingFailure.php | 14 + lib/Weasel/Common/Logger/FileLogger.php | 55 ++ lib/Weasel/Common/Logger/Logger.php | 22 + .../Common/Utils/NoUndeclaredProperties.php | 33 + lib/Weasel/Common/Utils/ReflectionUtils.php | 70 ++ .../DoctrineAnnotationReaderAdapter.php | 157 ++++ .../DoctrineAnnotationReaderFactory.php | 45 + .../DoctrineAnnotation/WeaselCacheAdapter.php | 114 +++ .../Config/AnnotationDriver.php | 96 +++ .../Config/Annotations/JsonAnyGetter.php | 20 + .../Config/Annotations/JsonAnySetter.php | 20 + .../Config/Annotations/JsonCreator.php | 44 + .../Annotations/JsonIgnoreProperties.php | 53 ++ .../Config/Annotations/JsonInclude.php | 55 ++ .../Config/Annotations/JsonProperty.php | 58 ++ .../Config/Annotations/JsonSubTypes.php | 45 + .../Config/Annotations/JsonSubTypes/Type.php | 57 ++ .../Config/Annotations/JsonTypeInfo.php | 123 +++ .../Config/Annotations/JsonTypeName.php | 39 + .../Config/ArrayCachingAnnotationDriver.php | 27 + .../Config/ClassAnnotationDriver.php | 620 ++++++++++++++ .../JsonMarshaller/Config/ClassMarshaller.php | 42 + .../Deserialization/ClassDeserialization.php | 79 ++ .../Config/Deserialization/Creator.php | 36 + .../Deserialization/DelegateCreator.php | 24 + .../Deserialization/DirectDeserialization.php | 34 + .../Config/Deserialization/Feature.php | 31 + .../Config/Deserialization/Param.php | 30 + .../Deserialization/PropertyCreator.php | 29 + .../PropertyDeserialization.php | 69 ++ .../Deserialization/SetterDeserialization.php | 36 + .../Config/Deserialization/TypeInfo.php | 65 ++ .../DoctrineAnnotations/JsonAnyGetter.php | 21 + .../DoctrineAnnotations/JsonAnySetter.php | 21 + .../DoctrineAnnotations/JsonCreator.php | 51 ++ .../JsonIgnoreProperties.php | 68 ++ .../DoctrineAnnotations/JsonInclude.php | 38 + .../DoctrineAnnotations/JsonProperty.php | 77 ++ .../DoctrineAnnotations/JsonSubTypes.php | 35 + .../DoctrineAnnotations/JsonSubTypes/Type.php | 49 ++ .../DoctrineAnnotations/JsonTypeInfo.php | 81 ++ .../DoctrineAnnotations/JsonTypeName.php | 35 + .../Config/IAnnotations/IJsonAnyGetter.php | 18 + .../Config/IAnnotations/IJsonAnySetter.php | 18 + .../Config/IAnnotations/IJsonCreator.php | 20 + .../IAnnotations/IJsonIgnoreProperties.php | 25 + .../Config/IAnnotations/IJsonInclude.php | 25 + .../Config/IAnnotations/IJsonProperty.php | 36 + .../Config/IAnnotations/IJsonSubTypes.php | 21 + .../Config/IAnnotations/IJsonTypeInfo.php | 63 ++ .../Config/IAnnotations/IJsonTypeName.php | 21 + .../IAnnotations/JsonSubTypes/IType.php | 26 + .../Config/JsonConfigProvider.php | 22 + .../Config/MultiConfigProvider.php | 46 + .../Config/PropertyConfigProvider.php | 45 + .../Serialization/ClassSerialization.php | 51 ++ .../Serialization/DirectSerialization.php | 35 + .../Serialization/GetterSerialization.php | 40 + .../Serialization/PropertySerialization.php | 68 ++ .../Config/Serialization/TypeInfo.php | 53 ++ .../Config/SerializedConfigProvider.php | 45 + .../JsonMarshaller/Config/Type/ListType.php | 23 + .../JsonMarshaller/Config/Type/MapType.php | 36 + .../JsonMarshaller/Config/Type/ScalarType.php | 28 + .../JsonMarshaller/Config/Type/Type.php | 25 + .../JsonMarshaller/Config/Type/TypeParser.php | 45 + .../JsonMarshaller/Config/bootstrap.cnf | 1 + .../Exception/BadConfigurationException.php | 13 + .../Exception/InvalidTypeException.php | 66 ++ .../Exception/JsonMarshallerException.php | 13 + .../Exception/UnknownPropertyException.php | 8 + lib/Weasel/JsonMarshaller/JsonMapper.php | 694 +++++++++++++++ lib/Weasel/JsonMarshaller/Types/BoolType.php | 36 + .../JsonMarshaller/Types/DateTimeType.php | 53 ++ lib/Weasel/JsonMarshaller/Types/FloatType.php | 37 + lib/Weasel/JsonMarshaller/Types/IntType.php | 41 + lib/Weasel/JsonMarshaller/Types/JsonType.php | 30 + .../JsonMarshaller/Types/OldTypeWrapper.php | 29 + .../JsonMarshaller/Types/StringType.php | 32 + lib/Weasel/JsonMarshaller/Types/Type.php | 34 + .../WeaselDefaultAnnotationDrivenFactory.php | 181 ++++ .../WeaselDoctrineAnnotationDrivenFactory.php | 197 +++++ lib/Weasel/WeaselFactory.php | 30 + lib/Weasel/WeaselJsonConfigDrivenFactory.php | 161 ++++ .../XmlMarshaller/Config/AnnotationDriver.php | 93 ++ .../Config/Annotations/XmlAttribute.php | 65 ++ .../Config/Annotations/XmlDiscriminator.php | 45 + .../Annotations/XmlDiscriminatorValue.php | 45 + .../Config/Annotations/XmlElement.php | 74 ++ .../Config/Annotations/XmlElementRef.php | 56 ++ .../Config/Annotations/XmlElementRefs.php | 46 + .../Config/Annotations/XmlElementWrapper.php | 65 ++ .../Config/Annotations/XmlRootElement.php | 46 + .../Config/Annotations/XmlSeeAlso.php | 42 + .../Config/Annotations/XmlType.php | 105 +++ .../Config/ClassAnnotationDriver.php | 448 ++++++++++ .../XmlMarshaller/Config/ClassMarshaller.php | 26 + .../XmlMarshaller/Config/ConfigProvider.php | 18 + .../AttributeDeserialization.php | 20 + .../Deserialization/ClassDeserialization.php | 85 ++ .../Deserialization/DirectDeserialization.php | 25 + .../ElementDeserialization.php | 49 ++ .../Config/Deserialization/ElementWrapper.php | 38 + .../Config/Deserialization/Param.php | 25 + .../PropertyDeserialization.php | 37 + .../Deserialization/SetterDeserialization.php | 25 + .../Config/Deserialization/TypeInfo.php | 58 ++ .../DoctrineAnnotations/XmlAttribute.php | 61 ++ .../DoctrineAnnotations/XmlDiscriminator.php | 35 + .../XmlDiscriminatorValue.php | 35 + .../Config/DoctrineAnnotations/XmlElement.php | 71 ++ .../DoctrineAnnotations/XmlElementRef.php | 51 ++ .../DoctrineAnnotations/XmlElementRefs.php | 41 + .../DoctrineAnnotations/XmlElementWrapper.php | 62 ++ .../DoctrineAnnotations/XmlRootElement.php | 41 + .../Config/DoctrineAnnotations/XmlSeeAlso.php | 35 + .../Config/DoctrineAnnotations/XmlType.php | 83 ++ .../Config/IAnnotations/IXmlAttribute.php | 19 + .../Config/IAnnotations/IXmlDiscriminator.php | 15 + .../IAnnotations/IXmlDiscriminatorValue.php | 18 + .../Config/IAnnotations/IXmlElement.php | 23 + .../Config/IAnnotations/IXmlElementRef.php | 19 + .../Config/IAnnotations/IXmlElementRefs.php | 20 + .../IAnnotations/IXmlElementWrapper.php | 21 + .../Config/IAnnotations/IXmlRootElement.php | 17 + .../Config/IAnnotations/IXmlSeeAlso.php | 18 + .../Config/IAnnotations/XmlType.php | 35 + .../Config/PropertyConfigProvider.php | 45 + .../Serialization/ClassSerialization.php | 35 + .../Serialization/DirectSerialization.php | 25 + .../Serialization/GetterSerialization.php | 25 + .../Serialization/PropertySerialization.php | 41 + .../Config/Serialization/TypeInfo.php | 47 + lib/Weasel/XmlMarshaller/XmlMapper.php | 476 +++++++++++ lib/WeaselAutoloader.php | 31 + .../Annotation/AnnotationConfiguratorTest.php | 654 ++++++++++++++ .../Annotation/AnnotationReaderTest.php | 33 + tests/Weasel/Annotation/DocblockLexerTest.php | 255 ++++++ .../Weasel/Annotation/DocblockParserTest.php | 599 +++++++++++++ tests/Weasel/Annotation/PHPParserTest.php | 80 ++ tests/Weasel/Annotation/TestDocblock.txt | 9 + .../Annotation/resources/AnnotatedClass.php | 8 + .../resources/MultipleNamespace.php | 30 + .../resources/NamespacedShorthand.php | 16 + .../Annotation/resources/NoDocBlock.php | 5 + .../Annotation/resources/NoNamespace.php | 11 + .../Annotation/resources/PHPGolfNamespace.php | 19 + .../Annotation/resources/SimpleNamespaced.php | 24 + .../resources/SimpleNamespacedExtends.php | 22 + .../DoctrineAnnotationReaderFactoryTest.php | 76 ++ .../Config/Annotations/JsonCreatorTest.php | 101 +++ .../Annotations/JsonIgnorePropertiesTest.php | 105 +++ .../Config/Annotations/JsonIncludeTest.php | 108 +++ .../Config/Annotations/JsonPropertyTest.php | 113 +++ .../Annotations/JsonSubTypes/TypeTest.php | 104 +++ .../Config/Annotations/JsonSubTypesTest.php | 103 +++ .../Config/Annotations/JsonTypeInfoTest.php | 126 +++ .../Config/Annotations/JsonTypeNameTest.php | 96 +++ .../Config/ClassAnnotationDriverTest.php | 106 +++ .../DoctrineAnnotations/JsonAnyGetterTest.php | 45 + .../DoctrineAnnotations/JsonAnySetterTest.php | 45 + .../DoctrineAnnotations/JsonCreatorTest.php | 106 +++ .../JsonIgnorePropertiesTest.php | 114 +++ .../DoctrineAnnotations/JsonIncludeTest.php | 38 + .../Weasel/JsonMarshaller/JsonMapperTest.php | 802 ++++++++++++++++++ .../JsonMarshaller/Types/BoolTypeTest.php | 139 +++ .../JsonMarshaller/Types/DateTimeTypeTest.php | 138 +++ .../JsonMarshaller/Types/FloatTypeTest.php | 133 +++ .../JsonMarshaller/Types/IntTypeTest.php | 138 +++ .../Types/OldTypeWrapperTest.php | 150 ++++ .../JsonMarshaller/Types/StringTypeTest.php | 110 +++ tests/benchmark.php | 21 + tests/bootstrap.php | 12 + 209 files changed, 15978 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 bin/BuildBootstrapConfigs.php create mode 100644 bin/buildJsonConfig.php create mode 100644 composer.json create mode 100644 lib/Weasel/Annotation/AnnotationConfigProvider.php create mode 100644 lib/Weasel/Annotation/AnnotationConfigurator.php create mode 100644 lib/Weasel/Annotation/AnnotationReader.php create mode 100644 lib/Weasel/Annotation/AnnotationReaderFactory.php create mode 100644 lib/Weasel/Annotation/ArrayCachingAnnotationConfigurator.php create mode 100644 lib/Weasel/Annotation/Config/Annotation.php create mode 100644 lib/Weasel/Annotation/Config/AnnotationConfig.php create mode 100644 lib/Weasel/Annotation/Config/Annotations/Annotation.php create mode 100644 lib/Weasel/Annotation/Config/Annotations/AnnotationCreator.php create mode 100644 lib/Weasel/Annotation/Config/Annotations/Enum.php create mode 100644 lib/Weasel/Annotation/Config/Annotations/Parameter.php create mode 100644 lib/Weasel/Annotation/Config/Annotations/Property.php create mode 100644 lib/Weasel/Annotation/Config/BuiltInsProvider.php create mode 100644 lib/Weasel/Annotation/Config/Enum.php create mode 100644 lib/Weasel/Annotation/Config/Param.php create mode 100644 lib/Weasel/Annotation/Config/Property.php create mode 100644 lib/Weasel/Annotation/DocblockLexer.php create mode 100644 lib/Weasel/Annotation/DocblockParser.php create mode 100644 lib/Weasel/Annotation/PhpParser.php create mode 100644 lib/Weasel/BounceContexts/WeaslDefaultAnnotationDrivenContext.xml create mode 100644 lib/Weasel/Command/BuildJsonMapperJsonConfigCommand.php create mode 100644 lib/Weasel/Command/BuildXmlMapperJsonConfigCommand.php create mode 100644 lib/Weasel/Common/Annotation/IAnnotationReader.php create mode 100644 lib/Weasel/Common/Annotation/IAnnotationReaderFactory.php create mode 100644 lib/Weasel/Common/Cache/ApcCache.php create mode 100644 lib/Weasel/Common/Cache/ArrayCache.php create mode 100644 lib/Weasel/Common/Cache/Cache.php create mode 100644 lib/Weasel/Common/Cache/CacheAwareInterface.php create mode 100644 lib/Weasel/Common/Cache/CacheException.php create mode 100644 lib/Weasel/Common/Cache/Exception/BackingFailure.php create mode 100644 lib/Weasel/Common/Logger/FileLogger.php create mode 100644 lib/Weasel/Common/Logger/Logger.php create mode 100644 lib/Weasel/Common/Utils/NoUndeclaredProperties.php create mode 100644 lib/Weasel/Common/Utils/ReflectionUtils.php create mode 100644 lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderAdapter.php create mode 100644 lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactory.php create mode 100644 lib/Weasel/DoctrineAnnotation/WeaselCacheAdapter.php create mode 100644 lib/Weasel/JsonMarshaller/Config/AnnotationDriver.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnyGetter.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnySetter.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonCreator.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonIgnoreProperties.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonInclude.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonProperty.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/Type.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfo.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeName.php create mode 100644 lib/Weasel/JsonMarshaller/Config/ArrayCachingAnnotationDriver.php create mode 100644 lib/Weasel/JsonMarshaller/Config/ClassAnnotationDriver.php create mode 100644 lib/Weasel/JsonMarshaller/Config/ClassMarshaller.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/ClassDeserialization.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/Creator.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/DelegateCreator.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/DirectDeserialization.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/Feature.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/Param.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyCreator.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyDeserialization.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/SetterDeserialization.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Deserialization/TypeInfo.php create mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetter.php create mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetter.php create mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php create mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php create mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonInclude.php create mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php create mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes.php create mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes/Type.php create mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeInfo.php create mode 100644 lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeName.php create mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnyGetter.php create mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnySetter.php create mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonCreator.php create mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonIgnoreProperties.php create mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonInclude.php create mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonProperty.php create mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonSubTypes.php create mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeInfo.php create mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeName.php create mode 100644 lib/Weasel/JsonMarshaller/Config/IAnnotations/JsonSubTypes/IType.php create mode 100644 lib/Weasel/JsonMarshaller/Config/JsonConfigProvider.php create mode 100644 lib/Weasel/JsonMarshaller/Config/MultiConfigProvider.php create mode 100644 lib/Weasel/JsonMarshaller/Config/PropertyConfigProvider.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Serialization/ClassSerialization.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Serialization/DirectSerialization.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Serialization/GetterSerialization.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Serialization/PropertySerialization.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Serialization/TypeInfo.php create mode 100644 lib/Weasel/JsonMarshaller/Config/SerializedConfigProvider.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Type/ListType.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Type/MapType.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Type/ScalarType.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Type/Type.php create mode 100644 lib/Weasel/JsonMarshaller/Config/Type/TypeParser.php create mode 100644 lib/Weasel/JsonMarshaller/Config/bootstrap.cnf create mode 100644 lib/Weasel/JsonMarshaller/Exception/BadConfigurationException.php create mode 100644 lib/Weasel/JsonMarshaller/Exception/InvalidTypeException.php create mode 100644 lib/Weasel/JsonMarshaller/Exception/JsonMarshallerException.php create mode 100644 lib/Weasel/JsonMarshaller/Exception/UnknownPropertyException.php create mode 100644 lib/Weasel/JsonMarshaller/JsonMapper.php create mode 100644 lib/Weasel/JsonMarshaller/Types/BoolType.php create mode 100644 lib/Weasel/JsonMarshaller/Types/DateTimeType.php create mode 100644 lib/Weasel/JsonMarshaller/Types/FloatType.php create mode 100644 lib/Weasel/JsonMarshaller/Types/IntType.php create mode 100644 lib/Weasel/JsonMarshaller/Types/JsonType.php create mode 100644 lib/Weasel/JsonMarshaller/Types/OldTypeWrapper.php create mode 100644 lib/Weasel/JsonMarshaller/Types/StringType.php create mode 100644 lib/Weasel/JsonMarshaller/Types/Type.php create mode 100644 lib/Weasel/WeaselDefaultAnnotationDrivenFactory.php create mode 100644 lib/Weasel/WeaselDoctrineAnnotationDrivenFactory.php create mode 100644 lib/Weasel/WeaselFactory.php create mode 100644 lib/Weasel/WeaselJsonConfigDrivenFactory.php create mode 100644 lib/Weasel/XmlMarshaller/Config/AnnotationDriver.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlAttribute.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminator.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminatorValue.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlElement.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRef.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRefs.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementWrapper.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlRootElement.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlSeeAlso.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Annotations/XmlType.php create mode 100644 lib/Weasel/XmlMarshaller/Config/ClassAnnotationDriver.php create mode 100644 lib/Weasel/XmlMarshaller/Config/ClassMarshaller.php create mode 100644 lib/Weasel/XmlMarshaller/Config/ConfigProvider.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/AttributeDeserialization.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/ClassDeserialization.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/DirectDeserialization.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/ElementDeserialization.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/ElementWrapper.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/Param.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/PropertyDeserialization.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/SetterDeserialization.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Deserialization/TypeInfo.php create mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlAttribute.php create mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminator.php create mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminatorValue.php create mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElement.php create mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRef.php create mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRefs.php create mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementWrapper.php create mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlRootElement.php create mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlSeeAlso.php create mode 100644 lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlType.php create mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlAttribute.php create mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminator.php create mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminatorValue.php create mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElement.php create mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRef.php create mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRefs.php create mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementWrapper.php create mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlRootElement.php create mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlSeeAlso.php create mode 100644 lib/Weasel/XmlMarshaller/Config/IAnnotations/XmlType.php create mode 100644 lib/Weasel/XmlMarshaller/Config/PropertyConfigProvider.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Serialization/ClassSerialization.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Serialization/DirectSerialization.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Serialization/GetterSerialization.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Serialization/PropertySerialization.php create mode 100644 lib/Weasel/XmlMarshaller/Config/Serialization/TypeInfo.php create mode 100644 lib/Weasel/XmlMarshaller/XmlMapper.php create mode 100644 lib/WeaselAutoloader.php create mode 100644 tests/Weasel/Annotation/AnnotationConfiguratorTest.php create mode 100644 tests/Weasel/Annotation/AnnotationReaderTest.php create mode 100644 tests/Weasel/Annotation/DocblockLexerTest.php create mode 100644 tests/Weasel/Annotation/DocblockParserTest.php create mode 100644 tests/Weasel/Annotation/PHPParserTest.php create mode 100644 tests/Weasel/Annotation/TestDocblock.txt create mode 100644 tests/Weasel/Annotation/resources/AnnotatedClass.php create mode 100644 tests/Weasel/Annotation/resources/MultipleNamespace.php create mode 100644 tests/Weasel/Annotation/resources/NamespacedShorthand.php create mode 100644 tests/Weasel/Annotation/resources/NoDocBlock.php create mode 100644 tests/Weasel/Annotation/resources/NoNamespace.php create mode 100644 tests/Weasel/Annotation/resources/PHPGolfNamespace.php create mode 100644 tests/Weasel/Annotation/resources/SimpleNamespaced.php create mode 100644 tests/Weasel/Annotation/resources/SimpleNamespacedExtends.php create mode 100644 tests/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactoryTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetterTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetterTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreatorTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnorePropertiesTest.php create mode 100644 tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIncludeTest.php create mode 100644 tests/Weasel/JsonMarshaller/JsonMapperTest.php create mode 100644 tests/Weasel/JsonMarshaller/Types/BoolTypeTest.php create mode 100644 tests/Weasel/JsonMarshaller/Types/DateTimeTypeTest.php create mode 100644 tests/Weasel/JsonMarshaller/Types/FloatTypeTest.php create mode 100644 tests/Weasel/JsonMarshaller/Types/IntTypeTest.php create mode 100644 tests/Weasel/JsonMarshaller/Types/OldTypeWrapperTest.php create mode 100644 tests/Weasel/JsonMarshaller/Types/StringTypeTest.php create mode 100644 tests/benchmark.php create mode 100644 tests/bootstrap.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1432d60 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea/ +atlassian-ide-plugin.xml +vendor/ +composer.lock +*.iml \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..09d7bfe --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: php +php: + - "7.3" + - "7.2" + - "7.1" + - "7.0" + - "5.6" +before_script: composer install -n --dev +script: "phpunit --coverage-text --bootstrap ./tests/bootstrap.php tests" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..da13ce2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2012, Moo Print Ltd. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..eab642b --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +PHP Weasel +========== +[![Build Status](https://travis-ci.org/moodev/php-weasel.png)](https://travis-ci.org/moodev/php-weasel) + +Weasel is an object marshalling library for PHP supporting JSON and XML. Marshalling is, by default, configured using “annotations”, driven by the `Doctrine\Common\Annotation` library. + +It also includes its own Annotation library, `Weasel\Annotation`, but this is considered deprecated in favour of using Doctrine. + +The latest version can be found here: https://github.com/moodev/php-weasel + +The documentation can be found here: https://github.com/moodev/php-weasel/wiki + +Installation +------------ + +If you can, use [composer](http://getcomposer.org/). If you can't, you'll find the list of dependencies in [composer.json](./composer.json). + +Usage +----- + +Annotate the classes you want to serialize/deserialize (see the documentation.) + +Then: +```php +$factory = new WeaselDoctrineAnnotationDrivenFactory(); +// optionally: + $factory->setCache($cacheInstance); + $factory->setLogger($psr3LoggerInstance); + +$mapper = $factory->getJsonMapperInstance(); +$thing = $mapper->readString($json, $typeToDecodeTo); +$backToJson = $mapper->writeString($thing); +``` +Why? +---- +`json_decode()` decodes to arrays or stdObj. Weasel, while making use of `json_decode()` internally, maps to objects; it's basically a configuration driven Object Mapper for JSON. + +Meanwhile, `json_encode()` gives you no fine grained control over how your data gets serialized to JSON. You can't disable marshalling of fields, you can't add typing information without adding it to your classes, and, most annoyingly, you don't have any control over how `array()` gets mapped on a field-by-field basis. Weasel allows you to configure how fields are marshalled on a per-field level: if you've got an array that should always be mapped as a JSON object, while other arrays need to be mapped as an array, you can have just that. + +The `XmlMarshaller` just seemed like a good idea at the time. It probably wasn't. It's incomplete and unloved. As soon as I find a better approach to the problem, it'll be deprecated. + +This project spawned from work on [moo-php](https://github.com/JonathanO/moo-php), a client library for the moo.com API. After writing serialization/deserialization code that was specific to that object structure, I realised that a general purpose, configurable marshaller, similar to Jackson in the Java world, would be rather useful. Weasel is the result. diff --git a/bin/BuildBootstrapConfigs.php b/bin/BuildBootstrapConfigs.php new file mode 100644 index 0000000..8820a1c --- /dev/null +++ b/bin/BuildBootstrapConfigs.php @@ -0,0 +1,63 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + * + * Builds the serialized bootstrap configs from the annotation driven configs. + */ + + +require_once(__DIR__ . '/../vendor/autoload.php'); + +$factory = new \Weasel\WeaselDoctrineAnnotationDrivenFactory(); + +$readerProvider = $factory->getAnnotationReaderFactoryInstance(); +$jsonProvider = new \Weasel\JsonMarshaller\Config\AnnotationDriver($readerProvider); +$jsonProvider->setAnnotationNamespace('\Weasel\JsonMarshaller\Config\DoctrineAnnotations'); + +$config = array(); + +addConfig('\Weasel\JsonMarshaller\Config\ClassMarshaller', $config, $jsonProvider); +buildSubConfig(__DIR__ . '/../lib/Weasel/JsonMarshaller/Config/Deserialization', + '\Weasel\JsonMarshaller\Config\Deserialization', + $config, + $jsonProvider); +buildSubConfig(__DIR__ . '/../lib/Weasel/JsonMarshaller/Config/Serialization', + '\Weasel\JsonMarshaller\Config\Serialization', + $config, + $jsonProvider); + +addConfig('\Weasel\XmlMarshaller\Config\ClassMarshaller', $config, $jsonProvider); +buildSubConfig(__DIR__ . '/../lib/Weasel/XmlMarshaller/Config/Deserialization', + '\Weasel\XmlMarshaller\Config\Deserialization', + $config, + $jsonProvider); +buildSubConfig(__DIR__ . '/../lib/Weasel/XmlMarshaller/Config/Serialization', + '\Weasel\XmlMarshaller\Config\Serialization', + $config, + $jsonProvider); + +file_put_contents(__DIR__ . '/../lib/Weasel/JsonMarshaller/Config/bootstrap.cnf', serialize($config)); + +exit(0); + +function addConfig($class, &$config, \Weasel\JsonMarshaller\Config\AnnotationDriver $provider) +{ + $config[ltrim($class, '\\')] = $provider->getConfig($class); +} + +function buildSubConfig($dir, $bns, &$config, $provider) +{ + $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS; + foreach (new FilesystemIterator($dir, $flags) as $fileInfo) { + /** + * @var SplFileInfo $fileInfo + */ + $class = $bns . '\\' . $fileInfo->getBasename(".php"); + addConfig($class, $config, $provider); + } +} + + + diff --git a/bin/buildJsonConfig.php b/bin/buildJsonConfig.php new file mode 100644 index 0000000..80efeff --- /dev/null +++ b/bin/buildJsonConfig.php @@ -0,0 +1,19 @@ +#!/usr/bin/php +add(new BuildJsonMapperJsonConfigCommand()); +$application->add(new BuildXmlMapperJsonConfigCommand()); +$application->run(); + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..fca0bc8 --- /dev/null +++ b/composer.json @@ -0,0 +1,28 @@ +{ + "name": "moodev/weasel", + "type": "library", + "description": "Object marshalling library for PHP supporting JSON and XML", + "keywords": ["marshall", "marshalling", "json", "serialization", "deserialization", "jackson"], + "homepage": "http://github.com/moodev/php-weasel", + "license": "ISC", + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/log": "~1.1", + "doctrine/annotations": "~1.4", + "doctrine/cache": "~1.6", + "symfony/Console": "~3.4|~4.0" + }, + "require-dev": { + "mockery/mockery": "~1.2", + "phpunit/phpunit": "~5." + }, + "suggest": { + "monolog/monolog": "A logging framework that implements PSR 3" + }, + "autoload": { + "psr-0": { + "Weasel": "lib" + } + }, + "bin": ["bin/buildJsonConfig.php"] +} diff --git a/lib/Weasel/Annotation/AnnotationConfigProvider.php b/lib/Weasel/Annotation/AnnotationConfigProvider.php new file mode 100644 index 0000000..f642ff7 --- /dev/null +++ b/lib/Weasel/Annotation/AnnotationConfigProvider.php @@ -0,0 +1,18 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation; + +interface AnnotationConfigProvider +{ + + /** + * @abstract + * @param string $name The name of the annotation to load + * @return \Weasel\Annotation\Config\Annotation The annotation object + */ + public function get($name); +} diff --git a/lib/Weasel/Annotation/AnnotationConfigurator.php b/lib/Weasel/Annotation/AnnotationConfigurator.php new file mode 100644 index 0000000..30e62fb --- /dev/null +++ b/lib/Weasel/Annotation/AnnotationConfigurator.php @@ -0,0 +1,203 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation; + +use Weasel\Common\Cache\Cache; +use Weasel\Common\Cache\Exception; + +use Psr\Log\LoggerInterface; +use Psr\Log\LoggerAwareInterface; +use Weasel\Common\Cache\CacheAwareInterface; + +class AnnotationConfigurator implements AnnotationConfigProvider, LoggerAwareInterface, CacheAwareInterface +{ + + /** + * @var Config\AnnotationConfig + */ + protected static $builtIns; + + protected $logger; + + /** + * @var Cache + */ + protected $cache; + + protected $ownedFactory = false; + + /** + * @var AnnotationReaderFactory + */ + protected $readerFactory = null; + + public function __construct(LoggerInterface $logger = null, + Cache $cache = null, + AnnotationReaderFactory $readerFactory = null) + { + if (isset($logger)) { + $this->setLogger($logger); + } + if (isset($cache)) { + $this->setCache($cache); + } + if (!isset(self::$builtIns)) { + self::$builtIns = Config\BuiltInsProvider::getConfig(); + } + if (isset($readerFactory)) { + $this->setReaderFactory($readerFactory); + } else { + $readerFactory = new AnnotationReaderFactory($this); + $this->ownedFactory = true; + if (isset($logger)) { + $readerFactory->setLogger($logger); + } + $this->setReaderFactory($readerFactory); + } + + } + + public function get($name) + { + if (isset($this->cache)) { + $found = false; + $cached = $this->cache->get($name, "Annotation", $found); + if ($found) { + return $cached; + } + } + + if (self::$builtIns->getAnnotation($name)) { + return self::$builtIns->getAnnotation($name); + } + + $class = new \ReflectionClass($name); + $reader = $this->readerFactory->getReaderForClass($class); + + /** + * @var \Weasel\Annotation\Config\Annotations\Annotation $annotation + */ + $annotation = $reader->getSingleClassAnnotation('\Weasel\Annotation\Config\Annotations\Annotation'); + if (!isset($annotation)) { + throw new \RuntimeException("Did not find an @Annotation annotation on $name"); + } + + $metaConfig = new Config\Annotation($name, $annotation->getOn(), $annotation->getMax()); + + foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { + /** + * @var \ReflectionMethod $method + * @var \Weasel\Annotation\Config\Annotations\AnnotationCreator $creator + */ + $creator = $reader->getSingleMethodAnnotation($method->getName(), + '\Weasel\Annotation\Config\Annotations\AnnotationCreator' + ); + if (isset($creator)) { + if (!$method->isStatic() && !$method->isConstructor()) { + throw new \RuntimeException("Non-static methods cannot be configured as creators"); + } + $metaConfig->setCreatorMethod($method->getName()); + $creatorArgs = $method->getParameters(); + if (count($creatorArgs) != count($creator->getParams())) { + throw new \RuntimeException("Creator args don't match with method args"); + } + $i = 0; + foreach ($creator->getParams() as $param) { + $paramName = $param->getName(); + if (!isset($paramName)) { + $paramName = $creatorArgs[$i]->getName(); + } + $creatorParam = new Config\Param($paramName, $param->getType(), $param->getRequired()); + $i++; + $metaConfig->addCreatorParam($creatorParam); + } + + } + } + + foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { + /** + * @var \ReflectionProperty $property + * @var \Weasel\Annotation\Config\Annotations\Property $annotProperty + */ + $annotProperty = $reader->getSinglePropertyAnnotation($property->getName(), + '\Weasel\Annotation\Config\Annotations\Property' + ); + + if (isset($annotProperty)) { + $propertyConfig = new Config\Property($property->getName(), $annotProperty->getType()); + $metaConfig->addProperty($propertyConfig); + } + + /** + * @var \Weasel\Annotation\Config\Annotations\Enum $annotEnum + */ + $annotEnum = $reader->getSinglePropertyAnnotation($property->getName(), + '\Weasel\Annotation\Config\Annotations\Enum' + ); + + if (isset($annotEnum)) { + if (!$property->isStatic()) { + throw new \RuntimeException("Enums must be static properties"); + } + $name = $annotEnum->getName(); + if (!isset($name)) { + $name = $property->getName(); + } + $value = $property->getValue(null); + if (!is_array($value)) { + throw new \RuntimeException("Enum must be an array"); + } + $metaConfig->addEnum(new Config\Enum($name, $value)); + } + + } + + if (isset($this->cache)) { + $this->cache->set($name, $metaConfig, "Annotation"); + } + + return $metaConfig; + } + + public function getLogger() + { + return $this->logger; + } + + /** + * @param \Weasel\Annotation\AnnotationReaderFactory $readerFactory + * @return AnnotationConfigurator + */ + public function setReaderFactory($readerFactory) + { + $this->readerFactory = $readerFactory; + return $this; + } + + /** + * @param \Weasel\Common\Cache\Cache $cache + */ + public function setCache(Cache $cache) + { + $this->cache = $cache; + } + + /** + * Sets a logger instance on the object + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + if ($this->ownedFactory) { + $this->readerFactory->setLogger($logger); + } + } +} diff --git a/lib/Weasel/Annotation/AnnotationReader.php b/lib/Weasel/Annotation/AnnotationReader.php new file mode 100644 index 0000000..1a30626 --- /dev/null +++ b/lib/Weasel/Annotation/AnnotationReader.php @@ -0,0 +1,251 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation; + +use Psr\Log\LoggerInterface; +use Psr\Log\LoggerAwareInterface; +use Weasel\Common\Annotation\IAnnotationReader; + +/** + * Class AnnotationReader + * @package Weasel\Annotation + * @deprecated Use the DoctrineAnnotation driven reader. + */ +class AnnotationReader implements LoggerAwareInterface, IAnnotationReader +{ + + /** + * @var \ReflectionClass + */ + protected $class; + + /** + * @var null|array[] + */ + protected $classAnnotations = null; + /** + * @var null|array[] + */ + protected $methodAnnotations = null; + /** + * @var null|array[] + */ + protected $propertyAnnotations = null; + + protected $parser = null; + protected $namespaces; + + protected $otherNamespaces = array(); + + /** + * @var \Psr\Log\LoggerInterface + */ + protected $logger; + + /** + * @var PhpParser + */ + protected $nsParser; + + /** + * @param \ReflectionClass $class + * @param AnnotationConfigProvider $annotations + */ + public function __construct(\ReflectionClass $class, AnnotationConfigProvider $annotations) + { + $this->class = $class; + $this->parser = new DocblockParser($annotations); + $this->nsParser = new PhpParser(); + } + + protected function _getNamespaces() + { + if (!isset($this->namespaces)) { + $this->namespaces = $this->nsParser->parseClass($this->class); + } + return $this->namespaces; + } + + /** + * @return array[] + */ + public function getClassAnnotations() + { + if (isset($this->classAnnotations)) { + return $this->classAnnotations; + } + + $docblock = $this->class->getDocComment(); + + if ($docblock === false) { + $this->classAnnotations = array(); + } else { + $this->classAnnotations = $this->parser->parse($docblock, "class", $this->_getNamespaces()); + } + return $this->classAnnotations; + } + + /** + * @param string $annotation + * @return mixed[] + */ + public function getClassAnnotation($annotation) + { + $classes = $this->getClassAnnotations(); + return isset($classes[$annotation]) ? $classes[$annotation] : null; + } + + /** + * @param mixed[] $annotations + * @return mixed + * @throws \Exception + */ + protected function _singleAnnotation($annotations) + { + if (empty($annotations)) { + return null; + } + if (count($annotations) > 1) { + throw new \Exception("Attempt to get single annotation when there are multiple"); + } + return array_shift($annotations); + } + + /** + * @param string $annotation + * @return mixed + */ + public function getSingleClassAnnotation($annotation) + { + return $this->_singleAnnotation($this->getClassAnnotation($annotation)); + } + + /** + * @param \Reflection|\ReflectionMethod|\ReflectionProperty $rThing + * @return array + */ + protected function _getDeclaredNamespaces($rThing) + { + /** + * @var \ReflectionClass $dClass + */ + $dClass = $rThing->getDeclaringClass(); + + if ($dClass != $this->class) { + $fullName = $dClass->getNamespaceName() . '\\' . $dClass->getName(); + if (!isset($this->otherNamespaces[$fullName])) { + $this->otherNamespaces[$fullName] = $this->nsParser->parseClass($dClass); + } + return $this->otherNamespaces[$fullName]; + } + return $this->_getNamespaces(); + } + + /** + * @param string $method + * @return array[] + */ + public function getMethodAnnotations($method) + { + if (isset($this->methodAnnotations[$method])) { + return $this->methodAnnotations[$method]; + } + + $this->methodAnnotations[$method] = array(); + $rMethod = $this->class->getMethod($method); + $docblock = $rMethod->getDocComment(); + if ($docblock !== false) { + $this->methodAnnotations[$method] = $this->parser->parse($docblock, + "method", + $this->_getDeclaredNamespaces($rMethod) + ); + } + return $this->methodAnnotations[$method]; + + } + + /** + * @param string $method + * @param string $annotation + * @return mixed[] + */ + public function getMethodAnnotation($method, $annotation) + { + $methods = $this->getMethodAnnotations($method); + return (isset($methods[$annotation]) ? $methods[$annotation] : null); + + } + + /** + * @param string $method + * @param string $annotation + * @return mixed + */ + public function getSingleMethodAnnotation($method, $annotation) + { + return $this->_singleAnnotation($this->getMethodAnnotation($method, $annotation)); + } + + /** + * @param string $property + * @return array[] + */ + public function getPropertyAnnotations($property) + { + if (isset($this->propertyAnnotations[$property])) { + return $this->propertyAnnotations[$property]; + } + + $this->propertyAnnotations[$property] = array(); + $rProperty = $this->class->getProperty($property); + $docblock = $rProperty->getDocComment(); + if ($docblock !== false) { + $this->propertyAnnotations[$property] = $this->parser->parse($docblock, + "property", + $this->_getDeclaredNamespaces($rProperty) + ); + } + return $this->propertyAnnotations[$property]; + + } + + /** + * @param string $property + * @param string $annotation + * @return mixed[] + */ + public function getPropertyAnnotation($property, $annotation) + { + $properties = $this->getPropertyAnnotations($property); + return isset($properties[$annotation]) ? $properties[$annotation] : null; + } + + /** + * @param string $property + * @param string $annotation + * @return mixed + */ + public function getSinglePropertyAnnotation($property, $annotation) + { + return $this->_singleAnnotation($this->getPropertyAnnotation($property, $annotation)); + } + + /** + * Sets a logger instance on the mixed + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + if (isset($logger)) { + $this->parser->setLogger($logger); + $this->nsParser->setLogger($logger); + } + } +} diff --git a/lib/Weasel/Annotation/AnnotationReaderFactory.php b/lib/Weasel/Annotation/AnnotationReaderFactory.php new file mode 100644 index 0000000..68839b9 --- /dev/null +++ b/lib/Weasel/Annotation/AnnotationReaderFactory.php @@ -0,0 +1,63 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation; + +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerInterface; +use Weasel\Common\Annotation\IAnnotationReaderFactory; + +/** + * Class AnnotationReaderFactory + * @package Weasel\Annotation + * @deprecated Use the DoctrineAnnotation driven reader. + */ +class AnnotationReaderFactory implements IAnnotationReaderFactory, LoggerAwareInterface +{ + + /** + * @var LoggerInterface + */ + protected $logger; + + /** + * @var AnnotationConfigProvider + */ + protected $configProvider; + + /** + * @param AnnotationConfigProvider $configProvider + */ + public function __construct(AnnotationConfigProvider $configProvider) + { + $this->configProvider = $configProvider; + } + + /** + * @param \ReflectionClass $class + * @return \Weasel\Common\Annotation\IAnnotationReader + */ + public function getReaderForClass(\ReflectionClass $class) + { + $reader = new AnnotationReader($class, $this->configProvider); + if (isset($this->logger)) { + $reader->setLogger($this->logger); + } + return $reader; + } + + + /** + * Sets a logger instance on the object + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } +} diff --git a/lib/Weasel/Annotation/ArrayCachingAnnotationConfigurator.php b/lib/Weasel/Annotation/ArrayCachingAnnotationConfigurator.php new file mode 100644 index 0000000..0bf9191 --- /dev/null +++ b/lib/Weasel/Annotation/ArrayCachingAnnotationConfigurator.php @@ -0,0 +1,29 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation; + +use Psr\Log\LoggerInterface; +use Psr\Log\LoggerAwareInterface; +use Weasel\Common\Cache\ArrayCache; + +/** + * Left over from prior to new cache system. + * Stop using this. Use an AnnotationConfigurator, and call setCache. + * @deprecated Use the AnnotationConfiguration and call setCache()! + */ +class ArrayCachingAnnotationConfigurator extends AnnotationConfigurator implements LoggerAwareInterface +{ + public function __construct(LoggerInterface $logger = null, + AnnotationReaderFactory $readerFactory = null) + { + parent::__construct($logger, $readerFactory); + $this->setCache(new ArrayCache("AnnotationConfigurator")); + } + + +} + diff --git a/lib/Weasel/Annotation/Config/Annotation.php b/lib/Weasel/Annotation/Config/Annotation.php new file mode 100644 index 0000000..426c154 --- /dev/null +++ b/lib/Weasel/Annotation/Config/Annotation.php @@ -0,0 +1,223 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config; + +class Annotation +{ + + /** + * @var string + */ + private $class; + + /** + * @var string[] + */ + private $on; + + private $onFlipped; + + /** + * @var int + */ + private $max; + + /** + * @var string + */ + private $creatorMethod; + + /** + * @var \Weasel\Annotation\Config\Param[] + */ + private $creatorParams; + + /** + * @var \Weasel\Annotation\Config\Property[] + */ + private $properties; + + /** + * @var \Weasel\Annotation\Config\Enum[] + */ + private $enums; + + /** + * @param string $class + * @param string[] $on + * @param int $max + */ + public function __construct($class, $on, $max = null) + { + $this->class = $class; + $this->on = $on; + $this->max = $max; + $this->onFlipped = array_flip($on); + } + + /** + * @return string + */ + public function getClass() + { + return $this->class; + } + + /** + * @return string + */ + public function getCreatorMethod() + { + return $this->creatorMethod; + } + + /** + * @return \Weasel\Annotation\Config\Param[] + */ + public function getCreatorParams() + { + return $this->creatorParams; + } + + /** + * @return int + */ + public function getMax() + { + return $this->max; + } + + /** + * @return \string[] + */ + public function getOn() + { + return $this->on; + } + + public function permittedOn($location) + { + return isset($this->onFlipped[$location]); + } + + /** + * @param string $creatorMethod + * @return \Weasel\Annotation\Config\Annotation + */ + public function setCreatorMethod($creatorMethod) + { + $this->creatorMethod = $creatorMethod; + return $this; + } + + /** + * @param \Weasel\Annotation\Config\Param $param + * @return Annotation + */ + public function addCreatorParam($param) + { + $this->creatorParams[] = $param; + return $this; + } + + /** + * @param \Weasel\Annotation\Config\Param[] $creatorParams + * @return Annotation + */ + public function setCreatorParams($creatorParams) + { + $this->creatorParams = $creatorParams; + return $this; + } + + /** + * @param int $max + * @return \Weasel\Annotation\Config\Annotation + */ + public function setMax($max) + { + $this->max = $max; + return $this; + } + + /** + * @param $on + * @return Annotation + */ + public function setOn($on) + { + $this->on = $on; + return $this; + } + + /** + * @return \Weasel\Annotation\Config\Property[] + */ + public function getProperties() + { + return $this->properties; + } + + /** + * @param \Weasel\Annotation\Config\Property[] $properties + * @return Annotation + */ + public function setProperties($properties) + { + $this->properties = $properties; + return $this; + } + + /** + * @param \Weasel\Annotation\Config\Property $property + * @return Annotation + */ + public function addProperty(Property $property) + { + $this->properties[$property->getName()] = $property; + return $this; + } + + /** + * @return \Weasel\Annotation\Config\Enum[] + */ + public function getEnums() + { + return $this->enums; + } + + /** + * @param \Weasel\Annotation\Config\Enum[] $enums + * @return Annotation + */ + public function setEnums($enums) + { + $this->enums = $enums; + return $this; + } + + /** + * @param \Weasel\Annotation\Config\Enum $enum + * @return Annotation + */ + public function addEnum($enum) + { + $this->enums[$enum->getName()] = $enum; + return $this; + } + + /** + * @param string $name + * @return \Weasel\Annotation\Config\Enum + */ + public function getEnum($name) + { + return isset($this->enums[$name]) ? $this->enums[$name] : null; + } + +} + diff --git a/lib/Weasel/Annotation/Config/AnnotationConfig.php b/lib/Weasel/Annotation/Config/AnnotationConfig.php new file mode 100644 index 0000000..f57e462 --- /dev/null +++ b/lib/Weasel/Annotation/Config/AnnotationConfig.php @@ -0,0 +1,50 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config; + +class AnnotationConfig +{ + + /** + * @var \Weasel\Annotation\Config\Annotation[] + */ + private $annotations = array(); + + /** + * @param \Weasel\Annotation\Config\Annotation $annotation + */ + public function addAnnotation($annotation) + { + $this->annotations[$annotation->getClass()] = $annotation; + } + + /** + * @param \Weasel\Annotation\Config\Annotation[] $annotations + * @return AnnotationConfig + */ + public function setAnnotations($annotations) + { + $this->annotations = $annotations; + return $this; + } + + /** + * @return Annotation[] + */ + public function getAnnotations() + { + return $this->annotations; + } + + public function getAnnotation($class) + { + $class = "\\" . ltrim($class, "\\"); + return isset($this->annotations[$class]) ? $this->annotations[$class] : null; + } + + +} diff --git a/lib/Weasel/Annotation/Config/Annotations/Annotation.php b/lib/Weasel/Annotation/Config/Annotations/Annotation.php new file mode 100644 index 0000000..4e7cc7c --- /dev/null +++ b/lib/Weasel/Annotation/Config/Annotations/Annotation.php @@ -0,0 +1,42 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; + +/** + * @Annotation(on="class", max=1) + */ +class Annotation +{ + + protected $on; + protected $max; + + /** + * @param string[]|null $on + * @param int|null $max + * @AnnotationCreator({@Parameter(name="on", type="string[]", required=false), @Parameter(name="max", type="integer", required=false)}) + */ + public function __construct(array $on, $max) + { + $this->on = isset($on) ? $on : null; + $this->max = isset($max) ? $max : null; + } + + public function getMax() + { + return $this->max; + } + + public function getOn() + { + return $this->on; + } + +} diff --git a/lib/Weasel/Annotation/Config/Annotations/AnnotationCreator.php b/lib/Weasel/Annotation/Config/Annotations/AnnotationCreator.php new file mode 100644 index 0000000..cf788b9 --- /dev/null +++ b/lib/Weasel/Annotation/Config/Annotations/AnnotationCreator.php @@ -0,0 +1,40 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\Parameter; + +/** + * @Annotation(on="method", max=1) + */ +class AnnotationCreator +{ + + /** + * @var array|null|\Weasel\Annotation\Config\Annotations\Parameter[] + */ + protected $params; + + /** + * @param \Weasel\Annotation\Config\Annotations\Parameter[]|null $params + * @AnnotationCreator(@Parameter(name="params", type="\Weasel\Annotation\Config\Annotations\Parameter[]", required=false)) + */ + public function __construct(array $params) + { + $this->params = isset($params) ? $params : null; + } + + /** + * @return array|null|\Weasel\Annotation\Config\Annotations\Parameter[] + */ + public function getParams() + { + return $this->params; + } + +} diff --git a/lib/Weasel/Annotation/Config/Annotations/Enum.php b/lib/Weasel/Annotation/Config/Annotations/Enum.php new file mode 100644 index 0000000..f596ffc --- /dev/null +++ b/lib/Weasel/Annotation/Config/Annotations/Enum.php @@ -0,0 +1,36 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; + +/** + * @Annotation(on="property") + */ +class Enum +{ + + protected $name; + + /** + * @param string $name + * @AnnotationCreator(@Parameter(name="name", type="string", required=false)) + */ + public function __construct($name) + { + $this->name = isset($name) ? $name : null; + } + + public function getName() + { + return $this->name; + } + +} + diff --git a/lib/Weasel/Annotation/Config/Annotations/Parameter.php b/lib/Weasel/Annotation/Config/Annotations/Parameter.php new file mode 100644 index 0000000..ce05012 --- /dev/null +++ b/lib/Weasel/Annotation/Config/Annotations/Parameter.php @@ -0,0 +1,50 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; + +/** + * @Annotation(on="\Weasel\Annotation\Config\Annotations\AnnotationCreator") + */ +class Parameter +{ + + protected $name; + protected $type; + protected $required; + + /** + * @param string $name + * @param string $type + * @param bool $required + * @AnnotationCreator({@Parameter(name="name", type="string", required=false), @Parameter(name="type", type="string", required=false), @Parameter(name="required", type="boolean", required=false)}) + */ + public function __construct($name, $type, $required) + { + $this->name = isset($name) ? $name : null; + $this->type = isset($type) ? $type : "string"; + $this->required = isset($required) ? $required : false; + } + + public function getName() + { + return $this->name; + } + + public function getRequired() + { + return $this->required; + } + + public function getType() + { + return $this->type; + } + +} diff --git a/lib/Weasel/Annotation/Config/Annotations/Property.php b/lib/Weasel/Annotation/Config/Annotations/Property.php new file mode 100644 index 0000000..d921bea --- /dev/null +++ b/lib/Weasel/Annotation/Config/Annotations/Property.php @@ -0,0 +1,41 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; + +/** + * @Annotation(on="property", max=1) + */ +class Property +{ + + /** + * @var string + */ + protected $type; + + /** + * @param string $type + * @AnnotationCreator + * @CreatorParam(name="type", type="string", required=false) + */ + public function __construct($type) + { + $this->type = isset($type) ? $type : "string"; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } +} diff --git a/lib/Weasel/Annotation/Config/BuiltInsProvider.php b/lib/Weasel/Annotation/Config/BuiltInsProvider.php new file mode 100644 index 0000000..0435a57 --- /dev/null +++ b/lib/Weasel/Annotation/Config/BuiltInsProvider.php @@ -0,0 +1,62 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config; + +class BuiltInsProvider +{ + + /** + * @var AnnotationConfig + */ + protected static $builtIns; + + protected static function _buildConfig() + { + + self::$builtIns = new AnnotationConfig(); + + $annotation = new Annotation('\Weasel\Annotation\Config\Annotations\Annotation', array('class'), 1); + $annotation->setCreatorMethod('__construct'); + $annotation->addCreatorParam( + new Param('on', 'string[]', false) + ); + $annotation->addCreatorParam( + new Param('max', 'integer', false) + ); + self::$builtIns->addAnnotation($annotation); + + $annotation = new Annotation('\Weasel\Annotation\Config\Annotations\AnnotationCreator', array('method'), 1); + $annotation->setCreatorMethod('__construct'); + $annotation->addCreatorParam( + new Param('params', '\Weasel\Annotation\Config\Annotations\Parameter[]', false) + ); + self::$builtIns->addAnnotation($annotation); + + $annotation = + new Annotation('\Weasel\Annotation\Config\Annotations\Parameter', array('\Weasel\Annotation\Config\Annotations\AnnotationCreator'), null); + $annotation->setCreatorMethod('__construct'); + $annotation->addCreatorParam( + new Param('name', 'string', false) + ); + $annotation->addCreatorParam( + new Param('type', 'string', false) + ); + $annotation->addCreatorParam( + new Param('required', 'bool', false) + ); + self::$builtIns->addAnnotation($annotation); + } + + public static function getConfig() + { + if (!isset(self::$builtIns)) { + self::_buildConfig(); + } + return self::$builtIns; + } + +} diff --git a/lib/Weasel/Annotation/Config/Enum.php b/lib/Weasel/Annotation/Config/Enum.php new file mode 100644 index 0000000..b6237eb --- /dev/null +++ b/lib/Weasel/Annotation/Config/Enum.php @@ -0,0 +1,48 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config; + +class Enum +{ + + /** + * @var string + */ + private $name; + + /** + * @var array + */ + private $values; + + /** + * @param string $name + * @param array $values + */ + public function __construct($name, $values) + { + $this->name = $name; + $this->values = $values; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return array + */ + public function getValues() + { + return $this->values; + } + +} diff --git a/lib/Weasel/Annotation/Config/Param.php b/lib/Weasel/Annotation/Config/Param.php new file mode 100644 index 0000000..c236183 --- /dev/null +++ b/lib/Weasel/Annotation/Config/Param.php @@ -0,0 +1,62 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config; + +class Param +{ + + /** + * @var string + */ + private $name; + + /** + * @var string + */ + private $type; + + /** + * @var bool + */ + private $required; + + /** + * @param string $name + * @param string $type + * @param bool $required + */ + public function __construct($name, $type, $required) + { + $this->name = $name; + $this->type = $type; + $this->required = $required; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return bool + */ + public function getRequired() + { + return $this->required; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } +} diff --git a/lib/Weasel/Annotation/Config/Property.php b/lib/Weasel/Annotation/Config/Property.php new file mode 100644 index 0000000..3b97537 --- /dev/null +++ b/lib/Weasel/Annotation/Config/Property.php @@ -0,0 +1,47 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Config; + +class Property +{ + + /** + * @var string + */ + private $name; + + /** + * @var string + */ + private $type; + + /** + * @param string $name + * @param string $type + */ + public function __construct($name, $type) + { + $this->name = $name; + $this->type = $type; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } +} diff --git a/lib/Weasel/Annotation/DocblockLexer.php b/lib/Weasel/Annotation/DocblockLexer.php new file mode 100644 index 0000000..72de017 --- /dev/null +++ b/lib/Weasel/Annotation/DocblockLexer.php @@ -0,0 +1,263 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation; +class DocblockLexer +{ + + const T_MEH = 1; + const T_WHITESPACE = 2; + const T_EOL = 3; + const T_PREAMBLE = 4; + const T_NULL = 10; + const T_QUOTED_STRING = 11; + const T_INTEGER = 12; + const T_FLOAT = 13; + const T_BOOLEAN = 14; + + const T_IDENTIFIER = 50; + + const T_AT = 60; + const T_OPEN_PAREN = 61; + const T_CLOSE_PAREN = 62; + const T_OPEN_BRACE = 63; + const T_CLOSE_BRACE = 64; + const T_COMMA = 65; + const T_EQUAL = 66; + const T_BACKSLASH = 67; + const T_COLON = 68; + const T_DOT = 69; + + public static $TREAT_AS_WS = array(self::T_WHITESPACE => self::T_WHITESPACE, + self::T_EOL => self::T_EOL, + self::T_PREAMBLE => self::T_PREAMBLE, + ); + + protected $tokens = array(); + + protected $pos; + + public function __construct($input) + { + $this->_scan($input); + } + + + /** + * @param string $input + * @throws \Exception + */ + protected function _scan($input) + { + + // In a more traditional world we'd scan the input a single char at a time + // Fortunately preg_split gives us a way to split the input up into a slightly more helpful form. + // Yay. + $split = preg_split( + '(' . implode('|', + array( + // Quoted strings + '("(?:[^"]|"")*")', + // Numeric + '([+-]?[0-9]+(?:\.[0-9]+|[eE][+-]?[0-9]+)?)', + // Identifier + '([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)', + // Line preamble + '(\v+\s+\*[^\S\v])', + // End of line + '(\v+)', + // All other whitespace + '(\s+)', + // Everything else will be split into single chars + '(.)', + ) + ) . ')', + $input, + -1, + (PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_DELIM_CAPTURE) + ); + + foreach ($split as $segment) { + list ($token, $position) = $segment; + $type = $this->_processToken($token); + $tokens['token'] = $token; + $tokens['type'] = $type; + $tokens['pos'] = $position; + $this->tokens[] = $tokens; + } + $this->pos = 0; + } + + protected function _processToken(&$value) + { + + switch (strtolower($value)) { + case '@': + return self::T_AT; + case '(': + return self::T_OPEN_PAREN; + case ')': + return self::T_CLOSE_PAREN; + case '{': + return self::T_OPEN_BRACE; + case '}': + return self::T_CLOSE_BRACE; + case ',': + return self::T_COMMA; + case '=': + return self::T_EQUAL; + case '\\': + return self::T_BACKSLASH; + case ':': + return self::T_COLON; + case '.': + return self::T_DOT; + case 'true': + $value = true; + return self::T_BOOLEAN; + case 'false': + $value = false; + return self::T_BOOLEAN; + case 'null': + return self::T_NULL; + } + + if ($value[0] === '"' && strlen($value) > 1) { + $value = str_replace('""', '"', substr($value, 1, -1)); + return self::T_QUOTED_STRING; + } + + if (is_numeric($value)) { + if (strpos($value, '.') !== false || stripos($value, 'e') !== false) { + return self::T_FLOAT; + } + return self::T_INTEGER; + } + + if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $value)) { + return self::T_IDENTIFIER; + } + + if (preg_match('/^(\v+\s+\*\s+)$/', $value)) { + return self::T_PREAMBLE; + } + + if (preg_match('/^\v+$/', $value)) { + return self::T_EOL; + } + + if (preg_match('/^\s+$/', $value)) { + return self::T_WHITESPACE; + } + + return self::T_MEH; + } + + public function skipToType($target) + { + if (!$cur = $this->get()) { + return null; + } + do { + if ($cur['type'] === $target) { + return $cur; + } + } while ($cur = $this->next()); + return null; + } + + public function get() + { + if (!isset($this->tokens[$this->pos])) { + return null; + } else { + return $this->tokens[$this->pos]; + } + } + + public function skip($types = null) + { + if (!isset($types)) { + $types = self::$TREAT_AS_WS; + } + if (!$cur = $this->get()) { + return null; + } + do { + if (!isset($types[$cur['type']])) { + return $cur; + } + } while ($cur = $this->next()); + return null; + } + + public function next($skipWS = false) + { + $this->pos++; + if ($skipWS) { + return $this->skip(); + } + return $this->get(); + } + + public function seek($to = 0) + { + if ($to < 0) { + $to = count($this->tokens) + $to; + } + if (!isset($this->tokens[$to])) { + return null; + } + $this->pos = $to; + return $this->get(); + } + + public function cur() + { + return $this->pos; + } + + protected function _wsSkippingPeek($num = 1) + { + if ($num === 0) { + $cur = $this->get(); + if (!isset(self::$TREAT_AS_WS[$cur["type"]])) { + return $cur["type"]; + } + } + $pos = $this->pos; + $ret = null; + $i = 0; + do { + $ret = $this->next(true); + $i++; + } while ($i < $num && $ret !== null); + $this->seek($pos); + return isset($ret) ? $ret["type"] : null; + } + + public function peek($num = 1, $skipWS = false) + { + if ($num < 0) { + throw new \InvalidArgumentException("Cannot peek backwards"); + } + if ($skipWS) { + return $this->_wsSkippingPeek($num); + } + if ($num === 0) { + $cur = $this->get(); + return $cur["type"]; + } + $pos = $this->pos; + if ($ret = $this->seek($pos + $num)) { + $this->seek($pos); + return $ret['type']; + } + $this->seek($pos); + return null; + } + +} diff --git a/lib/Weasel/Annotation/DocblockParser.php b/lib/Weasel/Annotation/DocblockParser.php new file mode 100644 index 0000000..66806c9 --- /dev/null +++ b/lib/Weasel/Annotation/DocblockParser.php @@ -0,0 +1,473 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation; + +use Psr\Log\LoggerInterface; +use Psr\Log\LoggerAwareInterface; + +class DocblockParser implements LoggerAwareInterface +{ + + /** + * @var AnnotationConfigProvider + */ + protected $annotations; + + /** + * @var LoggerInterface + */ + protected $logger; + + static $silentlyDiscard = array( + "param" => true, + "author" => true, + "copyright" => true, + "var" => true, + "return" => true, + "package" => true, + "throws" => true, + ); + + public function parse($docBlock, $location, $namespaces) + { + return $this->_parse($docBlock, $location, $namespaces); + } + + public function __construct(AnnotationConfigProvider $annotations) + { + $this->annotations = $annotations; + } + + protected function _getAnnotation($name, $namespaces) + { + + if ($name[0] !== '\\') { + $exploded = explode('\\', $name); + $alias = ""; + $name = null; + $part = null; + do { + if ($part !== null) { + $alias .= '\\' . $part; + } + $baseNamespace = implode('\\', $exploded); + if (isset($namespaces[$baseNamespace])) { + $name = '\\' . $namespaces[$baseNamespace] . ($alias !== '' ? ($alias) : ''); + break; + } + } while ($part = array_pop($exploded)); + + if ($name === null) { + return null; + } + + } + + return $this->annotations->get($name); + } + + protected function _parse($input, $location, $namespaces) + { + $lexer = new DocblockLexer($input); + return $this->_DocBlock($lexer, $location, $namespaces); + } + + protected function _DocBlock(DocblockLexer $lexer, $location, $namespaces) + { + $annotations = array(); + while ($lexer->skipToType(DocblockLexer::T_PREAMBLE)) { + $next = $lexer->next(); + if ($next["type"] !== DocblockLexer::T_AT) { + // Skip because it doesn't have an annotation at the start + continue; + } + + $pos = $lexer->cur(); + try { + $annotation = $this->_Annotation($lexer, $location, $namespaces); + $this->_expectNext($lexer, DocblockLexer::$TREAT_AS_WS); + if (isset($annotation)) { + $annotations[$annotation[0]][] = $annotation[1]; + } else { + // If not then it parsed fine, but it isn't something we know about + } + } catch (\Exception $e) { + // OK, try starting 1 char after the @ to find the next annotation. + if ($this->logger) { + $this->logger->debug("Skipping syntax error: " . $e->getMessage(), array("exception" => $e)); + } + $lexer->seek($pos); + if (!$lexer->next()) { + break; + } + } + } + + return $annotations; + } + + protected function _Array(DocblockLexer $lexer, $location, $namespaces) + { + + $elements = array(); + + while (($next = $lexer->peek(1, true)) !== DocblockLexer::T_CLOSE_BRACE) { + $elements[] = $this->_ParamValue($lexer, $location, $namespaces); + + if ($lexer->peek(1, true) === DocblockLexer::T_CLOSE_BRACE) { + break; + } + $this->_expectNext($lexer, DocblockLexer::T_COMMA, true); + } + $this->_expectNext($lexer, DocblockLexer::T_CLOSE_BRACE, true); + return $elements; + } + + protected function _ParamValue(DocblockLexer $lexer, $location, $namespaces) + { + $next = $lexer->peek(1, true); + if ($next === DocblockLexer::T_IDENTIFIER) { + // Might be an enum then... + $enum = $this->_Enum($lexer, $location, $namespaces); + return $enum; + } + + $cur = $lexer->next(true); + switch ($cur['type']) { + case DocblockLexer::T_INTEGER: + $param = array('integer', + $cur['token'] + ); + break; + case DocblockLexer::T_FLOAT: + $param = array('float', + $cur['token'] + ); + break; + case DocblockLexer::T_BOOLEAN: + $param = array('boolean', + $cur['token'] + ); + break; + case DocblockLexer::T_QUOTED_STRING: + $param = array('string', + $cur['token'] + ); + break; + case DocblockLexer::T_AT: + $object = $this->_Annotation($lexer, $location, $namespaces); + return $object; + break; + case DocblockLexer::T_OPEN_BRACE: + $array = $this->_Array($lexer, $location, $namespaces); + return array('array', + $array + ); + default: + throw new \Exception("Parse error got {$cur["type"]} ({$cur['token']})"); + } + return $param; + } + + protected function _NamedParam(DocblockLexer $lexer, $location, $namespaces) + { + $nameToken = $this->_expectNext($lexer, DocblockLexer::T_IDENTIFIER, true); + + $this->_expectNext($lexer, DocblockLexer::T_EQUAL, true); + + $value = $this->_ParamValue($lexer, $location, $namespaces); + + return array($nameToken['token'], + $value + ); + + } + + protected function _expectNext(DocblockLexer $lexer, $types, $skipWS = false) + { + if (!is_array($types)) { + $types = array($types => $types); + } + $next = $lexer->next($skipWS); + if (!$next || !isset($types[$next['type']])) { + throw new \Exception('Parse error, expected one of ' . implode(',', $types) . ' but got ' . ($next ? + $next['type'] : 'EOF')); + } + return $next; + } + + protected function _ClassName(DocblockLexer $lexer) + { + $next = $lexer->next(); + + $class = ''; + if ($next['type'] === DocblockLexer::T_BACKSLASH) { + $class .= '\\'; + $next = $this->_expectNext($lexer, DocblockLexer::T_IDENTIFIER); + } + + $class .= $next['token']; + + while ($lexer->peek() === DocblockLexer::T_BACKSLASH) { + $this->_expectNext($lexer, DocblockLexer::T_BACKSLASH); + $class .= '\\'; + $part = $this->_expectNext($lexer, DocblockLexer::T_IDENTIFIER); + $class .= $part['token']; + } + return $class; + } + + protected function _Enum(DocblockLexer $lexer, $location, $namespaces) + { + $class = $this->_ClassName($lexer); + $meta = $this->_getAnnotation($class, $namespaces); + if (!$meta) { + throw new \Exception("Unable to resolve enum class $class"); + } + + $this->_expectNext($lexer, DocblockLexer::T_DOT); + $enumTok = $this->_expectNext($lexer, DocblockLexer::T_IDENTIFIER); + $enum = $enumTok["token"]; + $this->_expectNext($lexer, DocblockLexer::T_DOT); + $indexTok = $this->_expectNext($lexer, DocblockLexer::T_IDENTIFIER); + $index = $indexTok["token"]; + + if ($meta->getEnum($enum) === null) { + throw new \Exception("Unable to find an enum for $class : $enum : $index"); + } + $enumValues = $meta->getEnum($enum)->getValues(); + if (!isset($enumValues[$index])) { + throw new \Exception("Unable to lookup enum value for $class : $enum : $index"); + } + + return array("integer", + $enumValues[$index] + ); + + } + + protected function _Annotation(DocblockLexer $lexer, $location, $namespaces) + { + + $identifier = $this->_ClassName($lexer); + + $meta = $this->_getAnnotation($identifier, $namespaces); + if (!$meta) { + if ($this->logger) { + if (!isset(self::$silentlyDiscard[$identifier])) { + $this->logger->debug("Skipping unknown annotation: $identifier"); + } + } + return null; + } + + if ($meta->getOn() && !$meta->permittedOn($location)) { + throw new \Exception( + "Found annotation in wrong location, got $location but expected one of " . implode(", ", + $meta->getOn() + )); + } + + if ($lexer->peek() === DocblockLexer::T_OPEN_PAREN) { + // There are params to read + $this->_expectNext($lexer, DocblockLexer::T_OPEN_PAREN); + + $anonParams = array(); + $namedParams = array(); + + $expectingComma = false; + while (($next = $lexer->peek(1, true)) !== DocblockLexer::T_CLOSE_PAREN) { + if ($next === null) { + throw new \Exception('Unmatched parentheses'); + } + if ($next === DocblockLexer::T_IDENTIFIER && $lexer->peek(2, true) === DocblockLexer::T_EQUAL) { + if ($expectingComma) { + throw new \Exception('Unexpected identifier, expecting comma or close paren'); + } + list($name, $param) = $this->_NamedParam($lexer, $meta->getClass(), $namespaces); + $namedParams[$name] = $param; + $expectingComma = true; + } elseif ($next === DocblockLexer::T_COMMA) { + if (!$expectingComma) { + throw new \Exception('Unexpected comma'); + } + $this->_expectNext($lexer, DocblockLexer::T_COMMA, true); + $expectingComma = false; + } else { + if ($expectingComma) { + throw new \Exception('Unexpected value, expecting comma or close paren'); + } + $anonParams[] = $this->_ParamValue($lexer, $meta->getClass(), $namespaces); + $expectingComma = true; + } + } + if (!empty($anonParams) && !empty($namedParams)) { + throw new \Exception('Named or anonymous params, pick one.'); + } + + $this->_expectNext($lexer, DocblockLexer::T_CLOSE_PAREN, true); + + if ((!empty($anonParams) || !empty($namedParams)) && $expectingComma === false) { + // There has been a comma followed by a close paren... + throw new \Exception('Unexpected close paren after comma'); + } + + } + + $class = $meta->getClass(); + + if ($meta->getCreatorMethod()) { + // There's a creator method to call + + /** + * @var \Weasel\Annotation\Config\Param[] $expectedParams + */ + $expectedParams = $meta->getCreatorParams() ? $meta->getCreatorParams() : array(); + $actualParams = array(); + if (!empty($anonParams)) { + if (count($anonParams) > count($expectedParams)) { + throw new \Exception("Too many parameters"); + } + reset($anonParams); + foreach ($expectedParams as $paramConfig) { + $param = each($anonParams); + $param = ($param === false) ? null : $param['value']; + if ($param === null) { + if ($paramConfig->getRequired() && $paramConfig->getRequired() === true) { + throw new \Exception('Missing required parameter ' . $paramConfig->getName()); + } + $actualParams[] = null; + } else { + $actualParams[] = $this->_collapseAndCheckType($param, $paramConfig->getType()); + } + } + } elseif (!empty($namedParams)) { + foreach ($expectedParams as $paramConfig) { + if (!isset($namedParams[$paramConfig->getName()])) { + if ($paramConfig->getRequired() && $paramConfig->getRequired() === true) { + throw new \Exception('Missing required parameter ' . $paramConfig->getName()); + } + $actualParams[] = null; + } else { + $actualParams[] = $this->_collapseAndCheckType($namedParams[$paramConfig->getName()], + $paramConfig->getType() + ); + } + } + } else { + $actualParams = array_fill(0, count($expectedParams), null); + } + + if ($meta->getCreatorMethod() === '__construct') { + $reflectionClass = new \ReflectionClass($class); + $annotation = $reflectionClass->newInstanceArgs($actualParams); + } else { + $method = $meta->getCreatorMethod(); + $reflectionMethod = new \ReflectionMethod($class, $method); + $annotation = $reflectionMethod->invokeArgs(null, $actualParams); + } + } else { + $annotation = new $class(); + } + + if (!empty($namedParams) && $meta->getProperties()) { + foreach ($meta->getProperties() as $name => $property) { + /** + * @var Config\Property $property + */ + if (isset($namedParams[$name])) { + $annotation->$name = $this->_collapseAndCheckType($namedParams[$name], $property->getType()); + } + } + } + + return array($class, + $annotation + ); + } + + protected function _collapseAndCheckType($param, $type) + { + list($paramType, $paramValue) = $param; + switch ($type) { + case "bool": + case "boolean": + if ($paramType === "bool" || $paramType === "boolean") { + return (bool)$paramValue; + } + break; + case "int": + case "integer": + if ($paramType === "integer" || $paramType === "int") { + return (int)$paramValue; + } + break; + case "string": + if ($paramType === $type) { + return (string)$paramValue; + } + break; + case "float": + if ($paramType === $type) { + return (float)$paramValue; + } + break; + default: + + } + if ($paramType === $type) { + if (!is_object($paramValue)) { + throw new \Exception("Expected object"); + } + if (!$paramValue instanceof $type) { + throw new \Exception("Expected object of type $type"); + } + return $paramValue; + } + + // Assume type strings are well formed: look for the last [ to see if it's an array or map. + // Note that this might be an array of arrays, and we're after the outermost type, so we're after the last [! + $pos = strrpos($type, '['); + if ($pos === false) { + // Erm, right, it's not good then. + throw new \Exception("Type mismatch, expected $type but got $paramType"); + } + + // Extract the base type, and whatever's between the [...] as the index type. + // Potentially the type string is actually badly formed: + // e.g. this code will accept string[int! as being an array of string with index int. + // Bah. I'll ignore that case for now. This bit of code gets called a lot, I'd rather not add another substr. + $elementType = substr($type, 0, $pos); + + // Not currently supported + // $indexType = substr($type, $pos+1, -1); + + $result = array(); + if (!is_array($paramValue)) { + $paramValue = array(array($paramType, + $paramValue + ) + ); + } + foreach ($paramValue as $element) { + $result[] = $this->_collapseAndCheckType($element, $elementType); + } + return $result; + + } + + /** + * Sets a logger instance on the object + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } +} diff --git a/lib/Weasel/Annotation/PhpParser.php b/lib/Weasel/Annotation/PhpParser.php new file mode 100644 index 0000000..5209328 --- /dev/null +++ b/lib/Weasel/Annotation/PhpParser.php @@ -0,0 +1,255 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation; + +use RuntimeException; +use Psr\Log\LoggerInterface; +use Psr\Log\LoggerAwareInterface; + +class PhpParser implements LoggerAwareInterface +{ + + /** + * @var LoggerInterface + */ + protected $logger; + + public function __construct(LoggerInterface $logger = null) + { + if (isset($logger)) { + $this->setLogger($logger); + } + } + + public function parseClass(\ReflectionClass $class) + { + if (isset($this->logger)) { + $this->logger->debug("Parsing file " . $class->getFileName() . " for " . $class->getName()); + } + return $this->_parse($class); + } + + protected function _parse(\ReflectionClass $class) + { + // Read PHP file up to the point the class is defined + $data = $this->_readPrologue($class); + + $tokens = token_get_all('_Namespace($tokens); + $namespaces = array(); + continue; + } + + if ($name === T_USE) { + $namespaces = array_merge($namespaces, $this->_Use($tokens)); + } + + if ($name === T_CLASS) { + $foundClass = $this->_Class($tokens); + if (empty($foundClass)) { + // Class name is not on the same line as the class keyword. We're good to assume that we've read the right thing. + break; + } + if ($foundClass[0] != '\\') { + $foundClass = $curNamespace . '\\' . $foundClass; + } + if ($foundClass === $class->getName()) { + if ($class->getNamespaceName() !== $curNamespace) { + throw new \RuntimeException("Parsing error: Thought $foundClass was in {$class->getNamespaceName()} but it isn't."); + } + break; + } + } + + } + + $classNS = $class->getNamespaceName(); + if (!empty($classNS)) { + $namespaces[""] = $classNS; + } else { + $namespaces[""] = ""; + } + + return $namespaces; + } + + protected function _Use($tokens) + { + + $namespaces = array(); + + $aliasPart = false; + $namespace = ""; + $alias = null; + $lastSegment = null; + + while ($token = array_shift($tokens)) { + if (!is_array($token)) { + $namespace = ltrim($namespace, '\\'); + if ($token === ',') { + if (!isset($alias)) { + $alias = $lastSegment; + } + $namespaces[$alias] = $namespace; + $alias = null; + $lastSegment = null; + $aliasPart = false; + $namespace = ""; + continue; + } elseif ($token === ';') { + if (!isset($alias)) { + $alias = $lastSegment; + } + $namespaces[$alias] = $namespace; + break; + } else { + // Who knows. + break; + } + } + if (!$aliasPart && $token[0] === T_STRING) { + $namespace .= $token[1]; + $lastSegment = $token[1]; + } elseif (!$aliasPart && $token[0] === T_NS_SEPARATOR) { + $namespace .= $token[1]; + } elseif ($token[0] === T_AS) { + $aliasPart = true; + $alias = ""; + } elseif ($token[0] === T_WHITESPACE || $token[0] === T_COMMENT || $token[0] === T_DOC_COMMENT) { + // Meh + } elseif ($aliasPart && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) { + $alias .= $token[1]; + } else { + break; + } + } + return $namespaces; + + } + + + protected function _readPrologue(\ReflectionClass $class) + { + $file = $class->getFileName(); + $line = $class->getStartLine(); + + $buffer = ""; + $handle = @fopen($file, "r"); + if ($handle) { + for ($curLine = 0; $curLine < $line; $curLine++) { + $data = fgets($handle); + if ($data === false) { + break; + } + $buffer .= $data; + } + + fclose($handle); + } + + return $buffer; + + } + + private function _Namespace($tokens) + { + $namespace = ""; + + while ($token = array_shift($tokens)) { + if (!is_array($token)) { + switch ($token) { + case ";": + case "{": + return $namespace; + default: + throw new RuntimeException("Parse error: got $token expected ;"); + } + } else { + switch ($token[0]) { + case T_STRING: + case T_NS_SEPARATOR: + $namespace .= $token[1]; + break; + case T_WHITESPACE: + if (empty($namespace)) { + break; + } else { + return $namespace; + } + case T_COMMENT: + case T_DOC_COMMENT: + break; + default: + throw new RuntimeException("Parse error: got {$token[1]} expected part of namespace"); + } + } + } + return $namespace; + } + + private function _Class($tokens) + { + $class = ""; + + while ($token = array_shift($tokens)) { + if (!is_array($token)) { + switch ($token) { + case "{": + return $class; + default: + throw new RuntimeException("Parse error: got $token expected {"); + } + } else { + switch ($token[0]) { + case T_STRING: + case T_NS_SEPARATOR: + $class .= $token[1]; + break; + case T_WHITESPACE: + if (empty($class)) { + break; + } else { + return $class; + } + case T_COMMENT: + case T_DOC_COMMENT: + break; + default: + throw new RuntimeException("Parse error: got {$token[1]} expected part of class name"); + } + } + } + return $class; + } + + /** + * Sets a logger instance on the object + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } +} diff --git a/lib/Weasel/BounceContexts/WeaslDefaultAnnotationDrivenContext.xml b/lib/Weasel/BounceContexts/WeaslDefaultAnnotationDrivenContext.xml new file mode 100644 index 0000000..3a1ce77 --- /dev/null +++ b/lib/Weasel/BounceContexts/WeaslDefaultAnnotationDrivenContext.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/Weasel/Command/BuildJsonMapperJsonConfigCommand.php b/lib/Weasel/Command/BuildJsonMapperJsonConfigCommand.php new file mode 100644 index 0000000..633b3fd --- /dev/null +++ b/lib/Weasel/Command/BuildJsonMapperJsonConfigCommand.php @@ -0,0 +1,104 @@ +setName('json') + ->setDescription('Build a config for the JSON mapper') + ->addArgument( + 'in', + InputArgument::REQUIRED, + 'What directory/file should I scan?' + ) + ->addArgument( + 'out', + InputArgument::OPTIONAL, + 'What file should I write to? Default is stdout' + ) + ->addOption("builtinannot", + null, + InputOption::VALUE_OPTIONAL, + "Use the built in annotations rather than Doctrine", + false); + } + + /** + * @var AnnotationDriver + */ + protected $driver; + + /** + * @var JsonMapper + */ + protected $mapper; + + protected function setupDriver($useBuiltin) + { + if ($useBuiltin) { + $factory = new WeaselDefaultAnnotationDrivenFactory(); + $driver = $factory->getJsonDriverInstance(); + } else { + $factory = new WeaselDoctrineAnnotationDrivenFactory(); + $driver = $factory->getJsonDriverInstance(); + } + + $this->mapper = $factory->getJsonMapperInstance(); + $this->driver = $driver; + + } + + protected function generateConfigs($target) + { + $before = get_declared_classes(); + $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS; + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($target, $flags)) as $fileInfo) { + /** + * @var \SplFileInfo $fileInfo + */ + if ($fileInfo->isFile() && preg_match('/\.(php[0-9.]*|inc)$/', $fileInfo->getFilename())) { + include_once($fileInfo->getPathname()); + } + } + $after = get_declared_classes(); + $new = array_diff($after, $before); + + $config = array(); + foreach ($new as $class) { + $config[$class] = $this->driver->getConfig($class); + } + return $config; + + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $in = $input->getArgument('in'); + if (!is_readable($in)) { + throw new \InvalidArgumentException("in must be a readable file or directory"); + } + $this->setupDriver($input->getOption("builtinannot")); + $config = $this->generateConfigs($in); + $json = $this->mapper->writeString($config, '\Weasel\JsonMarshaller\Config\ClassMarshaller[string]'); + if ($out = $input->getArgument("out")) { + file_put_contents($out, $json); + } else { + print $json; + } + } +} \ No newline at end of file diff --git a/lib/Weasel/Command/BuildXmlMapperJsonConfigCommand.php b/lib/Weasel/Command/BuildXmlMapperJsonConfigCommand.php new file mode 100644 index 0000000..f71523c --- /dev/null +++ b/lib/Weasel/Command/BuildXmlMapperJsonConfigCommand.php @@ -0,0 +1,104 @@ +setName('xml') + ->setDescription('Build a config for the JSON mapper') + ->addArgument( + 'in', + InputArgument::REQUIRED, + 'What directory/file should I scan?' + ) + ->addArgument( + 'out', + InputArgument::OPTIONAL, + 'What file should I write to? Default is stdout' + ) + ->addOption("builtinannot", + null, + InputOption::VALUE_OPTIONAL, + "Use the built in annotations rather than Doctrine", + false); + } + + /** + * @var AnnotationDriver + */ + protected $driver; + + /** + * @var JsonMapper + */ + protected $mapper; + + protected function setupDriver($useBuiltin) + { + if ($useBuiltin) { + $factory = new WeaselDefaultAnnotationDrivenFactory(); + $driver = $factory->getXmlDriverInstance(); + } else { + $factory = new WeaselDoctrineAnnotationDrivenFactory(); + $driver = $factory->getXmlDriverInstance(); + } + + $this->mapper = $factory->getJsonMapperInstance(); + $this->driver = $driver; + + } + + protected function generateConfigs($target) + { + $before = get_declared_classes(); + $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS; + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($target, $flags)) as $fileInfo) { + /** + * @var \SplFileInfo $fileInfo + */ + if ($fileInfo->isFile() && preg_match('/\.(php[0-9.]*|inc)$/', $fileInfo->getFilename())) { + include_once($fileInfo->getPathname()); + } + } + $after = get_declared_classes(); + $new = array_diff($after, $before); + + $config = array(); + foreach ($new as $class) { + $config[$class] = $this->driver->getConfig($class); + } + return $config; + + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $in = $input->getArgument('in'); + if (!is_readable($in)) { + throw new \InvalidArgumentException("in must be a readable file or directory"); + } + $this->setupDriver($input->getOption("builtinannot")); + $config = $this->generateConfigs($in); + $json = $this->mapper->writeString($config, '\Weasel\XmlMarshaller\Config\ClassMarshaller[string]'); + if ($out = $input->getArgument("out")) { + file_put_contents($out, $json); + } else { + print $json; + } + } +} \ No newline at end of file diff --git a/lib/Weasel/Common/Annotation/IAnnotationReader.php b/lib/Weasel/Common/Annotation/IAnnotationReader.php new file mode 100644 index 0000000..6265a82 --- /dev/null +++ b/lib/Weasel/Common/Annotation/IAnnotationReader.php @@ -0,0 +1,72 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Common\Annotation; + +/** + * Something that reads annotation objects from a class. + */ +interface IAnnotationReader +{ + + /** + * @return array[] + */ + public function getClassAnnotations(); + + /** + * @param string $annotation + * @return mixed[] + */ + public function getClassAnnotation($annotation); + + /** + * @param string $annotation + * @return object + */ + public function getSingleClassAnnotation($annotation); + + /** + * @param string $method + * @return array[] + */ + public function getMethodAnnotations($method); + + /** + * @param string $method + * @param string $annotation + * @return mixed[] + */ + public function getMethodAnnotation($method, $annotation); + + /** + * @param string $method + * @param string $annotation + * @return mixed + */ + public function getSingleMethodAnnotation($method, $annotation); + + /** + * @param string $property + * @return array[] + */ + public function getPropertyAnnotations($property); + + /** + * @param string $property + * @param string $annotation + * @return mixed[] + */ + public function getPropertyAnnotation($property, $annotation); + + /** + * @param string $property + * @param string $annotation + * @return mixed + */ + public function getSinglePropertyAnnotation($property, $annotation); + +} diff --git a/lib/Weasel/Common/Annotation/IAnnotationReaderFactory.php b/lib/Weasel/Common/Annotation/IAnnotationReaderFactory.php new file mode 100644 index 0000000..eab80bc --- /dev/null +++ b/lib/Weasel/Common/Annotation/IAnnotationReaderFactory.php @@ -0,0 +1,24 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Common\Annotation; + +/** + * A factory for annotation readers. + */ +interface IAnnotationReaderFactory +{ + + /** + * Obtain an annotation reader for the provided reflection class. + * This is perfectly entitled to return the same instance of IAnnotationReader no matter what class you call it + * with. + * @param \ReflectionClass $class + * @return \Weasel\Common\Annotation\IAnnotationReader + */ + public function getReaderForClass(\ReflectionClass $class); + +} diff --git a/lib/Weasel/Common/Cache/ApcCache.php b/lib/Weasel/Common/Cache/ApcCache.php new file mode 100644 index 0000000..b32b0be --- /dev/null +++ b/lib/Weasel/Common/Cache/ApcCache.php @@ -0,0 +1,53 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Common\Cache; + +class ApcCache extends Cache +{ + + /** + * @param string $key Key to load from cache. + * @param null $namespace + * @param bool $found + * @return mixed + */ + public function get($key, $namespace = null, &$found = true) + { + $key = $this->_getRealKeyName($key, $namespace); + $success = false; + $res = apc_fetch($key, $success); + if (!$success) { + $found = false; + return null; + } + $found = true; + return $res; + } + + /** + * @param string $key Key to store data under + * @param mixed $value Data to store. If it's serializable it can be stored. + * @param null $namespace + * @throws Exception\BackingFailure + * @return void + */ + public function set($key, $value, $namespace = null) + { + $key = $this->_getRealKeyName($key, $namespace); + if (!apc_store($key, $value)) { + throw new Exception\BackingFailure($key, "apc_store returned false"); + } + } + + public function delete($key, $namespace = null) + { + $key = $this->_getRealKeyName($key, $namespace); + if (!apc_delete($key)) { + throw new Exception\BackingFailure($key, "apc_store returned false"); + } + } +} diff --git a/lib/Weasel/Common/Cache/ArrayCache.php b/lib/Weasel/Common/Cache/ArrayCache.php new file mode 100644 index 0000000..fe1dcd6 --- /dev/null +++ b/lib/Weasel/Common/Cache/ArrayCache.php @@ -0,0 +1,50 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Common\Cache; + +class ArrayCache extends Cache +{ + + private $cache = array(); + + /** + * @param string $key Key to load from cache. + * @param null|string $namespace + * @param bool $found + * @return mixed + */ + public function get($key, $namespace = null, &$found = true) + { + $key = $this->_getRealKeyName($key, $namespace); + if (array_key_exists($key, $this->cache)) { + $found = true; + return $this->cache[$key]; + } + $found = false; + return null; + } + + /** + * @param string $key Key to store data under + * @param mixed $value Data to store. If it's serializable it can be stored. + * @param null $namespace + * @return void + */ + public function set($key, $value, $namespace = null) + { + $key = $this->_getRealKeyName($key, $namespace); + $this->cache[$key] = $value; + } + + public function delete($key, $namespace = null) + { + $key = $this->_getRealKeyName($key, $namespace); + if (array_key_exists($key, $this->cache)) { + unset($this->cache[$key]); + } + } +} diff --git a/lib/Weasel/Common/Cache/Cache.php b/lib/Weasel/Common/Cache/Cache.php new file mode 100644 index 0000000..9cf2cd3 --- /dev/null +++ b/lib/Weasel/Common/Cache/Cache.php @@ -0,0 +1,80 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Common\Cache; + +/** + * A really boring interface for accessing caches. + */ +abstract class Cache +{ + + private $prefix; + + /** + * @abstract + * @param string $key Key to load from cache. + * @param string $namespace + * @param bool $found True if the key was found in the cache, false if it wasn't. Useful if the cache can store nulls. + * @return mixed + */ + public abstract function get($key, $namespace = null, &$found = true); + + /** + * @abstract + * @param string $key Key to store data under + * @param mixed $value Data to store. If it's serializable it can be stored. + * @param string $namespace + * @return + */ + public abstract function set($key, $value, $namespace = null); + + /** + * Delete something from the cache. + * To preserve keep old implementations working this base class implements the method to lob an error. + * This MUST be implemented for the DoctrineAnnotation cache adapter to work. + * @param string $key Key to delete + * @param string $namespace + * @throws \RuntimeException + */ + public function delete($key, $namespace = null) + { + throw new \RuntimeException("Unsupported for this cache implementation"); + } + + /** + * @param string $prefix + */ + public function setPrefix($prefix) + { + $this->prefix = $prefix; + } + + /** + * @return string + */ + public function getPrefix() + { + return $this->prefix; + } + + public function __construct($prefix = null) + { + $this->setPrefix($prefix); + } + + protected function _getRealKeyName($key, $namespace = null) + { + if (isset($namespace)) { + $key = $namespace . ':~:' . $key; + } + if (isset($this->prefix)) { + $key = $this->prefix . '::' . $key; + } + return $key; + } + +} diff --git a/lib/Weasel/Common/Cache/CacheAwareInterface.php b/lib/Weasel/Common/Cache/CacheAwareInterface.php new file mode 100644 index 0000000..9c8903e --- /dev/null +++ b/lib/Weasel/Common/Cache/CacheAwareInterface.php @@ -0,0 +1,12 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Common\Cache; + +use Exception; + +class CacheException extends Exception +{ + + protected $key; + + public function __construct($key, $message = "", $code = 0, Exception $previous = null) + { + $this->key = $key; + parent::__construct($message, $code, $previous); + } + +} diff --git a/lib/Weasel/Common/Cache/Exception/BackingFailure.php b/lib/Weasel/Common/Cache/Exception/BackingFailure.php new file mode 100644 index 0000000..6bedbbb --- /dev/null +++ b/lib/Weasel/Common/Cache/Exception/BackingFailure.php @@ -0,0 +1,14 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Common\Cache\Exception; + +use Weasel\Common\Cache\CacheException; + +class BackingFailure extends CacheException +{ + +} diff --git a/lib/Weasel/Common/Logger/FileLogger.php b/lib/Weasel/Common/Logger/FileLogger.php new file mode 100644 index 0000000..9446b5a --- /dev/null +++ b/lib/Weasel/Common/Logger/FileLogger.php @@ -0,0 +1,55 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Common\Logger; + +use Psr\Log\AbstractLogger; +use Psr\Log\LogLevel; + +/** + * This exists as a lame shim so that anyone relying on it can move to a real logging framework. + * @deprecated Use a real logger, like monolog! + */ +class FileLogger extends AbstractLogger implements Logger +{ + + protected $_logLevel = 0; + protected $_logFile; + + public function __construct($logFile = null) + { + if (!isset($logFile)) { + $this->_logFile = 'php://stderr'; + } else { + $this->_logFile = $logFile; + } + } + + public function setLogLevel($level) + { + $this->_logLevel = $level; + } + + public function logDebug($entry) + { + $this->debug($entry); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + public function log($level, $message, array $context = array()) + { + if ($this->_logLevel >= self::LOG_LEVEL_DEBUG) { + error_log($message . "\n", 3, $this->_logFile); + } + } +} diff --git a/lib/Weasel/Common/Logger/Logger.php b/lib/Weasel/Common/Logger/Logger.php new file mode 100644 index 0000000..485ce4c --- /dev/null +++ b/lib/Weasel/Common/Logger/Logger.php @@ -0,0 +1,22 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Common\Logger; + +/** + * @deprecated Use the PSR3 logger interface. + */ +interface Logger +{ + + const LOG_LEVEL_OFF = 0; + const LOG_LEVEL_DEBUG = 255; + + public function setLogLevel($level); + + public function logDebug($entry); + +} diff --git a/lib/Weasel/Common/Utils/NoUndeclaredProperties.php b/lib/Weasel/Common/Utils/NoUndeclaredProperties.php new file mode 100644 index 0000000..baaac32 --- /dev/null +++ b/lib/Weasel/Common/Utils/NoUndeclaredProperties.php @@ -0,0 +1,33 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Common\Utils; + +/** + * Utility class to do stuff involving reflection. + */ +class ReflectionUtils +{ + + /** + * Call a static method with some args. + * We avoid reflection for up to 4 args. + * Allegedly this is faster than using ReflectionMethod (really?) + * @param string $class + * @param string $method + * @param array $args + * @return mixed + */ + public static function invokeStaticMethod($class, $method, $args) + { + switch (count($args)) { + case 0: + return $class::$method(); + case 1: + return $class::$method($args[0]); + case 2: + return $class::$method($args[0], $args[1]); + case 3: + return $class::$method($args[0], $args[1], $args[2]); + case 4: + return $class::$method($args[0], $args[1], $args[2], $args[3]); + default: + $rMethod = new \ReflectionMethod($class, $method); + return $rMethod->invokeArgs(null, $args); + } + } + + /** + * Instantiate a class with some constructor args. + * We avoid reflection for up to 4 args. + * Allegedly this is faster than using ReflectionClass (really?) + * @param string $class + * @param array $args + * @return mixed + */ + public static function instantiateClassByConstructor($class, $args) + { + switch (count($args)) { + case 0: + return new $class(); + case 1: + return new $class($args[0]); + case 2: + return new $class($args[0], $args[1]); + case 3: + return new $class($args[0], $args[1], $args[2]); + case 4: + return new $class($args[0], $args[1], $args[2], $args[3]); + default: + $rClass = new \ReflectionClass($class); + return $rClass->newInstanceArgs($args); + } + } + +} diff --git a/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderAdapter.php b/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderAdapter.php new file mode 100644 index 0000000..5a4c84b --- /dev/null +++ b/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderAdapter.php @@ -0,0 +1,157 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\DoctrineAnnotation; + +use Doctrine\Common\Annotations\Reader; +use Weasel\Common\Annotation\IAnnotationReader; + +/** + * An adapter to allow a Doctrine AnnotationReader to be used in place of a Weasel one. + */ +class DoctrineAnnotationReaderAdapter implements IAnnotationReader +{ + + /** + * @var \Doctrine\Common\Annotations\Reader + */ + private $annotationReader; + + /** + * @var \ReflectionClass + */ + private $rClass; + + public function __construct(Reader $annotationReader, \ReflectionClass $rClass) + { + $this->annotationReader = $annotationReader; + $this->rClass = $rClass; + } + + /** + * @return array[] + */ + public function getClassAnnotations() + { + return $this->annotationReader->getClassAnnotations($this->rClass); + } + + /** + * @param string $annotation + * @return null|object[] + */ + public function getClassAnnotation($annotation) + { + $annotation = ltrim($annotation, '\\'); + $res = $this->annotationReader->getClassAnnotation($this->rClass, $annotation); + if (!is_array($res)) { + $res = array($res); + } + return $res; + } + + /** + * @param string $annotation + * @return object + */ + public function getSingleClassAnnotation($annotation) + { + $annotation = ltrim($annotation, '\\'); + $res = $this->annotationReader->getClassAnnotation($this->rClass, $annotation); + if (empty($res)) { + return null; + } + if (is_array($res)) { + return array_shift($res); + } + return $res; + } + + /** + * @param string $method + * @return array[] + */ + public function getMethodAnnotations($method) + { + return $this->annotationReader->getMethodAnnotations($this->rClass->getMethod($method)); + } + + /** + * @param string $method + * @param string $annotation + * @return null|object[] + */ + public function getMethodAnnotation($method, $annotation) + { + $annotation = ltrim($annotation, '\\'); + $res = $this->annotationReader->getMethodAnnotation($this->rClass->getMethod($method), $annotation); + if (!is_array($res)) { + $res = array($res); + } + return $res; + } + + /** + * @param string $method + * @param string $annotation + * @return null|object + */ + public function getSingleMethodAnnotation($method, $annotation) + { + $annotation = ltrim($annotation, '\\'); + $res = $this->annotationReader->getMethodAnnotation($this->rClass->getMethod($method), $annotation); + if (empty($res)) { + return null; + } + if (is_array($res)) { + return array_shift($res); + } + return $res; + } + + /** + * @param string $property + * @return array[] + */ + public function getPropertyAnnotations($property) + { + return $this->annotationReader->getPropertyAnnotations($this->rClass->getProperty($property)); + } + + /** + * @param string $property + * @param string $annotation + * @return null|object[] + */ + public function getPropertyAnnotation($property, $annotation) + { + $annotation = ltrim($annotation, '\\'); + $res = $this->annotationReader->getPropertyAnnotation($this->rClass->getProperty($property), $annotation); + if (!is_array($res)) { + $res = array($res); + } + return $res; + } + + /** + * @param string $property + * @param string $annotation + * @return null|object + */ + public function getSinglePropertyAnnotation($property, $annotation) + { + $annotation = ltrim($annotation, '\\'); + $res = $this->annotationReader->getPropertyAnnotation($this->rClass->getProperty($property), $annotation); + if (empty($res)) { + return null; + } + if (is_array($res)) { + return array_shift($res); + } + return $res; + } +} + diff --git a/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactory.php b/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactory.php new file mode 100644 index 0000000..85842cb --- /dev/null +++ b/lib/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactory.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\DoctrineAnnotation; + +use Doctrine\Common\Annotations\Reader; +use Doctrine\Common\Annotations\AnnotationReader; +use Doctrine\Common\Annotations\AnnotationRegistry; +use Weasel\Common\Annotation\IAnnotationReaderFactory; +use Doctrine\Common\Annotations\CachedReader; + +/** + * An AnnotationReaderFactory that provides Doctrine powered readers. + */ +class DoctrineAnnotationReaderFactory implements IAnnotationReaderFactory +{ + + /** + * @var \Doctrine\Common\Annotations\Reader + */ + protected $annotationReader; + + /** + * @param \Doctrine\Common\Annotations\Reader $annotationReader + */ + public function __construct(Reader $annotationReader) + { + $this->annotationReader = $annotationReader; + AnnotationRegistry::registerAutoloadNamespace('Weasel', array(__DIR__ . '/../../')); + AnnotationRegistry::registerAutoloadNamespace('\Weasel', array(__DIR__ . '/../../')); + } + + /** + * @param \ReflectionClass $class + * @return \Weasel\Common\Annotation\IAnnotationReader + */ + public function getReaderForClass(\ReflectionClass $class) + { + return new DoctrineAnnotationReaderAdapter($this->annotationReader, $class); + } + +} diff --git a/lib/Weasel/DoctrineAnnotation/WeaselCacheAdapter.php b/lib/Weasel/DoctrineAnnotation/WeaselCacheAdapter.php new file mode 100644 index 0000000..63799ff --- /dev/null +++ b/lib/Weasel/DoctrineAnnotation/WeaselCacheAdapter.php @@ -0,0 +1,114 @@ +delegate = $cache; + } + + /** + * Fetches an entry from the cache. + * + * @param string $id The id of the cache entry to fetch. + * + * @return string|bool The cached data or FALSE, if no cache entry exists for the given id. + */ + protected function doFetch($id) + { + $found = false; + $val = $this->delegate->get($id, null, $found); + if ($found) { + return $val; + } else { + return false; + } + } + + /** + * Tests if an entry exists in the cache. + * + * @param string $id The cache id of the entry to check for. + * + * @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise. + */ + protected function doContains($id) + { + $found = false; + $this->delegate->get($id, null, $found); + return $found; + } + + /** + * Puts data into the cache. + * + * @param string $id The cache id. + * @param string $data The cache entry/data. + * @param int $lifeTime The lifetime. If != 0, sets a specific lifetime for this + * cache entry (0 => infinite lifeTime). + * + * @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise. + */ + protected function doSave($id, $data, $lifeTime = 0) + { + $this->delegate->set($id, $data); + return true; + } + + /** + * Deletes a cache entry. + * + * @param string $id The cache id. + * + * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. + */ + protected function doDelete($id) + { + $this->delegate->delete($id); + return true; + } + + /** + * Flushes all cache entries. + * + * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. + */ + protected function doFlush() + { + return false; + } + + /** + * Retrieves cached information from the data store. + * + * @since 2.2 + * + * @return array|null An associative array with server's statistics if available, NULL otherwise. + */ + protected function doGetStats() + { + return null; + } + + /** + * @param Cache $cache + */ + public function setCache(Cache $cache) + { + $this->delegate = $cache; + } +} diff --git a/lib/Weasel/JsonMarshaller/Config/AnnotationDriver.php b/lib/Weasel/JsonMarshaller/Config/AnnotationDriver.php new file mode 100644 index 0000000..fe6b9b5 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/AnnotationDriver.php @@ -0,0 +1,96 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config; + +use Weasel\JsonMarshaller\Config\Annotations; +use Weasel\Annotation\AnnotationConfigurator; +use Weasel\Common\Cache\CacheAwareInterface; +use Weasel\Common\Cache\Cache; +use Weasel\Common\Annotation\IAnnotationReaderFactory; + +/** + * A config provider that uses Annotations + */ +class AnnotationDriver implements JsonConfigProvider, CacheAwareInterface +{ + + protected $classPaths = array(); + + protected $annotationNamespace = '\Weasel\JsonMarshaller\Config\Annotations'; + + /** + * @var \Weasel\Common\Cache\Cache + */ + protected $cache = null; + + /** + * @var \Weasel\Common\Annotation\IAnnotationReaderFactory + */ + public $annotationReaderFactory; + + public function __construct(IAnnotationReaderFactory $annotationReaderFactory) + { + $this->annotationReaderFactory = $annotationReaderFactory; + } + + /** + * Obtain the config for a named class + * @param string $class The class to get the config for + * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found + */ + public function getConfig($class) + { + $key = strtolower($class); + if (isset($this->cache)) { + $found = false; + $cached = $this->cache->get($key, "JsonConfig", $found); + if ($found) { + return $cached; + } + } + $config = $this->_getConfig($class); + + if (isset($this->cache)) { + $this->cache->set($key, $config, "JsonConfig"); + } + return $config; + } + + /** + * _Really_ obtain the config for a named class + * @param string $class The class to get the config for + * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found + */ + protected function _getConfig($class) + { + $rClass = new \ReflectionClass($class); + + // Delegate actually loading the config for the class to the ClassAnnotationDriver + $classDriver = new ClassAnnotationDriver($rClass, $this->annotationReaderFactory, $this->annotationNamespace); + + return $classDriver->getConfig(); + + } + + public function setCache(Cache $cache) + { + $this->cache = $cache; + } + + public function setAnnotationReaderFactory(IAnnotationReaderFactory $annotationReaderFactory) + { + $this->annotationReaderFactory = $annotationReaderFactory; + } + + /** + * @param string $annotationNamespace + */ + public function setAnnotationNamespace($annotationNamespace) + { + $this->annotationNamespace = $annotationNamespace; + } +} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnyGetter.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnyGetter.php new file mode 100644 index 0000000..1e42968 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnyGetter.php @@ -0,0 +1,20 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnyGetter; + +/** + * @Annotation(on="method", max=1) + */ +class JsonAnyGetter extends NoUndeclaredProperties implements IJsonAnyGetter +{ + + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnySetter.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnySetter.php new file mode 100644 index 0000000..65ac105 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonAnySetter.php @@ -0,0 +1,20 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnySetter; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation(on="method", max=1) + */ +class JsonAnySetter extends NoUndeclaredProperties implements IJsonAnySetter +{ + + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonCreator.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonCreator.php new file mode 100644 index 0000000..5eaaafe --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonCreator.php @@ -0,0 +1,44 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonCreator; + +/** + * @Annotation(on="method", max=1) + */ +class JsonCreator extends NoUndeclaredProperties implements IJsonCreator +{ + + /** + * @var \Weasel\JsonMarshaller\Config\Annotations\JsonProperty[] + */ + protected $params = array(); + + /** + * @param \Weasel\JsonMarshaller\Config\Annotations\JsonProperty[] params + * @AnnotationCreator(@Parameter(name="params", type="\Weasel\JsonMarshaller\Config\Annotations\JsonProperty[]", required=false)) + */ + public function __construct(array $params) + { + $this->params = isset($params) ? $params : array(); + } + + /** + * @return array|JsonProperty[] + */ + public function getParams() + { + return $this->params; + } + + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonIgnoreProperties.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonIgnoreProperties.php new file mode 100644 index 0000000..dd31b01 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonIgnoreProperties.php @@ -0,0 +1,53 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonIgnoreProperties; + +/** + * Provides a list of properties not to consider when serializing/deserializing. + * If ignoreUnknown is true then errors will not be thrown when we encounter properties to deserialize that we do not have a property for, + * they will just be discarded. + * + * @Annotation(on="class") + */ +class JsonIgnoreProperties extends NoUndeclaredProperties implements IJsonIgnoreProperties +{ + + /** + * @param $names + * @param $ignoreUnknown + * @AnnotationCreator({ + * @Parameter(name="names", type="string[]", required=false), + * @Parameter(name="ignoreUnknown", type="boolean", required=false) + * }) + */ + public function __construct($names, $ignoreUnknown) + { + $this->names = isset($names) ? $names : array(); + $this->ignoreUnknown = isset($ignoreUnknown) ? $ignoreUnknown : false; + } + + public function getIgnoreUnknown() + { + return $this->ignoreUnknown; + } + + public function getNames() + { + return $this->names; + } + + protected $names; + + protected $ignoreUnknown; + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonInclude.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonInclude.php new file mode 100644 index 0000000..cc4afb0 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonInclude.php @@ -0,0 +1,55 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\Annotation\Config\Annotations\Enum; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonInclude; + +/** + * @Annotation(on={"class", "method", "property"}, max=1) + */ +class JsonInclude extends NoUndeclaredProperties implements IJsonInclude +{ + + /** + * @var int[string] + * @Enum("Include") + */ + public static $enumInclude = array( + "ALWAYS" => self::INCLUDE_ALWAYS, + "NON_DEFAULT" => self::INCLUDE_NON_DEFAULT, + "NON_EMPTY" => self::INCLUDE_NON_EMPTY, + "NON_NULL" => self::INCLUDE_NON_NULL + ); + + /** + * @var integer + */ + protected $value; + + /** + * @AnnotationCreator(@Parameter(name="value", type="integer", required=true)) + * @param $value + */ + public function __construct($value) + { + $this->value = $value; + } + + /** + * @return int + */ + public function getValue() + { + return $this->value; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonProperty.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonProperty.php new file mode 100644 index 0000000..a03c1e8 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonProperty.php @@ -0,0 +1,58 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonProperty; + +/** + * Sets a property up to be serialized/deserialized explicitly. + * The name sets the json field name to use for this property. + * The type specifies the type to use. + * Because PHP is not strongly typed we can only make best guesses about types if you do not provide type info! + * @Annotation(on={"property", "method", "\Weasel\JsonMarshaller\Config\Annotations\JsonCreator"}) + */ +class JsonProperty extends NoUndeclaredProperties implements IJsonProperty +{ + + protected $name; + protected $type; + protected $strict; + + /** + * @param string $name + * @param string $type + * @param bool $strict + * @AnnotationCreator({@Parameter(name="name", type="string", required=false), @Parameter(name="type", type="string", required=false), @Parameter(name="strict", type="bool", required=false)}) + */ + public function __construct($name, $type, $strict) + { + $this->name = isset($name) ? $name : null; + $this->type = isset($type) ? $type : "string"; + $this->strict = isset($strict) ? $strict : true; + } + + public function getName() + { + return $this->name; + } + + public function getType() + { + return $this->type; + } + + public function getStrict() + { + return $this->strict; + } + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes.php new file mode 100644 index 0000000..2534288 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonSubTypes; + +/** + * The list of subtypes of this base class + * @Annotation(on={"class", "method", "property"}) + */ +class JsonSubTypes extends NoUndeclaredProperties implements IJsonSubTypes +{ + + /** + * @var JsonSubTypes\Type[] + */ + protected $value; + + /** + * @param \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type[] $value + * @AnnotationCreator(@Parameter(name="value", type="\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type[]", required=true)) + */ + public function __construct($value) + { + $this->value = $value; + } + + /** + * @return JsonSubTypes\Type[] + */ + public function getValue() + { + return $this->value; + } + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/Type.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/Type.php new file mode 100644 index 0000000..2fc0850 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/Type.php @@ -0,0 +1,57 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\JsonSubTypes\IType; + +/** + * A subtype + * @Annotation(on={"\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes"}) + */ +class Type extends NoUndeclaredProperties implements IType +{ + + /** + * @var string + */ + protected $value; + + /** + * @var string|null + */ + protected $name; + + /** + * @param string $value + * @param string|null $name + * @AnnotationCreator({@Parameter(name="value", type="string", required=true), @Parameter(name="name", type="string", required=false)}) + */ + public function __construct($value, $name) + { + $this->value = $value; + $this->name = $name; + } + + public function getValue() + { + return $this->value; + } + + /** + * @return null|string + */ + public function getName() + { + return $this->name; + } + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfo.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfo.php new file mode 100644 index 0000000..2193c4a --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfo.php @@ -0,0 +1,123 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\Annotation\Config\Annotations\Enum; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonTypeInfo; + +/** + * @Annotation(on={"class", "method", "property"}) + */ +class JsonTypeInfo extends NoUndeclaredProperties implements IJsonTypeInfo +{ + + /** + * @var int[string] + * @Enum("Id") + */ + public static $enumId = array( + "CLASS" => self::ID_CLASS, + "CUSTOM" => self::ID_CUSTOM, + "MINIMAL_CLASS" => self::ID_MINIMAL_CLASS, + "NAME" => self::ID_NAME, + "NONE" => self::ID_NONE, + ); + + /** + * @var int[string] + * @Enum("As") + */ + public static $enumAs = array( + "PROPERTY" => self::AS_PROPERTY, + "WRAPPER_ARRAY" => self::AS_WRAPPER_ARRAY, + "WRAPPER_OBJECT" => self::AS_WRAPPER_OBJECT, + "EXTERNAL_PROPERTY" => self::AS_EXTERNAL_PROPERTY, + ); + + /** + * @var string + */ + protected $use; + + /** + * @var string + */ + protected $include; + + /** + * @var string + */ + protected $property; + + /** + * @var bool + */ + protected $visible; + + /** + * @var string + */ + protected $defaultImpl; + + /** + * @AnnotationCreator({@Parameter(name="use", type="integer", required=true), @Parameter(name="include", type="integer", required=false), @Parameter(name="property", type="string", required=false), @Parameter(name="visible", type="bool", required=false), @Parameter(name="defaultImpl", type="string", required=false)}) + * @param int $use + * @param int $include + * @param string $property + * @param bool $visible + * @param string $defaultImpl + */ + public function __construct($use, $include = null, $property = null, $visible = false, $defaultImpl = null) + { + $this->use = $use; + $this->include = isset($include) ? $include : self::$enumAs["PROPERTY"]; + $this->property = empty($property) ? null : $property; + $this->visible = isset($visible) && $visible; + $this->defaultImpl = $defaultImpl; + } + + /** + * @return string + */ + public function getInclude() + { + return $this->include; + } + + /** + * @return string + */ + public function getProperty() + { + return $this->property; + } + + /** + * @return string + */ + public function getUse() + { + return $this->use; + } + + public function getVisible() + { + return $this->visible; + } + + /** + * @return string + */ + public function getDefaultImpl() + { + return $this->defaultImpl; + } +} diff --git a/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeName.php b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeName.php new file mode 100644 index 0000000..de8c6b9 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Annotations/JsonTypeName.php @@ -0,0 +1,39 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonTypeName; + +/** + * Allows you to specify an explicit name for this implementation, for use by JsonTypeInfo + * @Annotation(on={"class"}) + */ +class JsonTypeName extends NoUndeclaredProperties implements IJsonTypeName +{ + + protected $name; + + /** + * @param string $name + * @AnnotationCreator(@Parameter(name="name", type="string", required=true)) + */ + public function __construct($name) + { + $this->name = $name; + } + + public function getName() + { + return $this->name; + } + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/ArrayCachingAnnotationDriver.php b/lib/Weasel/JsonMarshaller/Config/ArrayCachingAnnotationDriver.php new file mode 100644 index 0000000..a912eb6 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/ArrayCachingAnnotationDriver.php @@ -0,0 +1,27 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config; + +use Weasel\JsonMarshaller\Config\Annotations as Annotations; +use Psr\Log\LoggerInterface; +use Weasel\Common\Cache\ArrayCache; +use Weasel\Common\Annotation\IAnnotationReaderFactory; + +/** + * A config provider that uses Annotations + * @deprecated Use the real driver, and pass in a cache implementation. + */ +class ArrayCachingAnnotationDriver extends AnnotationDriver +{ + + public function __construct(LoggerInterface $logger = null, IAnnotationReaderFactory $annotationReaderFactory = null) + { + parent::__construct($logger, $annotationReaderFactory); + $this->setCache(new ArrayCache()); + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/ClassAnnotationDriver.php b/lib/Weasel/JsonMarshaller/Config/ClassAnnotationDriver.php new file mode 100644 index 0000000..ddc5b3f --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/ClassAnnotationDriver.php @@ -0,0 +1,620 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config; + +use Weasel\JsonMarshaller\Config\Annotations as Annotations; +use Weasel\Annotation\AnnotationReader; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerInterface; +use Weasel\Common\Annotation\IAnnotationReaderFactory; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonCreator; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonProperty; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnyGetter; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnySetter; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonTypeInfo; + +/** + * Load the configuration for a given class from annotations + */ +class ClassAnnotationDriver implements LoggerAwareInterface +{ + + /** + * @var \Weasel\Annotation\AnnotationReaderFactory + */ + protected $annotationReaderFactory; + + /** + * @var \Weasel\Common\Annotation\IAnnotationReader + */ + protected $annotationReader; + + /** + * @var \ReflectionClass + */ + protected $rClass; + + /** + * @var ClassMarshaller + */ + protected $config; + + /** + * @var string The namespace the annotations live in. Current default is the Weasel annotations. + */ + protected $annNS = '\Weasel\JsonMarshaller\Config\Annotations'; + + /** + * @param \ReflectionClass $rClass A reflection for the class we're configuring + * @param \Weasel\Common\Annotation\IAnnotationReaderFactory $annotationReaderFactory A factory for annotation readers + * @param string $annotationNamespace namespace in which we can find the annotations. + */ + public function __construct(\ReflectionClass $rClass, IAnnotationReaderFactory $annotationReaderFactory, $annotationNamespace = '\Weasel\JsonMarshaller\Config\Annotations') + { + $this->annotationReaderFactory = $annotationReaderFactory; + $this->rClass = $rClass; + $this->annNS = $annotationNamespace . '\\'; + } + + /** + * @return AnnotationReader + */ + protected function _getAnnotationReader() + { + if (!isset($this->annotationReader)) { + $this->annotationReader = $this->annotationReaderFactory->getReaderForClass($this->rClass); + } + return $this->annotationReader; + } + + /** + * @param \Reflector $thing + * @throws \Exception + * @return callable + */ + protected function _getConfigGetter(\Reflector $thing = null) + { + $reader = $this->_getAnnotationReader(); + $annNS = $this->annNS; + if ($thing === null) { + return function ($ann) use ($reader, $annNS) { + return $reader->getSingleClassAnnotation($annNS . $ann); + }; + } + if ($thing instanceof \ReflectionMethod) { + return function ($ann) use ($reader, $thing, $annNS) { + return $reader->getSingleMethodAnnotation($thing->getName(), $annNS . $ann); + }; + } + if ($thing instanceof \ReflectionProperty) { + return function ($ann) use ($reader, $thing, $annNS) { + return $reader->getSinglePropertyAnnotation($thing->getName(), $annNS . $ann); + }; + } + throw new \Exception("Unable to work out how to configure a " . get_class($thing)); + } + + protected function _configureGetter(\ReflectionMethod $method, IJsonProperty $propertyConfig) + { + $name = $method->getName(); + + $getterConfig = new Serialization\GetterSerialization(); + + $property = $propertyConfig->getName(); + if (!isset($property)) { + if (substr($name, 0, 3) === 'get') { + $property = lcfirst(substr($name, 3)); + } elseif (substr($name, 0, 2) === 'is') { + if ($propertyConfig->getType() === 'bool') { + $property = lcfirst(substr($name, 2)); + } else { + $property = lcfirst($name); + } + } else { + $property = lcfirst($name); + } + } + + $fGetConfig = $this->_getConfigGetter($method); + + /** + * @var Annotations\JsonTypeInfo $typeInfo + * @var Annotations\JsonSubTypes $subTypes + * @var Annotations\JsonInclude $includer + */ + $typeInfo = $fGetConfig('JsonTypeInfo'); + $subTypes = $fGetConfig('JsonSubTypes'); + $includer = $fGetConfig('JsonInclude'); + + $getterConfig->typeInfo = $this->_getSerializationTypeInfo($typeInfo, $subTypes); + $getterConfig->include = $this->_getIncluderValue($includer); + + if (isset($this->config->serialization->properties[$property])) { + throw new \Exception("Serialization for property of name $property has already been configured."); + } + $getterConfig->method = $name; + $getterConfig->type = $propertyConfig->getType(); + + $this->config->serialization->properties[$property] = $getterConfig; + } + + protected function _configureSetter(\ReflectionMethod $method, IJsonProperty $propertyConfig) + { + $name = $method->getName(); + + $property = $propertyConfig->getName(); + if (!isset($property)) { + if (substr($name, 0, 3) === 'set') { + $property = lcfirst(substr($name, 3)); + } else { + $property = lcfirst($name); + } + } + + $fConfigGetter = $this->_getConfigGetter($method); + + /** + * @var Annotations\JsonTypeInfo $typeInfo + * @var Annotations\JsonSubTypes $subTypes + */ + $typeInfo = $fConfigGetter('JsonTypeInfo'); + $subTypes = $fConfigGetter('JsonSubtypes'); + + if (isset($this->config->deserialization->properties[$property])) { + throw new \Exception("Deserialization for property of name $property has already been configured."); + } + $setterConfig = new Deserialization\SetterDeserialization(); + $setterConfig->method = $name; + $setterConfig->type = $propertyConfig->getType(); + $setterConfig->typeInfo = $this->_getDeserializationTypeInfo($typeInfo, $subTypes); + $setterConfig->strict = $propertyConfig->getStrict(); + + $this->config->deserialization->properties[$property] = $setterConfig; + } + + protected function _configureAnyGetter(\ReflectionMethod $method, IJsonAnyGetter $config) + { + if ($method->getNumberOfParameters() != 0) { + throw new \Exception("anyGetter {$method->getName()} must not have parameters"); + } + $this->config->serialization->anyGetter = $method->getName(); + } + + protected function _configureAnySetter(\ReflectionMethod $method, IJsonAnySetter $config) + { + if ($method->getNumberOfParameters() != 2) { + throw new \Exception("anySetter {$method->getName()} must have exactly two parameters"); + } + $this->config->deserialization->anySetter = $method->getName(); + } + + protected function _configureCreator(\ReflectionMethod $method, IJsonCreator $creatorConfig) + { + $name = $method->getName(); + if (isset($this->config->deserialization->creator)) { + throw new \Exception("Found more than one creator method! Last was $name"); + } + $rParams = $creatorConfig->getParams(); + if (count($rParams) === 0) { + $creator = new Deserialization\DelegateCreator(); + $creator->method = $name; + } else { + $creator = new Deserialization\PropertyCreator(); + $creator->method = $name; + $i = 0; + $paramNames = array(); + foreach ($rParams as $rParam) { + $paramNames[] = $rParam->getName(); + } + foreach ($creatorConfig->getParams() as $paramConfig) { + $param = new Deserialization\Param(); + $param->name = $paramConfig->getName(); + $param->type = $paramConfig->getType(); + $param->strict = $paramConfig->getStrict(); + if (!isset($param->name)) { + if (!isset($paramNames[$i])) { + throw new \Exception("Unable to establish name of param $i of $name"); + } + $param->name = $paramNames[$i]; + } + $creator->params[] = $param; + $i++; + } + if (count($creator->params) !== count($paramNames)) { + throw new \Exception('Expected ' . count($paramNames) . ' params but found ' . count($creator->params)); + } + } + $this->config->deserialization->creator = $creator; + } + + protected function _configureMethod(\ReflectionMethod $method) + { + $fGetConfig = $this->_getConfigGetter($method); + + switch (true) { + case ($method->isStatic() || $method->isConstructor()): + if ($config = $fGetConfig('JsonCreator')) { + $this->_configureCreator($method, $config); + } + break; + case ($config = $fGetConfig('JsonAnyGetter')): + $this->_configureAnyGetter($method, $config); + break; + case ($config = $fGetConfig('JsonAnySetter')): + $this->_configureAnySetter($method, $config); + break; + case ($config = $fGetConfig('JsonProperty')): + if ($method->getNumberOfRequiredParameters() == 0) { + $this->_configureGetter($method, $config); + } elseif ($method->getNumberOfRequiredParameters() == 1) { + $this->_configureSetter($method, $config); + } + break; + } + } + + protected function _configureProperty(\ReflectionProperty $property) + { + $name = $property->getName(); + + $fConfigGetter = $this->_getConfigGetter($property); + /** + * @var IJsonProperty $propertyConfig + */ + if (!$propertyConfig = $fConfigGetter('JsonProperty')) { + return; + } + $propertyName = $propertyConfig->getName(); + if (!isset($propertyName)) { + $propertyName = $name; + } + + + /** + * @var Annotations\JsonTypeInfo $typeInfo + * @var Annotations\JsonSubTypes $subTypes + */ + $typeInfo = $fConfigGetter('JsonTypeInfo'); + $subTypes = $fConfigGetter('JsonSubTypes'); + + if (!isset($this->config->deserialization->properties[$propertyName])) { + $setterConfig = new Deserialization\DirectDeserialization(); + $setterConfig->property = $name; + $setterConfig->type = $propertyConfig->getType(); + $setterConfig->typeInfo = $this->_getDeserializationTypeInfo($typeInfo, $subTypes); + + $this->config->deserialization->properties[$propertyName] = $setterConfig; + } + + + if (!isset($this->config->serialization->properties[$propertyName])) { + $getterConfig = new Serialization\DirectSerialization(); + $getterConfig->property = $name; + $getterConfig->type = $propertyConfig->getType(); + + /** + * @var Annotations\JsonInclude $includer + */ + $includer = $fConfigGetter('JsonInclude'); + $getterConfig->include = $this->_getIncluderValue($includer); + $getterConfig->typeInfo = $this->_getSerializationTypeInfo($typeInfo, $subTypes); + + $this->config->serialization->properties[$propertyName] = $getterConfig; + } + + } + + /** + * @param Annotations\JsonInclude $includer + * @return int + */ + protected function _getIncluderValue($includer) + { + $val = $this->config->serialization->include; + if (isset($includer)) { + switch ($includer->getValue()) { + case (IAnnotations\IJsonInclude::INCLUDE_ALWAYS): + $val = Serialization\ClassSerialization::INCLUDE_ALWAYS; + break; + case (IAnnotations\IJsonInclude::INCLUDE_NON_DEFAULT): + $val = Serialization\ClassSerialization::INCLUDE_NON_DEFAULT; + break; + case (IAnnotations\IJsonInclude::INCLUDE_NON_EMPTY): + $val = Serialization\ClassSerialization::INCLUDE_NON_EMPTY; + break; + case (IAnnotations\IJsonInclude::INCLUDE_NON_NULL): + $val = Serialization\ClassSerialization::INCLUDE_NON_NULL; + break; + default: + } + } + return $val; + } + + /** + * Find out what name we should use to referr to one of our subtypes. + * @param \ReflectionClass $rClass + * @return string + */ + protected function _getSubClassName(\ReflectionClass $rClass) + { + $subClassReader = $this->annotationReaderFactory->getReaderForClass($rClass); + /** + * @var Annotations\JsonTypeName $subNameA + */ + $subNameA = $subClassReader->getSingleClassAnnotation($this->annNS . 'JsonTypeName'); + if (isset($subNameA)) { + return $subNameA->getName(); + } else { + return $rClass->getName(); + } + + } + + /** + * @param Annotations\JsonTypeInfo $typeInfo + * @param Annotations\JsonSubTypes $subTypes + * @throws \Exception + * @return Deserialization\TypeInfo|null + */ + protected function _getSerializationTypeInfo($typeInfo, $subTypes) + { + + if (!isset($typeInfo)) { + return null; + } + + $typeConfig = new Serialization\TypeInfo(); + switch ($typeInfo->getUse()) { + case IJsonTypeInfo::ID_CLASS: + $typeConfig->typeInfo = Serialization\TypeInfo::TI_USE_CLASS; + $typeConfig->typeInfoProperty = '@class'; + break; + case IJsonTypeInfo::ID_CUSTOM: + $typeConfig->typeInfo = Serialization\TypeInfo::TI_USE_CUSTOM; + break; + case IJsonTypeInfo::ID_MINIMAL_CLASS: + $typeConfig->typeInfo = Serialization\TypeInfo::TI_USE_MINIMAL_CLASS; + $typeConfig->typeInfoProperty = '@class'; + break; + case IJsonTypeInfo::ID_NAME: + $typeConfig->typeInfo = Serialization\TypeInfo::TI_USE_NAME; + $typeConfig->typeInfoProperty = '@name'; + break; + case IJsonTypeInfo::ID_NONE: + $typeConfig->typeInfo = Serialization\TypeInfo::TI_USE_NONE; + return null; + break; + + } + + if ($typeInfo->getProperty() !== null) { + $typeConfig->typeInfoProperty = $typeInfo->getProperty(); + } + + switch ($typeInfo->getInclude()) { + case IJsonTypeInfo::AS_PROPERTY: + $typeConfig->typeInfoAs = Serialization\TypeInfo::TI_AS_PROPERTY; + break; + case IJsonTypeInfo::AS_WRAPPER_ARRAY: + $typeConfig->typeInfoAs = Serialization\TypeInfo::TI_AS_WRAPPER_ARRAY; + break; + case IJsonTypeInfo::AS_WRAPPER_OBJECT: + $typeConfig->typeInfoAs = Serialization\TypeInfo::TI_AS_WRAPPER_OBJECT; + break; + case IJsonTypeInfo::AS_EXTERNAL_PROPERTY: + $typeConfig->typeInfoAs = Serialization\TypeInfo::TI_AS_EXTERNAL_PROPERTY; + break; + } + + if (isset($subTypes)) { + foreach ($subTypes->getValue() as $type) { + switch ($typeConfig->typeInfo) { + case Serialization\TypeInfo::TI_USE_CLASS: + $subName = ltrim($type->getValue(), '\\'); + break; + case Serialization\TypeInfo::TI_USE_MINIMAL_CLASS: + $exploded = explode('\\', $type->getValue(), 2); + $subName = $exploded[0]; + break; + case Serialization\TypeInfo::TI_USE_NAME: + $subName = $type->getName(); + if (empty($subName)) { + $subName = $this->_getSubClassName(new \ReflectionClass($type->getValue())); + } + break; + case Serialization\TypeInfo::TI_USE_CUSTOM: + default: + throw new \Exception("Unsupported typeinfo mode"); + } + $typeConfig->subTypes[ltrim($type->getValue(), '\\')] = $subName; + } + } + + return $typeConfig; + + + } + + /** + * For the given typeinfo, and sub type info, work out how we're going to be deserialized. + * + * @param Annotations\JsonTypeInfo $typeInfo + * @param Annotations\JsonSubTypes $subTypes + * @throws \Exception + * @return Deserialization\TypeInfo|null + */ + protected function _getDeserializationTypeInfo($typeInfo, $subTypes) + { + + if (!isset($typeInfo)) { + return null; + } + + $typeConfig = new Deserialization\TypeInfo(); + /** + * Based on the Use value we should also choose the default property name + */ + switch ($typeInfo->getUse()) { + case IJsonTypeInfo::ID_CLASS: + $typeConfig->typeInfo = Deserialization\TypeInfo::TI_USE_CLASS; + $typeConfig->typeInfoProperty = '@class'; + break; + case IJsonTypeInfo::ID_CUSTOM: + $typeConfig->typeInfo = Deserialization\TypeInfo::TI_USE_CUSTOM; + break; + case IJsonTypeInfo::ID_MINIMAL_CLASS: + $typeConfig->typeInfo = Deserialization\TypeInfo::TI_USE_MINIMAL_CLASS; + $typeConfig->typeInfoProperty = '@class'; + break; + case IJsonTypeInfo::ID_NAME: + $typeConfig->typeInfo = Deserialization\TypeInfo::TI_USE_NAME; + $typeConfig->typeInfoProperty = '@name'; + break; + case IJsonTypeInfo::ID_NONE: + $typeConfig->typeInfo = Deserialization\TypeInfo::TI_USE_NONE; + return null; + break; + + } + + if ($typeInfo->getProperty() !== null) { + // If there is a property specified then we should use that rather than the default + $typeConfig->typeInfoProperty = $typeInfo->getProperty(); + } + + $typeConfig->typeInfoVisible = $typeInfo->getVisible(); + $typeConfig->defaultImpl = $typeInfo->getDefaultImpl(); + + switch ($typeInfo->getInclude()) { + case IJsonTypeInfo::AS_PROPERTY: + $typeConfig->typeInfoAs = Deserialization\TypeInfo::TI_AS_PROPERTY; + break; + case IJsonTypeInfo::AS_WRAPPER_ARRAY: + $typeConfig->typeInfoAs = Deserialization\TypeInfo::TI_AS_WRAPPER_ARRAY; + break; + case IJsonTypeInfo::AS_WRAPPER_OBJECT: + $typeConfig->typeInfoAs = Deserialization\TypeInfo::TI_AS_WRAPPER_OBJECT; + break; + case IJsonTypeInfo::AS_EXTERNAL_PROPERTY: + $typeConfig->typeInfoAs = Deserialization\TypeInfo::TI_AS_EXTERNAL_PROPERTY; + break; + } + + if (isset($subTypes)) { + // Now we need to store a mapping from our discriminator values to the sub types + foreach ($subTypes->getValue() as $type) { + switch ($typeConfig->typeInfo) { + case Deserialization\TypeInfo::TI_USE_CLASS: + $subName = ltrim($type->getValue(), '\\'); + break; + case Deserialization\TypeInfo::TI_USE_MINIMAL_CLASS: + $exploded = explode('\\', $type->getValue(), 2); + $subName = $exploded[0]; + break; + case Deserialization\TypeInfo::TI_USE_NAME: + $subName = $type->getName(); + if (empty($subName)) { + // We've got to find out if our sub class has a JsonTypeName annotation + $subName = $this->_getSubClassName(new \ReflectionClass($type->getValue())); + } + break; + case Deserialization\TypeInfo::TI_USE_CUSTOM: + default: + throw new \Exception("Unsupported typeinfo mode"); + } + $typeConfig->subTypes[$subName] = ltrim($type->getValue(), '\\'); + } + } + + return $typeConfig; + + + } + + /** + * Get the config for the current class. + * @return ClassMarshaller A populated ClassMarshaller config object. + */ + public function getConfig() + { + $this->config = new ClassMarshaller(); + $this->config->serialization = new Serialization\ClassSerialization(); + $this->config->deserialization = new Deserialization\ClassDeserialization(); + + $reader = $this->_getAnnotationReader(); + + /** + * @var \Weasel\JsonMarshaller\Config\Annotations\JsonInclude $includer + */ + $includer = $reader->getSingleClassAnnotation($this->annNS . 'JsonInclude'); + $this->config->serialization->include = $this->_getIncluderValue($includer); + + /** + * Work out what the class' "name" is, just in case inheritance is needed. + * @var \Weasel\JsonMarshaller\Config\Annotations\JsonTypeName $typeNamer + */ + $typeNamer = $reader->getSingleClassAnnotation($this->annNS . 'JsonTypeName'); + $name = null; + if (isset($typeNamer)) { + $name = $typeNamer->getName(); + } + if (empty($name)) { + // Default to the unqualified class name + $name = $this->rClass->getName(); + } + $this->config->deserialization->name = $name; + + /** + * @var Annotations\JsonTypeInfo $typeInfo + * @var Annotations\JsonSubTypes $subTypes + */ + $typeInfo = $reader->getSingleClassAnnotation($this->annNS . 'JsonTypeInfo'); + $subTypes = $reader->getSingleClassAnnotation($this->annNS . 'JsonSubTypes'); + $this->config->deserialization->typeInfo = $this->_getDeserializationTypeInfo($typeInfo, $subTypes); + $this->config->serialization->typeInfo = $this->_getSerializationTypeInfo($typeInfo, $subTypes); + + $methods = $this->rClass->getMethods(\ReflectionMethod::IS_PUBLIC); + + foreach ($methods as $method) { + $this->_configureMethod($method); + } + + $properties = $this->rClass->getProperties(\ReflectionProperty::IS_PUBLIC & ~\ReflectionProperty::IS_STATIC); + foreach ($properties as $property) { + $this->_configureProperty($property); + } + + /** + * @var \Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties $ignorer + */ + $ignorer = $reader->getSingleClassAnnotation($this->annNS . 'JsonIgnoreProperties'); + if (!empty($ignorer)) { + // The ignorer config affects which properties we will consider. + $this->config->deserialization->ignoreUnknown = $ignorer->getIgnoreUnknown(); + $this->config->deserialization->ignoreProperties = $ignorer->getNames(); + } + + + return $this->config; + + } + + + /** + * Sets a logger instance on the object + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->annotationReaderFactory->setLogger($logger); + } + + +} diff --git a/lib/Weasel/JsonMarshaller/Config/ClassMarshaller.php b/lib/Weasel/JsonMarshaller/Config/ClassMarshaller.php new file mode 100644 index 0000000..ef21b35 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/ClassMarshaller.php @@ -0,0 +1,42 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config; + +/** + * Holder for the configuration for marshalling of a class + */ +use Weasel\JsonMarshaller\Config\Serialization\ClassSerialization; +use Weasel\JsonMarshaller\Config\Deserialization\ClassDeserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class ClassMarshaller +{ + + public function __construct() + { + $this->serialization = new ClassSerialization(); + $this->deserialization = new ClassDeserialization(); + } + + /** + * @var \Weasel\JsonMarshaller\Config\Serialization\ClassSerialization + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Serialization\ClassSerialization") + */ + public $serialization; + + /** + * @var \Weasel\JsonMarshaller\Config\Deserialization\ClassDeserialization + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\ClassDeserialization") + */ + public $deserialization; + + public function __toString() + { + return "[ClassMarshaller serialization=" . $this->serialization . " deserialization=" . $this->deserialization . "]"; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/ClassDeserialization.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/ClassDeserialization.php new file mode 100644 index 0000000..9d1a4e6 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Deserialization/ClassDeserialization.php @@ -0,0 +1,79 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Deserialization; + +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class ClassDeserialization +{ + + /** + * @var \Weasel\JsonMarshaller\Config\Deserialization\PropertyDeserialization[] + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\PropertyDeserialization[string]") + */ + public $properties = array(); + + /** + * @var \Weasel\JsonMarshaller\Config\Deserialization\Creator + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\Creator") + */ + public $creator = null; + + /** + * @var bool + * @JsonProperty(type="bool") + */ + public $ignoreUnknown; + + /** + * @var string[] + * @JsonProperty(type="string[]") + */ + public $ignoreProperties; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $name; + + /** + * @var \Weasel\JsonMarshaller\Config\Deserialization\TypeInfo + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\TypeInfo") + */ + public $typeInfo; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $anySetter = null; + + + function __construct($name = null, $properties = array(), $anySetter = null, $creator = null, $ignoreProperties = null, $ignoreUnknown = null, $typeInfo = null) + { + $this->anySetter = $anySetter; + $this->creator = $creator; + $this->ignoreProperties = $ignoreProperties; + $this->ignoreUnknown = $ignoreUnknown; + $this->name = $name; + $this->properties = $properties; + $this->typeInfo = $typeInfo; + } + + public function __toString() + { + $props = array(); + foreach ($this->properties as $key => $value) { + $props[] = $key . ' => ' . $value; + } + return '[ClassDeserialization name=' . $this->name . ' ignoreProperties={' . implode(', ', + $this->ignoreProperties) . '} anySetter=' . $this->anySetter . + ' ignoreUnknown=' . ($this->ignoreUnknown ? "true" : "false") . ' typeInfo=' . $this->typeInfo . ' creator=' . $this->creator . + ' properties={' . implode(", ", $props) . '}'; + } +} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/Creator.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/Creator.php new file mode 100644 index 0000000..34c9c8d --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Deserialization/Creator.php @@ -0,0 +1,36 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Deserialization; + +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +/** + * Class Creator + * @package Weasel\JsonMarshaller\Config\Deserialization + * @JsonSubTypes({ + * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Deserialization\DelegateCreator"), + * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Deserialization\PropertyCreator"), + * }) + * @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="creator") + */ +abstract class Creator +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $method; + + public function __toString() + { + return '[Creator method=' . $this->method . ']'; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/DelegateCreator.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/DelegateCreator.php new file mode 100644 index 0000000..0aafb06 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Deserialization/DelegateCreator.php @@ -0,0 +1,24 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class DelegateCreator + * @package Weasel\JsonMarshaller\Config\Deserialization + * @JsonTypeName("delegate") + */ +class DelegateCreator extends Creator +{ + + public function __toString() + { + return '[DelegateCreator method=' . $this->method . ']'; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/DirectDeserialization.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/DirectDeserialization.php new file mode 100644 index 0000000..843d4a8 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Deserialization/DirectDeserialization.php @@ -0,0 +1,34 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class DirectDeserialization + * @package Weasel\JsonMarshaller\Config\Deserialization + * @JsonTypeName("direct") + */ +class DirectDeserialization extends PropertyDeserialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $property; + + function __construct() + { + $this->how = "direct"; + } + + public function __toString() + { + return "[DirectDeserialization property={$this->property} type={$this->realType} typeInfo={$this->typeInfo}]"; + } +} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/Feature.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/Feature.php new file mode 100644 index 0000000..e251b26 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Deserialization/Feature.php @@ -0,0 +1,31 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Deserialization; + +/** + * Features for config general mapper behaviour. + * These are the keys to be passed to the mapper configure() method. + */ +interface Feature { + /** + * bool. When true, throw an exception (UnknownPropertyException) on encountering an unknown property in the JSON and + * there's no AnySetter configured (or ignoreUnknown isn't set.) Default: false. + */ + const FAIL_ON_UNKNOWN_PROPERTIES = "deserialization::fail_on_unknown"; + /** + * bool. When true trigger an E_USER_WARNING on encountering an unknown property in the JSON and there's no AnySetter + * configured (or ignoreUnknown isn't set.) Default: true. + */ + const WARN_ON_UNKNOWN_PROPERTIES = "deserialization::warn_on_unknown"; + + /** + * bool. When true apply strict type checking. JSON types encountered are expected to match the PHP types we're + * going to deserialize to. If they don't, throw an exception. Default true. + */ + const STRICT_TYPES = "deserialization::strict_types"; + +} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/Param.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/Param.php new file mode 100644 index 0000000..6b98c01 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Deserialization/Param.php @@ -0,0 +1,30 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class Param + * @package Weasel\JsonMarshaller\Config\Deserialization + * @JsonTypeName("param") + */ +class Param extends PropertyDeserialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $name; + + public function __toString() + { + return "[ParamDeserialization name={$this->name} type={$this->type} typeInfo={$this->typeInfo}]"; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyCreator.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyCreator.php new file mode 100644 index 0000000..27c59e5 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyCreator.php @@ -0,0 +1,29 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class PropertyCreator + * @package Weasel\JsonMarshaller\Config\Deserialization + * @JsonTypeName("property") + */ +class PropertyCreator extends Creator +{ + /** + * @var \Weasel\JsonMarshaller\Config\Deserialization\Param[] + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\Param[]") + */ + public $params = array(); + + public function __toString() + { + return "[PropertyCreator method={$this->method} params={" . implode(", ", $this->params) . "}]"; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyDeserialization.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyDeserialization.php new file mode 100644 index 0000000..fbd8d67 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Deserialization/PropertyDeserialization.php @@ -0,0 +1,69 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo; +use Weasel\JsonMarshaller\Config\Type\Type; +use Weasel\JsonMarshaller\Config\Type\TypeParser; + +/** + * Class PropertyDeserialization + * @package Weasel\JsonMarshaller\Config\Deserialization + * @JsonSubTypes({ + * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Deserialization\Param"), + * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Deserialization\SetterDeserialization"), + * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Deserialization\DirectDeserialization"), + * }) + * @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="how", visible=true) + */ +abstract class PropertyDeserialization +{ + + /** + * @var Type + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Type\Type") + */ + public $realType; + + /** + * @var \Weasel\JsonMarshaller\Config\Deserialization\TypeInfo + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Deserialization\TypeInfo") + */ + public $typeInfo; + + /** + * @var bool Should type checking be strict? + * @JsonProperty(type="bool") + */ + public $strict = true; + + public $how; + + /** + * @param string $value + * @JsonProperty(type="string") + * @deprecated exists only for backwards compat, use realType. + */ + public function setType($value) + { + $this->realType = TypeParser::parseTypeString($value); + } + + /** + * @return string + */ + abstract public function __toString(); + + public function __set($key, $value) + { + if ($key == "type") { + $this->setType($value); + } + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/SetterDeserialization.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/SetterDeserialization.php new file mode 100644 index 0000000..bc589f7 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Deserialization/SetterDeserialization.php @@ -0,0 +1,36 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Deserialization; + +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class SetterDeserialization + * @package Weasel\JsonMarshaller\Config\Deserialization + * @JsonTypeName("setter") + */ +class SetterDeserialization extends PropertyDeserialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $method; + + function __construct() + { + $this->how = "setter"; + } + + public function __toString() + { + return "[SetterDeserialization method={$this->method} type={$this->realType} typeInfo={$this->typeInfo}]"; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Deserialization/TypeInfo.php b/lib/Weasel/JsonMarshaller/Config/Deserialization/TypeInfo.php new file mode 100644 index 0000000..aaa6f81 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Deserialization/TypeInfo.php @@ -0,0 +1,65 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class TypeInfo +{ + const TI_USE_CLASS = 1; + const TI_USE_CUSTOM = 2; + const TI_USE_MINIMAL_CLASS = 3; + const TI_USE_NAME = 4; + const TI_USE_NONE = 5; + + const TI_AS_PROPERTY = 1; + const TI_AS_WRAPPER_OBJECT = 2; + const TI_AS_WRAPPER_ARRAY = 3; + const TI_AS_EXTERNAL_PROPERTY = 4; + + /** + * @var string[] + * @JsonProperty(type="string[string]") + */ + public $subTypes; + + /** + * @var int + * @JsonProperty(type="int") + */ + public $typeInfo = self::TI_USE_NONE; + + /** + * @var int + * @JsonProperty(type="int") + */ + public $typeInfoAs = self::TI_AS_PROPERTY; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $defaultImpl; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $typeInfoProperty; + + /** + * @var bool + * @JsonProperty(type="bool") + */ + public $typeInfoVisible = false; + + public function __toString() + { + return '[TypeInfo subTypes={' . implode(', ', $this->subTypes) . '} typeInfo=' . $this->typeInfo . + ' typeInfoAs=' . $this->typeInfoAs . ' typeInfoProperty=' . $this->typeInfoProperty . + 'defaultImpl=' . $this->defaultImpl . ' typeInfoVisible=' . ($this->typeInfoVisible ? "true" : "false") . ']'; + } +} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetter.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetter.php new file mode 100644 index 0000000..76cb5a8 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetter.php @@ -0,0 +1,21 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Weasel\Common\Utils\NoUndeclaredProperties; +use Doctrine\Common\Annotations\Annotation; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnyGetter; + +/** + * @Annotation + * @Target("METHOD") + */ +class JsonAnyGetter extends NoUndeclaredProperties implements IJsonAnyGetter +{ + + +} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetter.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetter.php new file mode 100644 index 0000000..76de796 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetter.php @@ -0,0 +1,21 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Weasel\Common\Utils\NoUndeclaredProperties; +use Doctrine\Common\Annotations\Annotation; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonAnySetter; + +/** + * @Annotation + * @Target("METHOD") + */ +class JsonAnySetter extends NoUndeclaredProperties implements IJsonAnySetter +{ + + +} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php new file mode 100644 index 0000000..67f5c1e --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php @@ -0,0 +1,51 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonCreator; + +/** + * @Annotation + * @Target("METHOD") + */ + +class JsonCreator extends NoUndeclaredProperties implements IJsonCreator +{ + + /** + * @var array + */ + public $params = array(); + + /** + * @return JsonProperty[] + */ + public function getParams() + { + return $this->params; + } + + /** + * @param array $values + */ + public function __construct($values) + { + if (isset($values["params"])) { + $this->params = $values["params"]; + } elseif (isset($values["value"])) { + if (!is_array($values["value"])) { + $this->params = array($values["value"]); + } else { + $this->params = $values["value"]; + } + } + } + + +} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php new file mode 100644 index 0000000..a895c38 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php @@ -0,0 +1,68 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Weasel\Common\Utils\NoUndeclaredProperties; +use Doctrine\Common\Annotations\Annotation; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonIgnoreProperties; + +/** + * Provides a list of properties not to consider when serializing/deserializing. + * If ignoreUnknown is true then errors will not be thrown when we encounter properties to deserialize that we do not have a property for, + * they will just be discarded. + * + * @Annotation + * @Target("CLASS") + */ +class JsonIgnoreProperties extends NoUndeclaredProperties implements IJsonIgnoreProperties +{ + + /** + * @return bool + */ + public function getIgnoreUnknown() + { + return $this->ignoreUnknown; + } + + /** + * @return string[] + */ + public function getNames() + { + return $this->names; + } + + /** + * @var array + */ + public $names = array(); + + /** + * @var bool + */ + public $ignoreUnknown = false; + + /** + * @param array $values + */ + public function __construct($values) + { + if (isset($values["names"])) { + $this->names = $values["names"]; + } elseif (isset($values["value"])) { + if (!is_array($values["value"])) { + $this->names = array($values["value"]); + } else { + $this->names = $values["value"]; + } + } + if (isset($values["ignoreUnknown"])) { + $this->ignoreUnknown = $values["ignoreUnknown"]; + } + } +} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonInclude.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonInclude.php new file mode 100644 index 0000000..0b737e9 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonInclude.php @@ -0,0 +1,38 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Weasel\Common\Utils\NoUndeclaredProperties; +use Doctrine\Common\Annotations\Annotation; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonInclude; + +/** + * @Annotation + * @Target({"CLASS", "METHOD", "PROPERTY"}) + */ +class JsonInclude extends NoUndeclaredProperties implements IJsonInclude +{ + + /** + * @var integer + * @Enum({\Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude::INCLUDE_ALWAYS, + * \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude::INCLUDE_NON_DEFAULT, + * \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude::INCLUDE_NON_EMPTY, + * \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude::INCLUDE_NON_NULL + * }) + */ + public $value; + + /** + * @return int + */ + public function getValue() + { + return $this->value; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php new file mode 100644 index 0000000..892afde --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php @@ -0,0 +1,77 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonProperty; + +/** + * Sets a property up to be serialized/deserialized explicitly. + * The name sets the json field name to use for this property. + * The type specifies the type to use. + * Because PHP is not strongly typed we can only make best guesses about types if you do not provide type info! + * + * @Annotation + * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) + */ +class JsonProperty extends NoUndeclaredProperties implements IJsonProperty +{ + + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $type; + + /** + * @var bool + */ + public $strict = true; + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } + + public function __construct($value) + { + if (isset($value["name"])) { + $this->name = $value["name"]; + } + if (isset($value["type"])) { + $this->type = $value["type"]; + } + if (isset($value["strict"])) { + $this->strict = $value["strict"]; + } + } + + /** + * @return bool + */ + public function getStrict() + { + return $this->strict; + } + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes.php new file mode 100644 index 0000000..cad1a27 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes.php @@ -0,0 +1,35 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Weasel\Common\Utils\NoUndeclaredProperties; +use Doctrine\Common\Annotations\Annotation; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonSubTypes; + +/** + * The list of subtypes of this base class + * @Annotation + * @Target({"CLASS", "METHOD", "PROPERTY"}) + */ +class JsonSubTypes extends NoUndeclaredProperties implements IJsonSubTypes +{ + + /** + * @var array + */ + public $value; + + /** + * @return JsonSubTypes\Type[] + */ + public function getValue() + { + return $this->value; + } + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes/Type.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes/Type.php new file mode 100644 index 0000000..f246163 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonSubTypes/Type.php @@ -0,0 +1,49 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\Common\Utils\NoUndeclaredProperties; +use Weasel\JsonMarshaller\Config\IAnnotations\JsonSubTypes\IType; + +/** + * A subtype + * @Annotation + * @Target("ANNOTATION") + */ +class Type extends NoUndeclaredProperties implements IType +{ + + /** + * @var string + */ + public $value; + + /** + * @var string + */ + public $name; + + + /** + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeInfo.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeInfo.php new file mode 100644 index 0000000..7a901a8 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeInfo.php @@ -0,0 +1,81 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Weasel\Common\Utils\NoUndeclaredProperties; +use Doctrine\Common\Annotations\Annotation; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonTypeInfo; + +/** + * @Annotation + * @Target({"CLASS", "METHOD", "PROPERTY"}) + */ +class JsonTypeInfo extends NoUndeclaredProperties implements IJsonTypeInfo +{ + + /** + * @var int + */ + public $use = self::ID_CLASS; + + /** + * @var int + */ + public $include = self::AS_PROPERTY; + + /** + * @var string + */ + public $property = '@type'; + + /** + * @var bool + */ + public $visible = false; + + /** + * @var string + */ + public $defaultImpl; + + /** + * @return string + */ + public function getInclude() + { + return $this->include; + } + + /** + * @return string + */ + public function getProperty() + { + return $this->property; + } + + /** + * @return string + */ + public function getUse() + { + return $this->use; + } + + public function getVisible() + { + return $this->visible; + } + + /** + * @return string + */ + public function getDefaultImpl() + { + return $this->defaultImpl; + } +} diff --git a/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeName.php b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeName.php new file mode 100644 index 0000000..941b87d --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonTypeName.php @@ -0,0 +1,35 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Weasel\Common\Utils\NoUndeclaredProperties; +use Doctrine\Common\Annotations\Annotation; +use Weasel\JsonMarshaller\Config\IAnnotations\IJsonTypeName; + +/** + * Allows you to specify an explicit name for this implementation, for use by JsonTypeInfo + * @Annotation + * @Target("CLASS") + */ +class JsonTypeName extends NoUndeclaredProperties implements IJsonTypeName +{ + + /** + * @var string + */ + public $name; + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnyGetter.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnyGetter.php new file mode 100644 index 0000000..e28892a --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnyGetter.php @@ -0,0 +1,18 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\IAnnotations; + + +/** + * Used to mark as method as the "Any Getter." + * + * A method so marked will be called to obtain a map of extra stuff to add to the output. + */ +interface IJsonAnyGetter +{ + +} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnySetter.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnySetter.php new file mode 100644 index 0000000..e72975b --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonAnySetter.php @@ -0,0 +1,18 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\IAnnotations; + + +/** + * Mark a method as the "Any Setter" + * This method will be called with a set of key => value pairs containing any data from the JSON that we didn't + * recognise as belonging in another field. + */ +interface IJsonAnySetter +{ + +} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonCreator.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonCreator.php new file mode 100644 index 0000000..65688f4 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonCreator.php @@ -0,0 +1,20 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\IAnnotations; + +/** + * Mark a static factory method or constructor, and define the params to call it with. + */ +interface IJsonCreator +{ + + /** + * @return IJsonProperty[] An array of IJsonProperty defining the params to call the method with. + */ + public function getParams(); + +} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonIgnoreProperties.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonIgnoreProperties.php new file mode 100644 index 0000000..140504e --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonIgnoreProperties.php @@ -0,0 +1,25 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\IAnnotations; + +/** + * Configure the ignoring of unknown JSON elements for a class. + */ +interface IJsonIgnoreProperties +{ + + /** + * @return bool True if we should silently ignore all unknowns, false if not. + */ + public function getIgnoreUnknown(); + + /** + * @return string[] List of JSON properties we should silently ignore. + */ + public function getNames(); + +} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonInclude.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonInclude.php new file mode 100644 index 0000000..986da77 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonInclude.php @@ -0,0 +1,25 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\IAnnotations; + +/** + * Set what properties to include for a class when serializing to JSON. + */ +interface IJsonInclude +{ + + const INCLUDE_ALWAYS = 1; // Always include every property + const INCLUDE_NON_DEFAULT = 2; // Include any property not set to it's default value. + const INCLUDE_NON_EMPTY = 3; // Include any property that isn't empty() + const INCLUDE_NON_NULL = 4; // Include any property that isn't === null + + /** + * @return int One of the INCLUDE_ consts. + */ + public function getValue(); + +} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonProperty.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonProperty.php new file mode 100644 index 0000000..734642c --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonProperty.php @@ -0,0 +1,36 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\IAnnotations; + +/** + * Sets a property up to be serialized/deserialized explicitly. + * The name sets the json field name to use for this property. + * The type specifies the type to use. + * Because PHP is not strongly typed we can only make best guesses about types if you do not provide type info! + */ +interface IJsonProperty +{ + + /** + * @return string Name to use for the JSON field (optional.) For a property the default is lcfirst($propertyName) + * For a method any leading "get" or "set" will be stripped, and a leading "is" stripped if the + * type's a bool and the method is thought to be a getter (it has 1 param.) + */ + public function getName(); + + /** + * @return string The Weasel type for the field. + */ + public function getType(); + + /** + * @return bool Should strict type checking be used? + */ + public function getStrict(); + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonSubTypes.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonSubTypes.php new file mode 100644 index 0000000..a51b965 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonSubTypes.php @@ -0,0 +1,21 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\IAnnotations; + +/** + * The list of subtypes of this base class. + */ +interface IJsonSubTypes +{ + + /** + * @return JsonSubTypes\IType[] The list of sub-types + */ + public function getValue(); + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeInfo.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeInfo.php new file mode 100644 index 0000000..ec1805b --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeInfo.php @@ -0,0 +1,63 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\IAnnotations; + +/** + * Configure behaviour when dealing with inheritance. + * When on a class this defines the behaviour to use when dealing with it's subclasses. + * When on a property this defines the behaviour to use when dealing with subclasses of a the property's type. + * + * Without this we wont be able to work out how to encode the type of subclasses. + */ +interface IJsonTypeInfo +{ + + /* + * These constants define what to use as the identifier of a subclass + */ + const ID_CLASS = 1; // Use the fully qualified class name. + const ID_CUSTOM = 2; // Use a custom method to obtain the name. + const ID_MINIMAL_CLASS = 3; // Use the class name not including namespace. + const ID_NAME = 4; // Use a "name" configured by @JsonSubTypes (on the parent) or @JsonTypeName (on the child) + const ID_NONE = 5; // Don't store anything. This will not permit deserialization as a subclass (default.) + + /* + * And these constants set where to store the identifier. + */ + const AS_PROPERTY = 1; // Store as a property on the JSON object (default.) + const AS_WRAPPER_ARRAY = 2; // Store as a wrapper array e.g. array($id, $object) + const AS_WRAPPER_OBJECT = 3; // Store as a wrapper object e.g. array($id => $object) + const AS_EXTERNAL_PROPERTY = 4; // Store as a property on the containing object (only works if on a property.) + + /** + * @return int Get how to include the ID, one of the AS_ constants. + */ + public function getInclude(); + + /** + * @return string If we're storing as property or ext property, what name should we use? + * Default for ID_*CLASS is "@class" + * Default for ID_NAME is "@name" + */ + public function getProperty(); + + /** + * @return int Get what to use as the ID, one of the ID_ constants. + */ + public function getUse(); + + /** + * @return bool If we're storing as a property should the property be visible on the PHP object? + */ + public function getVisible(); + + /** + * @return string If we can't work out what subclass to use, we'll assume it's one of these. Fully qualified class. + */ + public function getDefaultImpl(); + +} diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeName.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeName.php new file mode 100644 index 0000000..ec39d9c --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/IAnnotations/IJsonTypeName.php @@ -0,0 +1,21 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\IAnnotations; + +/** + * Allows you to specify an explicit name for a class, for use by JsonTypeInfo + */ +interface IJsonTypeName +{ + + /** + * @return string The name. + */ + public function getName(); + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/IAnnotations/JsonSubTypes/IType.php b/lib/Weasel/JsonMarshaller/Config/IAnnotations/JsonSubTypes/IType.php new file mode 100644 index 0000000..2faf1e7 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/IAnnotations/JsonSubTypes/IType.php @@ -0,0 +1,26 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\IAnnotations\JsonSubTypes; + +/** + * Type values for use in IJsonSubTypes; + */ +interface IType +{ + + /** + * @return string The fully qualified class which is our subtype (required.) + */ + public function getValue(); + + /** + * @return string The name to use for this subtype (optional.) + */ + public function getName(); + +} + diff --git a/lib/Weasel/JsonMarshaller/Config/JsonConfigProvider.php b/lib/Weasel/JsonMarshaller/Config/JsonConfigProvider.php new file mode 100644 index 0000000..b3e8c32 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/JsonConfigProvider.php @@ -0,0 +1,22 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config; + +/** + * A config provider is expected to somehow obtain the configuration (Config\ClassMarshaller) for a named class. + */ +interface JsonConfigProvider +{ + + /** + * Obtain the config for a named class + * @param string $class The class to get the config for + * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found + */ + public function getConfig($class); + +} diff --git a/lib/Weasel/JsonMarshaller/Config/MultiConfigProvider.php b/lib/Weasel/JsonMarshaller/Config/MultiConfigProvider.php new file mode 100644 index 0000000..2d6f4bb --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/MultiConfigProvider.php @@ -0,0 +1,46 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ + +namespace Weasel\JsonMarshaller\Config; + +/** + * Allow you to have multiple config sources, all working together to provide one config. + * This would be useful if you've broken your JSON config up into multiple different files for some reason. + * @package Weasel\JsonMarshaller\Config + */ +class MultiConfigProvider implements JsonConfigProvider +{ + + /** + * @var JsonConfigProvider[] + */ + private $providers = array(); + + /** + * @param JsonConfigProvider[] $providers Array of providers + */ + public function __construct(array $providers = array()) + { + $this->providers = $providers; + } + + /** + * Obtain the config for a named class + * @param string $class The class to get the config for + * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found + */ + public function getConfig($class) + { + foreach ($this->providers as $provider) { + $config = $provider->getConfig($class); + if ($config) { + return $config; + } + } + return null; + } +} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/PropertyConfigProvider.php b/lib/Weasel/JsonMarshaller/Config/PropertyConfigProvider.php new file mode 100644 index 0000000..ac31c44 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/PropertyConfigProvider.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ + +namespace Weasel\JsonMarshaller\Config; + +/** + * Class PropertyConfigProvider + * A really boring config provider which works off a public property containing a config object structure. + * This might be suitable for building a configuration from some DI framework or something. + * @package Weasel\JsonMarshaller\Config + */ +class PropertyConfigProvider implements JsonConfigProvider +{ + + /** + * @var ClassMarshaller[] Map of class names to ClassMarshallers + */ + public $config = array(); + + /** + * @param ClassMarshaller[] $config Map of class names to ClassMarshallers + */ + public function __construct(array $config = array()) + { + $this->config = $config; + } + + /** + * Obtain the config for a named class + * @param string $class The class to get the config for + * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found + */ + public function getConfig($class) + { + $class = ltrim($class, '\\'); + if (isset($this->config[$class])) { + return $this->config[$class]; + } + return null; + } +} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Serialization/ClassSerialization.php b/lib/Weasel/JsonMarshaller/Config/Serialization/ClassSerialization.php new file mode 100644 index 0000000..72bcfd2 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Serialization/ClassSerialization.php @@ -0,0 +1,51 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Serialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class ClassSerialization +{ + + const INCLUDE_ALWAYS = 1; + const INCLUDE_NON_DEFAULT = 2; + const INCLUDE_NON_EMPTY = 3; + const INCLUDE_NON_NULL = 4; + + /** + * @var \Weasel\JsonMarshaller\Config\Serialization\PropertySerialization[] Map of names to how to serialize them + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Serialization\PropertySerialization[string]") + */ + public $properties = array(); + + /** + * @var int + * @JsonProperty(type="int") + */ + public $include = self::INCLUDE_ALWAYS; + + /** + * @var \Weasel\JsonMarshaller\Config\Serialization\TypeInfo + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Serialization\TypeInfo") + */ + public $typeInfo; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $anyGetter = null; + + public function __toString() + { + $props = array(); + foreach ($this->properties as $key => $value) { + $props[] = $key . ' => ' . $value; + } + return '[ClassSerialization include=' . $this->include . ' anyGetter=' . $this->anyGetter . ' typeInfo=' . $this->typeInfo . + ' properties={' . implode(", ", $props) . '}'; + } +} diff --git a/lib/Weasel/JsonMarshaller/Config/Serialization/DirectSerialization.php b/lib/Weasel/JsonMarshaller/Config/Serialization/DirectSerialization.php new file mode 100644 index 0000000..bb61f0d --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Serialization/DirectSerialization.php @@ -0,0 +1,35 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Serialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class DirectSerialization + * @package Weasel\JsonMarshaller\Config\Serialization + * @JsonTypeName("direct") + */ +class DirectSerialization extends PropertySerialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $property; + + function __construct() + { + $this->how = "direct"; + } + + public function __toString() + { + return "[DirectSerialization property={$this->property} include={$this->include} type={$this->realType} typeInfo={$this->typeInfo}]"; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Serialization/GetterSerialization.php b/lib/Weasel/JsonMarshaller/Config/Serialization/GetterSerialization.php new file mode 100644 index 0000000..b881265 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Serialization/GetterSerialization.php @@ -0,0 +1,40 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Serialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class GetterSerialization + * @package Weasel\JsonMarshaller\Config\Serialization + * @JsonTypeName("getter") + */ +class GetterSerialization extends PropertySerialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $method; + + function __construct($method = null, $type = null, $include = null, $typeInfo = null) + { + $this->method = $method; + $this->include = $include; + $this->typeInfo = $typeInfo; + $this->how = "getter"; + $this->setType($type); + } + + public function __toString() + { + return "[GetterSerialization method={$this->method} include={$this->include} type={$this->realType} typeInfo={$this->typeInfo}]"; + } + + +} diff --git a/lib/Weasel/JsonMarshaller/Config/Serialization/PropertySerialization.php b/lib/Weasel/JsonMarshaller/Config/Serialization/PropertySerialization.php new file mode 100644 index 0000000..3e761f0 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Serialization/PropertySerialization.php @@ -0,0 +1,68 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Serialization; + +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo; +use Weasel\JsonMarshaller\Config\Type\Type; +use Weasel\JsonMarshaller\Config\Type\TypeParser; + +/** + * Class PropertySerialization + * @package Weasel\JsonMarshaller\Config\Serialization + * @JsonSubTypes({ + * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Serialization\DirectSerialization"), + * @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Serialization\GetterSerialization"), + * }) + * @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="how", visible=true) + */ +abstract class PropertySerialization +{ + + /** + * @var integer + * @JsonProperty(type="int") + */ + public $include; + + /** + * @var Type + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Type\Type") + */ + public $realType; + + /** + * @var \Weasel\JsonMarshaller\Config\Serialization\TypeInfo + * @JsonProperty(type="\Weasel\JsonMarshaller\Config\Serialization\TypeInfo") + */ + public $typeInfo; + + public $how; + + /** + * @return string + */ + abstract public function __toString(); + + public function __set($key, $value) + { + if ($key == "type") { + $this->setType($value); + } + } + + /** + * @param string $value + * @JsonProperty(type="string") + * @deprecated exists only for backwards compat, use realType. + */ + public function setType($value) + { + $this->realType = TypeParser::parseTypeString($value); + } +} diff --git a/lib/Weasel/JsonMarshaller/Config/Serialization/TypeInfo.php b/lib/Weasel/JsonMarshaller/Config/Serialization/TypeInfo.php new file mode 100644 index 0000000..e3b5fce --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Serialization/TypeInfo.php @@ -0,0 +1,53 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Serialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class TypeInfo +{ + const TI_USE_CLASS = 1; + const TI_USE_CUSTOM = 2; + const TI_USE_MINIMAL_CLASS = 3; + const TI_USE_NAME = 4; + const TI_USE_NONE = 5; + + const TI_AS_PROPERTY = 1; + const TI_AS_WRAPPER_OBJECT = 2; + const TI_AS_WRAPPER_ARRAY = 3; + const TI_AS_EXTERNAL_PROPERTY = 4; + + /** + * @var string[] + * @JsonProperty(type="string[string]") + */ + public $subTypes; + + /** + * @var int + * @JsonProperty(type="int") + */ + public $typeInfo = self::TI_USE_NONE; + + /** + * @var int + * @JsonProperty(type="int") + */ + public $typeInfoAs = self::TI_AS_PROPERTY; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $typeInfoProperty; + + public function __toString() + { + return '[TypeInfo subTypes={' . implode(', ', + $this->subTypes) . '} typeInfo=' . $this->typeInfo . ' typeInfoAs=' . $this->typeInfoAs . ' typeInfoProperty=' . $this->typeInfoProperty . ']'; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Config/SerializedConfigProvider.php b/lib/Weasel/JsonMarshaller/Config/SerializedConfigProvider.php new file mode 100644 index 0000000..52315ed --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/SerializedConfigProvider.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ + +namespace Weasel\JsonMarshaller\Config; + +use Weasel\JsonMarshaller\Config\Serialization\ClassSerialization; + +class SerializedConfigProvider implements JsonConfigProvider +{ + + private static $_bootstrapConfig = null; + + private $configFile = null; + + public function __construct($filename) + { + $this->configFile = $filename; + } + + private function _buildBootstrapConfig() + { + $file = $this->configFile; + self::$_bootstrapConfig[$file] = unserialize(file_get_contents($file)); + } + + /** + * Obtain the config for a named class + * @param string $class The class to get the config for + * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found + */ + public function getConfig($class) + { + $class = ltrim($class, '\\'); + $file = $this->configFile; + if (!isset(self::$_bootstrapConfig[$file])) { + $this->_buildBootstrapConfig(); + } + return isset(self::$_bootstrapConfig[$file][$class]) ? self::$_bootstrapConfig[$file][$class] : null; + } + +} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Type/ListType.php b/lib/Weasel/JsonMarshaller/Config/Type/ListType.php new file mode 100644 index 0000000..2183eb9 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Type/ListType.php @@ -0,0 +1,23 @@ +type = "list"; + $this->elementType = $elementType; + $this->indexType = new ScalarType("int"); + } + +} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Type/MapType.php b/lib/Weasel/JsonMarshaller/Config/Type/MapType.php new file mode 100644 index 0000000..3955f31 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Type/MapType.php @@ -0,0 +1,36 @@ +type = "map"; + $this->elementType = $elementType; + $this->indexType = $indexType; + } + +} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Type/ScalarType.php b/lib/Weasel/JsonMarshaller/Config/Type/ScalarType.php new file mode 100644 index 0000000..a2b6e57 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Type/ScalarType.php @@ -0,0 +1,28 @@ +type = "scalar"; + $this->typeName = $typeName; + } + +} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Config/Type/Type.php b/lib/Weasel/JsonMarshaller/Config/Type/Type.php new file mode 100644 index 0000000..c757258 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Config/Type/Type.php @@ -0,0 +1,25 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ + +namespace Weasel\JsonMarshaller\Exception; + +class BadConfigurationException extends JsonMarshallerException +{ + +} \ No newline at end of file diff --git a/lib/Weasel/JsonMarshaller/Exception/InvalidTypeException.php b/lib/Weasel/JsonMarshaller/Exception/InvalidTypeException.php new file mode 100644 index 0000000..a5fa657 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Exception/InvalidTypeException.php @@ -0,0 +1,66 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Exception; +use Exception; + +class InvalidTypeException extends JsonMarshallerException +{ + + protected $expectedType; + protected $gotType; + protected $gotValue; + + protected function _stringifyValue($value) + { + $typeStr = '(' . gettype($value) . ')'; + if (is_int($value) || is_float($value) || (is_object($value) && method_exists($value, "__toString"))) { + return $typeStr . $value; + } elseif (is_string($value)) { + return $typeStr . '"' . addcslashes($value, '"') . '"'; + } elseif (is_bool($value)) { + return $typeStr . ($value ? "true" : "false"); + } elseif (is_array($value)) { + $pos = current($value); + $retval = $typeStr . '{'; + $fst = true; + foreach ($value as $key => $element) { + if (!$fst) { + $retval .= ', '; + } + $retval .= $this->_stringifyValue($key) . ' => ' . $this->_stringifyValue($element); + $fst = false; + } + $retval .= '}'; + + if ($pos !== false) { + for (reset($value); current($value) != $pos && current($value) !== false; each($value)) { + ; + } + } + + return $retval; + } + return $typeStr; + } + + /** + * @param string $expected + * @param mixed $gotValue + * @param int $code + * @param \Exception $previous + */ + public function __construct($expected, $gotValue, $code = 0, Exception $previous = null) + { + $this->expectedType = $expected; + $this->gotType = gettype($gotValue); + $this->gotValue = $gotValue; + $message = "Expected $expected but got " . $this->_stringifyValue($gotValue); + parent::__construct($message, $code, $previous); + } + + +} diff --git a/lib/Weasel/JsonMarshaller/Exception/JsonMarshallerException.php b/lib/Weasel/JsonMarshaller/Exception/JsonMarshallerException.php new file mode 100644 index 0000000..1a54350 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Exception/JsonMarshallerException.php @@ -0,0 +1,13 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Exception; +use Exception; + +class JsonMarshallerException extends Exception +{ + +} diff --git a/lib/Weasel/JsonMarshaller/Exception/UnknownPropertyException.php b/lib/Weasel/JsonMarshaller/Exception/UnknownPropertyException.php new file mode 100644 index 0000000..27ea509 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Exception/UnknownPropertyException.php @@ -0,0 +1,8 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller; + +use Weasel\Common\Utils\ReflectionUtils; +use Weasel\JsonMarshaller\Config\Serialization\ClassSerialization; +use Weasel\JsonMarshaller\Config\Type\ListType; +use Weasel\JsonMarshaller\Config\Type\MapType; +use Weasel\JsonMarshaller\Config\Type\ScalarType; +use Weasel\JsonMarshaller\Config\Type\Type; +use Weasel\JsonMarshaller\Config\Type\TypeParser; +use Weasel\JsonMarshaller\Exception\BadConfigurationException; +use Weasel\JsonMarshaller\Exception\InvalidTypeException; +use InvalidArgumentException; +use Weasel\JsonMarshaller\Exception\UnknownPropertyException; +use Weasel\JsonMarshaller\Types; +use Weasel\JsonMarshaller\Types\JsonType; +use Weasel\JsonMarshaller\Types\OldTypeWrapper; +use Weasel\JsonMarshaller\Exception\JsonMarshallerException; +use Weasel\JsonMarshaller\Config\JsonConfigProvider; + +class JsonMapper +{ + + /** + * @var \Weasel\JsonMarshaller\Config\JsonConfigProvider The source of our configuration + */ + protected $configProvider; + + /** + * @var Types\JsonType[] Array mapping type names to their handlers + */ + protected $typeHandlers = array(); + + /** + * @var array Configuration parameters. + */ + protected $mapperConfig = array(); + + /** + * Setup a JsonMapper from a config provider + * @param Config\JsonConfigProvider $configProvider + * @param bool $strict Default for strict mode. + */ + public function __construct(JsonConfigProvider $configProvider, $strict = true) + { + $this->configProvider = $configProvider; + $this->_registerBuiltInTypes(); + if (isset($strict)) { + // Legacy way to configure strict mode. + $this->configure(Config\Deserialization\Feature::STRICT_TYPES, $strict); + } + } + + /** + * @param string $key One of the Config\*\Feature:: constants. + * @param mixed $value Appropriate value for the config option. See their documentation. + */ + public function configure($key, $value) + { + $this->mapperConfig[$key] = $value; + } + + protected function getConfigOption($key, $default, $permitsNull = false) + { + if (($permitsNull && array_key_exists($key, $this->mapperConfig)) || isset($this->mapperConfig[$key])) { + return $this->mapperConfig[$key]; + } else { + return $default; + } + } + + /** + * Setup the types we consider "built-in". + */ + protected function _registerBuiltInTypes() + { + $this->registerJsonType("boolean", new Types\BoolType(), array("bool")); + $this->registerJsonType("float", new Types\FloatType()); + $this->registerJsonType("integer", new Types\IntType(), array("int")); + $this->registerJsonType("string", new Types\StringType()); + $this->registerJsonType("datetime", new Types\DateTimeType()); + } + + /** + * Given a string of JSON, decode it into an instance of the named $class. + * @param string $string JSON string containing an object + * @param string $type Type to deserialize to. + * @param bool $strict Use strict type checking. If false will not check any types. If true can be overridden on a property by property basis. If null use the default. + * @throws \InvalidArgumentException + * @return mixed A populated instance of $class + */ + public function readString($string, $type, $strict = null) + { + if ($string === "null" || $string === "") { + return null; + } + $decoded = json_decode($string, true); + if ($decoded === null) { + throw new InvalidArgumentException("Unable to decode JSON: $string"); + } + if ($strict === null) { + $strict = $this->getConfigOption(Config\Deserialization\Feature::STRICT_TYPES, true); + } + return $this->_decodeValue($decoded, $this->_parseTypeString($type), $strict); + } + + /** + * Given a string containing a JSON array decode it into an array of the named $class. + * @param string $string JSON string containing an array + * @param string $class Full namespaced name of the class this JSON array contains + * @param bool $strict Use strict type checking. If false will not check any types. If true can be overridden on a property by property basis. If null use the default. + * @return array Array of populated $class instances + * @deprecated Use readString with an array type. + */ + public function readArray($string, $class, $strict = null) + { + return $this->readString($string, $class . '[]', $strict); + } + + protected function _guessType($data) + { + $type = gettype($data); + + switch ($type) { + case "integer": + case "string": + break; + case "double": + $type = "float"; + break; + case "object": + $type = get_class($data); + break; + case "NULL": + $type = "string"; + break; + default: + throw new InvalidArgumentException("Unable to guess type of data, please provide a type specification."); + } + + return $type; + } + + /** + * Serialize an data to a string of JSON. + * @param mixed $data Data to serialize + * @param string $type Type of the data being encoded. If not provided then this will be guessed. + * Guessing only works with primitives and simple objects. + * @return string The JSON + */ + public function writeString($data, $type = null) + { + if (!isset($type)) { + $type = $this->_guessType($data); + } + return $this->_encodeValue($data, $this->_parseTypeString($type)); + } + + /** + * Serialize an object to an array suitable for passing to json_encode. + * This used to be useful. Now all it does is call json_decode on the result of a writeString(). + * It's probably not what you want to use. + * @param mixed $data The data to serialize + * @param string $type Type of the data being encoded. If not provided then this will be guessed. + * Guessing may not work reliably with complex array structures, or if $data is a subclass + * of the class you actually want to serialize as. + * @return array An array suitable for json_encode. + * @deprecated This is no longer useful since all it does is call json_decode on the result of a writeString() operation. + */ + public function writeArray($data, $type = null) + { + return json_decode($this->writeString($data, $type), true); + } + + /** + * Encode an object to an array representation based on our configuration. + * @param object $object Object to serialize. + * @param Config\Serialization\TypeInfo $typeInfo TypeInfo to override that from the class config, used when a + * property has TypeInfo associated with it. + * @param string $type Type this is being encoded into. + * @throws Exception\InvalidTypeException + * @throws \Exception + * @return array + */ + protected function _encodeObject($object, $typeInfo = null, $type = null) + { + if (!is_object($object)) { + throw new InvalidTypeException($type, $object); + } + + $class = get_class($object); + if (!$class) { + throw new InvalidTypeException($type, $object); + } + $classconfig = $this->configProvider->getConfig($class); + if (!isset($classconfig)) { + throw new BadConfigurationException("No configuration found for class $class"); + } + $config = $classconfig->serialization; + if (!isset($config)) { + throw new BadConfigurationException("No serialization configuration found for class $class"); + } + + $properties = array(); + if (isset($config->anyGetter)) { + $method = $config->anyGetter; + $extras = $object->$method(); + if (isset($extras)) { + if (!is_array($properties)) { + throw new InvalidTypeException("array", $properties); + } + foreach ($extras as $key => $value) { + $properties[$key] = json_encode($value); + } + } + } + + foreach ($config->properties as $key => $propConfig) { + + $value = null; + if ($propConfig->how == "direct") { + /** + * @var Config\Serialization\DirectSerialization $propConfig + */ + + $prop = $propConfig->property; + $value = $object->$prop; + + } elseif ($propConfig->how == "getter") { + /** + * @var Config\Serialization\GetterSerialization $propConfig + */ + + $meth = $propConfig->method; + $value = $object->$meth(); + } else { + throw new BadConfigurationException("No idea how to serialize something with the given config"); + } + + switch ($propConfig->include) { + case ClassSerialization::INCLUDE_ALWAYS: + break; + case Config\Serialization\ClassSerialization::INCLUDE_NON_EMPTY: + if (empty($value)) { + continue 2; + } + break; + case Config\Serialization\ClassSerialization::INCLUDE_NON_DEFAULT: + throw new \Exception("Not currently supported"); + case Config\Serialization\ClassSerialization::INCLUDE_NON_NULL: + if (is_null($value)) { + continue 2; + } + } + + $properties[$key] = $this->_encodeValue($value, $propConfig->realType, $propConfig->typeInfo); + if ($propConfig->typeInfo && + $propConfig->typeInfo->typeInfoAs === Config\Serialization\TypeInfo::TI_AS_EXTERNAL_PROPERTY + ) { + // We need to store the type of the encoded object on ourselves + $propClass = get_class($object); + if ($propClass && isset($typeInfo->subTypes[$propClass])) { + $classId = $typeInfo->subTypes[$propClass]; + + $properties[$propConfig->typeInfo->typeInfoProperty] = $classId; + } + + } + } + + if (!$typeInfo) { + // Typeinfo wasn't passed in on the property, we need to see if we have any to load + if (isset($type)) { + // We load typeinfo stuff from our base type, not the actual class we're serializing. + $parentConfig = $this->configProvider->getConfig($type); + if (isset($parentConfig)) { + $typeInfo = $parentConfig->serialization->typeInfo; + } + } + } + + if ($typeInfo) { + // We need to encode information about what type we are somewhere. + // First off work out what name we go by (what value should be stored wherever it is) + switch ($typeInfo->typeInfo) { + case Config\Serialization\TypeInfo::TI_USE_CLASS: + case Config\Serialization\TypeInfo::TI_USE_MINIMAL_CLASS: + case Config\Serialization\TypeInfo::TI_USE_NAME: + // In all these cases the typeInfo subTypes config should contain the mapping from our class to + // whatever value we should be called by. + if (!isset($typeInfo->subTypes[$class])) { + break; + } + $classId = $typeInfo->subTypes[$class]; + break; + case Config\Serialization\TypeInfo::TI_USE_CUSTOM: // TODO + default: + throw new BadConfigurationException("Unsupported type info at class level"); + } + // Now where should we put this information? + switch ($typeInfo->typeInfoAs) { + case Config\Serialization\TypeInfo::TI_AS_EXTERNAL_PROPERTY: + // The property is on the object that contains us, so this is SEP. + break; + case Config\Serialization\TypeInfo::TI_AS_PROPERTY: + // We're going to store the classId as a string on this object + if (!isset($classId)) { + break; + } + $property = $typeInfo->typeInfoProperty; + $properties[$property] = $this->_encodeToString($classId); + break; + case Config\Serialization\TypeInfo::TI_AS_WRAPPER_ARRAY: + // We're actually going to encase this encoded object in an array containing the classId. + if (!isset($classId)) { + break; + } + return '[' . $this->_encodeToString($classId) . ', ' . $this->_objectToJson($properties) . ']'; + break; + case Config\Serialization\TypeInfo::TI_AS_WRAPPER_OBJECT: + // Very similar yo the wrapper array case, but this time it's a map from the classId to the object. + if (!isset($classId)) { + break; + } + return '{' . $this->_encodeToString($classId) . ': ' . $this->_objectToJson($properties) . '}'; + break; + default: + throw new BadConfigurationException("Unsupported type info storage at class level"); + } + } + + return $this->_objectToJson($properties); + + } + + protected function _objectToJson($properties) + { + $elements = array(); + foreach ($properties as $key => $property) { + $elements[] = $this->_encodeToString($key) . ': ' . $property; + } + return '{' . implode(', ', $elements) . '}'; + } + + + protected function _instantiateClassFromPropertyCreator($array, + $class, + Config\Deserialization\PropertyCreator $creator, + $strict) + { + $args = array(); + foreach ($creator->params as $param) { + $val = null; + if (isset($array[$param->name])) { + $val = $this->_decodeValue($array[$param->name], $param->realType, $param->strict && $strict); + } + $args[] = $val; + } + + if ($creator->method === '__construct') { + return ReflectionUtils::instantiateClassByConstructor($class, $args); + } else { + return ReflectionUtils::invokeStaticMethod($class, $creator->method, $args); + } + } + + + protected function _decodeClass($array, $class, $strict) + { + $classconfig = $this->configProvider->getConfig($class); + if (!isset($classconfig)) { + throw new BadConfigurationException("No configuration found for class $class"); + } + + $deconfig = $classconfig->deserialization; + + $canIgnoreProperties = array(); + if (isset($deconfig->typeInfo)) { + $typeInfo = $deconfig->typeInfo; + // First we need to work out what type to deserialize as + if (isset($typeInfo->defaultImpl)) { + $class = $typeInfo->defaultImpl; + } + $typeId = null; + switch ($typeInfo->typeInfoAs) { + case Config\Deserialization\TypeInfo::TI_AS_EXTERNAL_PROPERTY: + case Config\Deserialization\TypeInfo::TI_AS_PROPERTY: + $property = $typeInfo->typeInfoProperty; + $canIgnoreProperties[$property] = true; + if (!isset($array[$property])) { + break; + } + $typeId = $array[$property]; + if ($typeInfo->typeInfoVisible == false) { + unset($array[$property]); + } + break; + case Config\Deserialization\TypeInfo::TI_AS_WRAPPER_ARRAY: + if (count($array) !== 2) { + throw new InvalidTypeException("array(2)", $array); + } + $typeId = $array[0]; + $array = $array[1]; + break; + case Config\Deserialization\TypeInfo::TI_AS_WRAPPER_OBJECT: + if (count($array) !== 1) { + throw new InvalidTypeException("array(1)", $array); + } + list($typeId) = array_keys($array); + $array = array_shift($array); + break; + default: + throw new BadConfigurationException("Unsupported type info storage at class level"); + } + + switch ($typeInfo->typeInfo) { + case Config\Deserialization\TypeInfo::TI_USE_CLASS: + case Config\Deserialization\TypeInfo::TI_USE_MINIMAL_CLASS: + case Config\Deserialization\TypeInfo::TI_USE_NAME: + if (!isset($typeInfo->subTypes[$typeId])) { + break; + } + $class = $typeInfo->subTypes[$typeId]; + break; + case Config\Deserialization\TypeInfo::TI_USE_CUSTOM: // TODO + default: + throw new BadConfigurationException("Unsupported type info at class level"); + } + + } + $classconfig = $this->configProvider->getConfig($class); + + if (!isset($classconfig)) { + throw new BadConfigurationException("No config found to decode $class"); + } + $deconfig = $classconfig->deserialization; + + if ($deconfig->creator) { + if ($deconfig->creator instanceof Config\Deserialization\DelegateCreator) { + return new $class($array); + } else { + $creator = $deconfig->creator; + /** + * @var Config\Deserialization\PropertyCreator $creator + */ + $object = $this->_instantiateClassFromPropertyCreator($array, $class, $creator, $strict); + foreach ($creator->params as $param) { + $canIgnoreProperties[$param->name] = true; + } + } + } else { + if (class_exists($class)) { + $object = new $class(); + } else { + throw new BadConfigurationException("Configured class $class is not an instantiable class."); + } + } + + if (isset($deconfig->ignoreProperties)) { + foreach ($deconfig->ignoreProperties as $ignore) { + $canIgnoreProperties[$ignore] = true; + } + } + + foreach ($array as $key => $value) { + if (isset($deconfig->properties[$key])) { + $propConfig = $deconfig->properties[$key]; + + try { + $decodedValue = $this->_decodeValue($value, $propConfig->realType, $propConfig->strict && $strict); + } catch (\Exception $e) { + throw new \Exception("Failed to decode property $key on $class", 0, $e); + } + + if ($propConfig->how == "direct") { + /** + * @var Config\Deserialization\DirectDeserialization $propConfig + */ + + $prop = $propConfig->property; + + $object->$prop = $decodedValue; + + } elseif ($propConfig->how == "setter") { + /** + * @var Config\Deserialization\SetterDeserialization $propConfig + */ + + $meth = $propConfig->method; + + $object->$meth($decodedValue); + + } + } elseif (isset($deconfig->anySetter)) { + $method = $deconfig->anySetter; + $object->$method($key, $value); + } elseif (!$deconfig->ignoreUnknown) { + if (!isset($canIgnoreProperties[$key])) { + if ($this->getConfigOption(Config\Deserialization\Feature::WARN_ON_UNKNOWN_PROPERTIES, true)) { + trigger_error("Unknown property $key on $class", E_USER_WARNING); + } + if ($this->getConfigOption(Config\Deserialization\Feature::FAIL_ON_UNKNOWN_PROPERTIES, false)) { + throw new UnknownPropertyException("Unknown property $key on $class"); + } + } + } + } + + return $object; + + + } + + /** + * @param string $typeName + * @return JsonType + */ + protected function _getTypeHandler($typeName) + { + if (isset($this->typeHandlers[$typeName])) { + // Assumption: if there's a type handler for this type string, then it's the right thing to use. + return $this->typeHandlers[$typeName]; + } + return null; + } + + protected function _parseTypeString($type) + { + return TypeParser::parseTypeString($type); + } + + /** + * @param mixed $value + * @param Type $type + * @return mixed + * @throws Exception\InvalidTypeException + * @throws Exception\JsonMarshallerException + */ + protected function _decodeKey($value, $type) + { + if (!isset($value)) { + throw new JsonMarshallerException("Key values cannot be null"); + } + if ($type->type != "scalar") { + throw new JsonMarshallerException("Keys must be of type int or string, not " . $type); + } + // Keys are always strings, however we will allow other types, and disable strict type checking. + return $this->_decodeValue($value, $type, false); + } + + protected function _decodeValue($value, $type, $strict) + { + if (!isset($value)) { + return null; + } + if ($type->type == "scalar") { + $typeName = $type->typeName; + if ($typeName == "integer" || $typeName == "string" || $typeName == "float" || $typeName == "boolean" || $typeName == "datetime") { + return $this->typeHandlers[$typeName]->decodeValue($value, $this, $strict); + } + $typeHandler = $this->_getTypeHandler($typeName); + if (isset($typeHandler)) { + return $typeHandler->decodeValue($value, $this, $strict); + } + if (!is_array($value)) { + throw new InvalidTypeException($typeName, $value); + } + return $this->_decodeClass($value, $typeName, $strict); + } + if ($type->type == "map" || $type->type == "list") { + $indexType = $type->indexType; + $elementType = $type->elementType; + $result = array(); + if (!is_array($value)) { + $value = array($value); + } + foreach ($value as $key => $element) { + $result[$this->_decodeKey($key, $indexType)] = $this->_decodeValue($element, $elementType, $strict); + } + return $result; + + } + return null; + } + + protected function _encodeKey($value, $type) + { + if (!isset($value)) { + throw new JsonMarshallerException("Key values cannot be null"); + } + if (!isset($type->typeName)) { + throw new JsonMarshallerException("Keys must be of type int or string, not " . $type); + } + return $this->_encodeToString($value); + } + + protected function _encodeToString($value) + { + return $this->typeHandlers["string"]->encodeValue($value, $this); + } + + /** + * @param mixed $value + * @param Type $type + * @param Config\Serialization\TypeInfo $typeInfo + * @throws Exception\InvalidTypeException + * @return mixed + */ + protected function _encodeValue($value, $type, $typeInfo = null) + { + if (!isset($value)) { + return "null"; + } + if ($type->type == "scalar") { + /** + * @var ScalarType $type + */ + $typeName = $type->typeName; + if ($typeName == "integer" || $typeName == "string" || $typeName == "float" || $typeName == "boolean" || $typeName == "datetime") { + return $this->typeHandlers[$typeName]->encodeValue($value, $this); + } + $typeHandler = $this->_getTypeHandler($typeName); + if (isset($typeHandler)) { + return $typeHandler->encodeValue($value, $this); + } + return $this->_encodeObject($value, $typeInfo, $type->typeName); + } + if ($type->type == "list") { + /** + * @var ListType $type + */ + $elementType = $type->elementType; + if (!is_array($value)) { + $value = array($value); + } + $elements = array(); + foreach ($value as $element) { + $elements[] = $this->_encodeValue($element, $elementType); + } + return '[' . implode(', ', $elements) . ']'; + } + if ($type->type == "map") { + /** + * @var MapType $type + */ + $indexType = $type->indexType; + $elementType = $type->elementType; + if (!is_array($value)) { + $value = array($value); + } + $elements = array(); + foreach ($value as $key => $element) { + $elements[] = $this->_encodeKey($key, $indexType) . ': ' . $this->_encodeValue($element, + $elementType); + } + return '{' . implode(', ', $elements) . '}'; + } + return "null"; + } + + + /** + * Register a custom type. + * @param string $name + * @param Types\JsonType $handler + * @param string[] $aliases + */ + public function registerJsonType($name, $handler, $aliases = array()) + { + $this->typeHandlers[$name] = $handler; + foreach ($aliases as $alias) { + $this->typeHandlers[$alias] = $handler; + } + } + + /** + * Register an old style custom type. + * This is a compatibility handler and will be removed. Please use registerJsonType! + * @Deprecated + * @param string $name + * @param Types\Type $handler + * @param string[] $aliases + */ + public function registerType($name, $handler, $aliases = array()) + { + trigger_error("Types are deprecated, use JsonTypes through registerJsonType.", E_USER_DEPRECATED); + $this->registerJsonType($name, new OldTypeWrapper($handler), $aliases); + } +} diff --git a/lib/Weasel/JsonMarshaller/Types/BoolType.php b/lib/Weasel/JsonMarshaller/Types/BoolType.php new file mode 100644 index 0000000..d3078b5 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Types/BoolType.php @@ -0,0 +1,36 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; +use Weasel\JsonMarshaller\JsonMapper; +use Weasel\JsonMarshaller\Exception\InvalidTypeException; + +class BoolType implements JsonType +{ + + public function decodeValue($value, JsonMapper $mapper, $strict) + { + if (is_bool($value)) { + return $value; + } + if ($value === "true" || $value === 1) { + return true; + } + if ($value === "false" || $value === 0) { + return false; + } + throw new InvalidTypeException("boolean", $value); + } + + public function encodeValue($value, JsonMapper $mapper) + { + if (!is_bool($value)) { + throw new InvalidTypeException("boolean", $value); + } + return ((bool)$value) ? "true" : "false"; + } + +} diff --git a/lib/Weasel/JsonMarshaller/Types/DateTimeType.php b/lib/Weasel/JsonMarshaller/Types/DateTimeType.php new file mode 100644 index 0000000..4b2deff --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Types/DateTimeType.php @@ -0,0 +1,53 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; +use Weasel\JsonMarshaller\JsonMapper; +use Exception; +use DateTime; +use Weasel\JsonMarshaller\Exception\InvalidTypeException; + +class DateTimeType implements JsonType +{ + + protected $dateTimeFormat; + + public function __construct($dateTimeFormat = DateTime::ISO8601) + { + $this->dateTimeFormat = $dateTimeFormat; + } + + public function decodeValue($value, JsonMapper $mapper, $strict) + { + if (!is_string($value)) { + throw new InvalidTypeException('date string', $value); + } + try { + $retval = DateTime::createFromFormat($this->dateTimeFormat, $value); + if ($retval !== false) { + return $retval; + } + } catch (Exception $e) { + throw new InvalidTypeException('date string', $value, 0, $e); + } + throw new InvalidTypeException('date string', $value); + } + + /** + * @param \DateTime $value + * @param \Weasel\JsonMarshaller\JsonMapper $mapper + * @throws \Weasel\JsonMarshaller\Exception\InvalidTypeException + * @return string + */ + public function encodeValue($value, JsonMapper $mapper) + { + if (!$value instanceof DateTime) { + throw new InvalidTypeException('\DateTime', $value); + } + return json_encode($value->format($this->dateTimeFormat)); + } + +} diff --git a/lib/Weasel/JsonMarshaller/Types/FloatType.php b/lib/Weasel/JsonMarshaller/Types/FloatType.php new file mode 100644 index 0000000..b4f1e28 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Types/FloatType.php @@ -0,0 +1,37 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; +use Weasel\JsonMarshaller\JsonMapper; +use Weasel\JsonMarshaller\Exception\InvalidTypeException; + +class FloatType implements JsonType +{ + + protected function checkAndCast($value) + { + if (!is_numeric($value)) { + throw new InvalidTypeException("float", $value); + } + return (float)($value + 0); + } + + public function decodeValue($value, JsonMapper $mapper, $strict) + { + if ($strict) { + if (!is_int($value) && !is_double($value)) { + throw new InvalidTypeException("float", $value); + } + } + return $this->checkAndCast($value); + } + + public function encodeValue($value, JsonMapper $mapper) + { + return json_encode($this->checkAndCast($value)); + } + +} diff --git a/lib/Weasel/JsonMarshaller/Types/IntType.php b/lib/Weasel/JsonMarshaller/Types/IntType.php new file mode 100644 index 0000000..b692d05 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Types/IntType.php @@ -0,0 +1,41 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; +use Weasel\JsonMarshaller\JsonMapper; +use Weasel\JsonMarshaller\Exception\InvalidTypeException; + +class IntType implements JsonType +{ + + protected function checkAndCastValue($value) + { + if (!is_numeric($value)) { + throw new InvalidTypeException("integer", $value); + } + $intval = (int)($value + 0); + if ($intval != $value) { + throw new InvalidTypeException("integer", $value); + } + return $intval; + } + + public function decodeValue($value, JsonMapper $mapper, $strict) + { + if ($strict) { + if (!is_int($value)) { + throw new InvalidTypeException("integer", $value); + } + } + return $this->checkAndCastValue($value); + } + + public function encodeValue($value, JsonMapper $mapper) + { + return json_encode($this->checkAndCastValue($value)); + } + +} diff --git a/lib/Weasel/JsonMarshaller/Types/JsonType.php b/lib/Weasel/JsonMarshaller/Types/JsonType.php new file mode 100644 index 0000000..e2ead44 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Types/JsonType.php @@ -0,0 +1,30 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; +use Weasel\JsonMarshaller\JsonMapper; +use Weasel\JsonMarshaller\Exception\InvalidTypeException; + +interface JsonType +{ + /** + * Deserialize something to its PHP type. + * @param mixed $value + * @param \Weasel\JsonMarshaller\JsonMapper $mapper + * @param bool $strict Apply strict checking of input values. + * @return mixed + */ + public function decodeValue($value, JsonMapper $mapper, $strict); + + /** + * Serialize a PHP value to Json. + * @param $value + * @param \Weasel\JsonMarshaller\JsonMapper $mapper + * @return string + */ + public function encodeValue($value, JsonMapper $mapper); + +} diff --git a/lib/Weasel/JsonMarshaller/Types/OldTypeWrapper.php b/lib/Weasel/JsonMarshaller/Types/OldTypeWrapper.php new file mode 100644 index 0000000..2c98d78 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Types/OldTypeWrapper.php @@ -0,0 +1,29 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; +use Weasel\JsonMarshaller\JsonMapper; + +class OldTypeWrapper implements JsonType +{ + + protected $_oldType; + + public function __construct(Type $oldType) + { + $this->_oldType = $oldType; + } + + public function decodeValue($value, JsonMapper $mapper, $strict) + { + return $this->_oldType->decodeValue($value, $mapper); + } + + public function encodeValue($value, JsonMapper $mapper) + { + return json_encode($this->_oldType->encodeValue($value, $mapper)); + } +} diff --git a/lib/Weasel/JsonMarshaller/Types/StringType.php b/lib/Weasel/JsonMarshaller/Types/StringType.php new file mode 100644 index 0000000..59605f3 --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Types/StringType.php @@ -0,0 +1,32 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; +use Weasel\JsonMarshaller\JsonMapper; +use Weasel\JsonMarshaller\Exception\InvalidTypeException; + +class StringType implements JsonType +{ + + protected function checkAndCastValue($value) + { + return (string)("" . $value); + } + + public function decodeValue($value, JsonMapper $mapper, $strict) + { + if ($strict && !is_string($value)) { + throw new InvalidTypeException("string", $value); + } + return $this->checkAndCastValue($value); + } + + public function encodeValue($value, JsonMapper $mapper) + { + return json_encode($this->checkAndCastValue($value)); + } + +} diff --git a/lib/Weasel/JsonMarshaller/Types/Type.php b/lib/Weasel/JsonMarshaller/Types/Type.php new file mode 100644 index 0000000..741c5da --- /dev/null +++ b/lib/Weasel/JsonMarshaller/Types/Type.php @@ -0,0 +1,34 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; +use Weasel\JsonMarshaller\JsonMapper; +use Weasel\JsonMarshaller\Exception\InvalidTypeException; + + +/** + * @Deprecated + * Custom types should extend JsonType, not this. + */ +interface Type +{ + /** + * Deserialize something to its PHP type. + * @param mixed $value + * @param \Weasel\JsonMarshaller\JsonMapper $mapper + * @return mixed + */ + public function decodeValue($value, JsonMapper $mapper); + + /** + * Serialize a PHP value. + * @param $value + * @param \Weasel\JsonMarshaller\JsonMapper $mapper + * @return string + */ + public function encodeValue($value, JsonMapper $mapper); + +} diff --git a/lib/Weasel/WeaselDefaultAnnotationDrivenFactory.php b/lib/Weasel/WeaselDefaultAnnotationDrivenFactory.php new file mode 100644 index 0000000..46e4f97 --- /dev/null +++ b/lib/Weasel/WeaselDefaultAnnotationDrivenFactory.php @@ -0,0 +1,181 @@ +setCache(new ArrayCache()); + $this->_strict = $strict; + } + + /** + * @return AnnotationConfigurator + */ + public function getAnnotationConfigProviderInstance() + { + if (!isset($this->_configurator)) { + $configurator = new AnnotationConfigurator(); + $this->_autowire($configurator); + $this->_configurator = $configurator; + } + return $this->_configurator; + } + + /** + * @return Annotation\AnnotationReaderFactory + */ + public function getAnnotationReaderFactoryInstance() + { + if (!isset($this->_annotationReaderFactory)) { + $factory = new AnnotationReaderFactory($this->getAnnotationConfigProviderInstance()); + $this->_autowire($factory); + $this->_annotationReaderFactory = $factory; + } + return $this->_annotationReaderFactory; + } + + /** + * @return XmlAnnotationDriver + */ + public function getXmlDriverInstance() + { + if (!isset($this->_xmlDriver)) { + $driver = new XmlAnnotationDriver($this->getAnnotationReaderFactoryInstance()); + $this->_autowire($driver); + $this->_xmlDriver = $driver; + } + return $this->_xmlDriver; + } + + /** + * @return XmlMarshaller\XmlMapper + */ + public function getXmlMapperInstance() + { + if (!isset($this->_xmlMapper)) { + $this->_xmlMapper = new XmlMapper($this->getXmlDriverInstance()); + } + return $this->_xmlMapper; + } + + /** + * @return JsonAnnotationDriver + */ + public function getJsonDriverInstance() + { + if (!isset($this->_jsonDriver)) { + $driver = new JsonAnnotationDriver($this->getAnnotationReaderFactoryInstance()); + $this->_autowire($driver); + $this->_jsonDriver = $driver; + } + return $this->_jsonDriver; + } + + /** + * @return JsonMarshaller\JsonMapper + */ + public function getJsonMapperInstance() + { + if (!isset($this->_jsonMapper)) { + $this->_jsonMapper = new JsonMapper($this->getJsonDriverInstance(), $this->_strict); + } + return $this->_jsonMapper; + } + + protected function _autowire($object) + { + $this->_configureLogger($object); + $this->_configureCache($object); + } + + protected function _configureLogger($object) + { + if ($object instanceof LoggerAwareInterface) { + if (isset($this->_logger)) { + $object->setLogger($this->_logger); + } + } + } + + protected function _configureCache($object) + { + if ($object instanceof CacheAwareInterface) { + if (isset($this->_cache)) { + $object->setCache($this->_cache); + } + } + } + + /** + * Sets a logger instance on the object + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->_logger = $logger; + } + + public function setCache(Cache $cache) + { + $this->_cache = $cache; + } +} diff --git a/lib/Weasel/WeaselDoctrineAnnotationDrivenFactory.php b/lib/Weasel/WeaselDoctrineAnnotationDrivenFactory.php new file mode 100644 index 0000000..c5c350d --- /dev/null +++ b/lib/Weasel/WeaselDoctrineAnnotationDrivenFactory.php @@ -0,0 +1,197 @@ +setCache(new ArrayCache()); + $this->_strict = $strict; + } + + /** + * @return AnnotationReader + */ + public function getDoctrineAnnotationReaderInstance() + { + if (!isset($this->annotationReader)) { + $reader = new AnnotationReader(); + if (isset($this->_cache)) { + $reader = new CachedReader($reader, new WeaselCacheAdapter($this->_cache)); + } + $this->_autowire($reader); + $this->annotationReader = $reader; + } + return $this->annotationReader; + } + + /** + * @return Annotation\AnnotationReaderFactory + */ + public function getAnnotationReaderFactoryInstance() + { + if (!isset($this->_annotationReaderFactory)) { + $factory = new DoctrineAnnotationReaderFactory($this->getDoctrineAnnotationReaderInstance()); + $this->_autowire($factory); + $this->_annotationReaderFactory = $factory; + } + return $this->_annotationReaderFactory; + } + + /** + * @return JsonAnnotationDriver + */ + public function getJsonDriverInstance() + { + if (!isset($this->_jsonDriver)) { + $driver = new JsonAnnotationDriver($this->getAnnotationReaderFactoryInstance()); + $driver->setAnnotationNamespace('\Weasel\JsonMarshaller\Config\DoctrineAnnotations'); + $this->_autowire($driver); + $this->_jsonDriver = $driver; + } + return $this->_jsonDriver; + } + + /** + * @return JsonMarshaller\JsonMapper + */ + public function getJsonMapperInstance() + { + if (!isset($this->_jsonMapper)) { + $this->_jsonMapper = new JsonMapper($this->getJsonDriverInstance(), $this->_strict); + } + return $this->_jsonMapper; + } + + protected function _autowire($object) + { + $this->_configureLogger($object); + $this->_configureCache($object); + } + + protected function _configureLogger($object) + { + if ($object instanceof LoggerAwareInterface) { + if (isset($this->_logger)) { + $object->setLogger($this->_logger); + } + } + } + + protected function _configureCache($object) + { + if ($object instanceof CacheAwareInterface) { + if (isset($this->_cache)) { + $object->setCache($this->_cache); + } + } + } + + /** + * Sets a logger instance on the object. + * This logger will be passed into any LoggerAware instances created by this class. + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->_logger = $logger; + } + + /** + * Sets a cache instance on the object. + * This cache will be passed into any CacheAware instances created by this class. + * @param Cache $cache + */ + public function setCache(Cache $cache) + { + $this->_cache = $cache; + } + + /** + * @return XmlAnnotationDriver + */ + public function getXmlDriverInstance() + { + if (!isset($this->_xmlDriver)) { + $driver = new XmlAnnotationDriver($this->getAnnotationReaderFactoryInstance()); + $driver->setAnnotationNamespace('\Weasel\XmlMarshaller\Config\DoctrineAnnotations'); + $this->_autowire($driver); + $this->_xmlDriver = $driver; + } + return $this->_xmlDriver; + } + + /** + * @return XmlMapper + */ + public function getXmlMapperInstance() + { + if (!isset($this->_xmlMapper)) { + $this->_xmlMapper = new XmlMapper($this->getXmlDriverInstance()); + } + return $this->_xmlMapper; + } +} diff --git a/lib/Weasel/WeaselFactory.php b/lib/Weasel/WeaselFactory.php new file mode 100644 index 0000000..bca8a7a --- /dev/null +++ b/lib/Weasel/WeaselFactory.php @@ -0,0 +1,30 @@ +_jsonConfigFile = $jsonConfigFile; + $this->_xmlConfigFile = $xmlConfigFile; + $this->setCache(new ArrayCache()); + } + + private function _getJsonConfigMapper() + { + return new JsonMapper(new SerializedConfigProvider(__DIR__ . '/JsonMarshaller/Config/bootstrap.cnf')); + } + + /** + * @return JsonConfigProvider + */ + private function _getJsonConfigDriver() + { + $mapper = $this->_getJsonConfigMapper(); + $configString = file_get_contents($this->_jsonConfigFile); + $config = $mapper->readString($configString, '\Weasel\JsonMarshaller\Config\ClassMarshaller[string]'); + return new JsonPropertyConfigProvider($config); + } + + /** + * @return ConfigProvider + */ + private function _getXmlConfigDriver() + { + $mapper = $this->_getJsonConfigMapper(); + $configString = file_get_contents($this->_xmlConfigFile); + $config = $mapper->readString($configString, '\Weasel\XmlMarshaller\Config\ClassMarshaller[string]'); + return new XmlPropertyConfigProvider($config); + } + + /** + * @return JsonMarshaller\JsonMapper + */ + public function getJsonMapperInstance() + { + if (!isset($this->_jsonMapper)) { + $this->_jsonMapper = new JsonMapper($this->_getJsonConfigDriver()); + } + return $this->_jsonMapper; + } + + protected function _autowire($object) + { + $this->_configureLogger($object); + $this->_configureCache($object); + } + + protected function _configureLogger($object) + { + if ($object instanceof LoggerAwareInterface) { + if (isset($this->_logger)) { + $object->setLogger($this->_logger); + } + } + } + + protected function _configureCache($object) + { + if ($object instanceof CacheAwareInterface) { + if (isset($this->_cache)) { + $object->setCache($this->_cache); + } + } + } + + /** + * Sets a logger instance on the object. + * This logger will be passed into any LoggerAware instances created by this class. + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->_logger = $logger; + } + + /** + * Sets a cache instance on the object. + * This cache will be passed into any CacheAware instances created by this class. + * @param Cache $cache + */ + public function setCache(Cache $cache) + { + $this->_cache = $cache; + } + + /** + * Get a fully configured XmlMapper instance. + * @return XmlMapper + */ + public function getXmlMapperInstance() + { + if (!isset($this->_xmlMapper)) { + $this->_xmlMapper = new XmlMapper($this->_getXmlConfigDriver()); + } + return $this->_xmlMapper; + } +} diff --git a/lib/Weasel/XmlMarshaller/Config/AnnotationDriver.php b/lib/Weasel/XmlMarshaller/Config/AnnotationDriver.php new file mode 100644 index 0000000..4ee6632 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/AnnotationDriver.php @@ -0,0 +1,93 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config; + +use Weasel\XmlMarshaller\Config\Annotations as Annotations; +use Weasel\Annotation\AnnotationConfigurator; +use Weasel\Common\Cache\CacheAwareInterface; +use Weasel\Common\Cache\Cache; +use Weasel\Common\Annotation\IAnnotationReaderFactory; + +class AnnotationDriver implements ConfigProvider, CacheAwareInterface +{ + + protected $classPaths = array(); + + protected $annotationNamespace = '\Weasel\XmlMarshaller\Config\Annotations'; + + /** + * @var \Weasel\Common\Annotation\IAnnotationReaderFactory + */ + public $annotationReaderFactory; + + /** + * @var \Weasel\Common\Cache\Cache + */ + protected $cache; + + public function __construct(IAnnotationReaderFactory $annotationReaderFactory) + { + $this->annotationReaderFactory = $annotationReaderFactory; + } + + /** + * @param string $class + * @return \Weasel\XmlMarshaller\Config\ClassMarshaller + */ + public function getConfig($class) + { + $key = strtolower($class); + if (isset($this->cache)) { + $found = false; + $cached = $this->cache->get($key, "XmlConfig", $found); + if ($found) { + return $cached; + } + } + $config = $this->_getConfig($class); + + if (isset($this->cache)) { + $this->cache->set($key, $config, "XmlConfig"); + } + return $config; + } + + /** + * @param string $class + * @return \Weasel\XmlMarshaller\Config\ClassMarshaller + */ + protected function _getConfig($class) + { + $rClass = new \ReflectionClass($class); + + $classDriver = new ClassAnnotationDriver($rClass, $this->annotationReaderFactory, $this->annotationNamespace); + + return $classDriver->getConfig(); + + } + + public function setCache(Cache $cache) + { + $this->cache = $cache; + } + + /** + * @param \Weasel\Common\Annotation\IAnnotationReaderFactory $annotationReaderFactory + */ + public function setAnnotationReaderFactory(IAnnotationReaderFactory $annotationReaderFactory) + { + $this->annotationReaderFactory = $annotationReaderFactory; + } + + /** + * @param string $annotationNamespace + */ + public function setAnnotationNamespace($annotationNamespace) + { + $this->annotationNamespace = $annotationNamespace; + } +} diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlAttribute.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlAttribute.php new file mode 100644 index 0000000..6b638a3 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlAttribute.php @@ -0,0 +1,65 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlAttribute; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation(on={"property", "method"}) + */ +class XmlAttribute extends NoUndeclaredProperties implements IXmlAttribute +{ + + protected $name; + protected $type; + protected $namespace; + protected $required; + + /** + * @param string $name + * @param string $type + * @param string $namespace + * @param bool $required + * @AnnotationCreator({@Parameter(name="name", type="string", required=false), + @Parameter(name="type", type="string", required=false), + @Parameter(name="namespace", type="string", required=false), + @Parameter(name="required", type="bool", required=false)}) + */ + public function __construct($name = null, $type = null, $namespace = null, $required = null) + { + $this->name = isset($name) ? $name : null; + $this->type = isset($type) ? $type : "string"; + $this->namespace = isset($namespace) ? $namespace : null; + $this->required = isset($required) && $required; + } + + public function getName() + { + return $this->name; + } + + public function getType() + { + return $this->type; + } + + public function getNamespace() + { + return $this->namespace; + } + + public function getRequired() + { + return $this->required; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminator.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminator.php new file mode 100644 index 0000000..c1251fd --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminator.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlDiscriminator; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation(on={"class"}) + */ +class XmlDiscriminator extends NoUndeclaredProperties implements IXmlDiscriminator +{ + + /** + * @var string + */ + protected $value; + + /** + * @param string $value; + * @AnnotationCreator({@Parameter(name="value", type="string", required=true)}) + */ + public function __construct($value = null) + { + $this->value = $value; + } + + /** + * @return string + */ + public function getValue() + { + return $this->value; + } + + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminatorValue.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminatorValue.php new file mode 100644 index 0000000..26e9a8b --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlDiscriminatorValue.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlDiscriminatorValue; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation(on={"class"}) + */ +class XmlDiscriminatorValue extends NoUndeclaredProperties implements IXmlDiscriminatorValue +{ + + /** + * @var string + */ + protected $value; + + /** + * @param string $value; + * @AnnotationCreator({@Parameter(name="value", type="string", required=true)}) + */ + public function __construct($value = null) + { + $this->value = $value; + } + + /** + * @return string + */ + public function getValue() + { + return $this->value; + } + + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElement.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElement.php new file mode 100644 index 0000000..b9c0597 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElement.php @@ -0,0 +1,74 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElement; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation(on={"property", "method"}) + */ +class XmlElement extends NoUndeclaredProperties implements IXmlElement +{ + + protected $name; + protected $type; + protected $namespace; + protected $required; + protected $nillable; + + /** + * @param string $name + * @param string $type + * @param $nillable + * @param string $namespace + * @param bool $required + * @AnnotationCreator({@Parameter(name="name", type="string", required=false), + @Parameter(name="type", type="string", required=false), + @Parameter(name="nillable", type="bool", required=false), + @Parameter(name="namespace", type="string", required=false), + @Parameter(name="required", type="bool", required=false)}) + */ + public function __construct($name = null, $type = null, $nillable = null, $namespace = null, $required = null) + { + $this->name = isset($name) ? $name : null; + $this->type = isset($type) ? $type : "string"; + $this->namespace = isset($namespace) ? $namespace : null; + $this->required = isset($required) && $required; + $this->nillable = isset($nillable) && $nillable; + } + + public function getName() + { + return $this->name; + } + + public function getType() + { + return $this->type; + } + + public function getNamespace() + { + return $this->namespace; + } + + public function getRequired() + { + return $this->required; + } + + public function getNillable() + { + return $this->nillable; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRef.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRef.php new file mode 100644 index 0000000..169cbc0 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRef.php @@ -0,0 +1,56 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRef; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation(on={"property", "method", "\Weasel\XmlMarshaller\Config\Annotations\XmlElementRefs"}) + */ +class XmlElementRef extends NoUndeclaredProperties implements IXmlElementRef +{ + + protected $name; + protected $type; + protected $namespace; + + /** + * @param string $name + * @param string $type + * @param string $namespace + * @AnnotationCreator({@Parameter(name="name", type="string", required=false), + @Parameter(name="type", type="string", required=true), + @Parameter(name="namespace", type="string", required=false)}) + */ + public function __construct($name = null, $type = null, $namespace = null) + { + $this->name = isset($name) ? $name : null; + $this->type = isset($type) ? $type : null; + $this->namespace = isset($namespace) ? $namespace : null; + } + + public function getName() + { + return $this->name; + } + + public function getType() + { + return $this->type; + } + + public function getNamespace() + { + return $this->namespace; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRefs.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRefs.php new file mode 100644 index 0000000..d0142ba --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementRefs.php @@ -0,0 +1,46 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRefs; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation(on={"property", "method"}) + */ +class XmlElementRefs extends NoUndeclaredProperties implements IXmlElementRefs +{ + + protected $values; + protected $type; + + /** + * @param \Weasel\XmlMarshaller\Config\Annotations\XmlElementRef[] $values + * @param string $type + * @AnnotationCreator({@Parameter(name="type", type="string", required=true), @Parameter(name="values", type="\Weasel\XmlMarshaller\Config\Annotations\XmlElementRef[]", required=true)}) + */ + public function __construct($type = null, array $values = array()) + { + $this->values = $values; + $this->type = $type; + } + + public function getValues() + { + return $this->values; + } + + public function getType() + { + return $this->type; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementWrapper.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementWrapper.php new file mode 100644 index 0000000..a7bf256 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlElementWrapper.php @@ -0,0 +1,65 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementWrapper; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation(on={"property", "method"}) + */ +class XmlElementWrapper extends NoUndeclaredProperties implements IXmlElementWrapper +{ + + protected $name; + protected $namespace; + protected $required; + protected $nillable; + + /** + * @param string $name + * @param $nillable + * @param string $namespace + * @param bool $required + * @AnnotationCreator({@Parameter(name="name", type="string", required=false), + @Parameter(name="nillable", type="bool", required=false), + @Parameter(name="namespace", type="string", required=false), + @Parameter(name="required", type="bool", required=false)}) + */ + public function __construct($name = null, $nillable = null, $namespace = null, $required = null) + { + $this->name = isset($name) ? $name : null; + $this->namespace = isset($namespace) ? $namespace : null; + $this->required = isset($required) && $required; + $this->nillable = isset($nillable) && $nillable; + } + + public function getName() + { + return $this->name; + } + + public function getNamespace() + { + return $this->namespace; + } + + public function getRequired() + { + return $this->required; + } + + public function getNillable() + { + return $this->nillable; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlRootElement.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlRootElement.php new file mode 100644 index 0000000..f0e64f1 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlRootElement.php @@ -0,0 +1,46 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlRootElement; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation(on={"class"}) + */ +class XmlRootElement extends NoUndeclaredProperties implements IXmlRootElement +{ + + protected $name; + protected $namespace; + + /** + * @param $name + * @param string $namespace + * @AnnotationCreator({@Parameter(name="name", type="string", required=false), @Parameter(name="namespace", type="string", required=false)}) + */ + public function __construct($name = null, $namespace = null) + { + $this->name = $name; + $this->namespace = $namespace; + } + + public function getName() + { + return $this->name; + } + + public function getNamespace() + { + return $this->namespace; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlSeeAlso.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlSeeAlso.php new file mode 100644 index 0000000..2274ede --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlSeeAlso.php @@ -0,0 +1,42 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlSeeAlso; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * The list of subtypes of this base class + * @Annotation(on={"class"}) + */ +class XmlSeeAlso extends NoUndeclaredProperties implements IXmlSeeAlso +{ + + protected $value; + + /** + * @param string[] $value + * @AnnotationCreator({@Parameter(name="value", type="string[]", required=true)}) + */ + public function __construct($value = null) + { + $this->value = $value; + } + + /** + * @return string[] + */ + public function getValue() + { + return $this->value; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/Annotations/XmlType.php b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlType.php new file mode 100644 index 0000000..6e8bbeb --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Annotations/XmlType.php @@ -0,0 +1,105 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Annotations; + +use Weasel\Annotation\Config\Annotations\Annotation; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlType; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation(on={"property", "method", "class"}) + */ +class XmlType extends NoUndeclaredProperties implements IXmlType +{ + + /** + * @var string + */ + protected $factoryClass; + + /** + * @var string + */ + protected $factoryMethod; + + /** + * @var string + */ + protected $name; + + /** + * @var string + */ + protected $namespace; + + /** + * @var string[] + */ + protected $propOrder; + + /** + * @param string $factoryClass + * @param string $factoryMethod + * @param string $name + * @param string $namespace + * @param string[] $propOrder + * @AnnotationCreator({@Parameter(name="factoryClass", type="string", required=false), + @Parameter(name="factoryMethod", type="string", required=false), + @Parameter(name="name", type="string", required=false), + @Parameter(name="namespace", type="string", required=false), + @Parameter(name="propOrder", type="string[]", required=false)}) + */ + public function __construct($factoryClass = null, $factoryMethod = null, $name = null, $namespace = null, $propOrder = null) + { + $this->factoryClass = $factoryClass; + $this->factoryMethod = $factoryMethod; + $this->name = $name; + $this->namespace = $namespace; + $this->propOrder = empty($propOrder) ? null : $propOrder; + } + + /** + * @return string + */ + public function getFactoryClass() + { + return $this->factoryClass; + } + + /** + * @return string + */ + public function getFactoryMethod() + { + return $this->factoryMethod; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return string + */ + public function getNamespace() + { + return $this->namespace; + } + + public function getPropOrder() + { + return $this->propOrder; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/ClassAnnotationDriver.php b/lib/Weasel/XmlMarshaller/Config/ClassAnnotationDriver.php new file mode 100644 index 0000000..9ad130b --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/ClassAnnotationDriver.php @@ -0,0 +1,448 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config; + +use Weasel\XmlMarshaller\Config\Annotations as Annotations; +use Weasel\XmlMarshaller\Config as Config; +use Weasel\Annotation\AnnotationReader; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerInterface; +use Weasel\Annotation\AnnotationReaderFactory; +use Weasel\Annotation\AnnotationConfigurator; +use Weasel\Common\Annotation\IAnnotationReaderFactory; + +class ClassAnnotationDriver implements LoggerAwareInterface +{ + /** + * @var \Weasel\Common\Annotation\IAnnotationReader + */ + protected $annotationReader; + + /** + * @var \Weasel\Annotation\AnnotationReaderFactory + */ + protected $annotationReaderFactory; + + /** + * @var \ReflectionClass + */ + protected $rClass; + + /** + * @var \Weasel\Annotation\AnnotationConfigurator + */ + protected $configurator; + + /** + * @var ClassMarshaller + */ + protected $config; + + /** + * @var string + */ + protected $annotationNamespace = '\Weasel\XmlMarshaller\Config\Annotations\\'; + + /** + * @param \ReflectionClass $rClass A reflection for the class we're configuring + * @param \Weasel\Common\Annotation\IAnnotationReaderFactory $annotationReaderFactory A factory for annotation readers + * @param string $annotationNamespace namespace in which we can find the annotations. + */ + public function __construct(\ReflectionClass $rClass, IAnnotationReaderFactory $annotationReaderFactory, $annotationNamespace = '\Weasel\XmlMarshaller\Config\Annotations') + { + $this->annotationReaderFactory = $annotationReaderFactory; + $this->rClass = $rClass; + $this->annotationNamespace = $annotationNamespace . '\\'; + } + + /** + * @return AnnotationReader + */ + public function getAnnotationReader() + { + if (!isset($this->annotationReader)) { + $this->annotationReader = $this->annotationReaderFactory->getReaderForClass($this->rClass); + } + return $this->annotationReader; + } + + protected function _configureSetter(\ReflectionMethod $method, $namespace) + { + $name = $method->getName(); + + $setterConfig = new Deserialization\SetterDeserialization(); + $setterConfig->method = $name; + $setterConfig->id = $method->getName(); + + /** + * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlAttribute $attributeConfig + */ + $attributeConfig = $this->getAnnotationReader()->getSingleMethodAnnotation($name, + $this->annotationNamespace . 'XmlAttribute'); + if (isset($attributeConfig)) { + $defaultName = lcfirst(substr($name, 3)); + $this->_configureAttributeDeserialization($attributeConfig, $setterConfig, $defaultName, $namespace); + return; + } + + $defaultName = ucfirst(substr($name, 3)); + + /** + * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElement $elementConfig + */ + $elementConfig = $this->getAnnotationReader()->getSingleMethodAnnotation($name, + $this->annotationNamespace . 'XmlElement'); + + if (isset($elementConfig)) { + $element = $this->_configureElementDeserialization($elementConfig, $setterConfig, $defaultName, $namespace); + } + + /** + * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRef $refConfig + */ + $refConfig = $this->getAnnotationReader()->getSingleMethodAnnotation($name, + $this->annotationNamespace . 'XmlElementRef'); + + if (isset($refConfig)) { + $element = $this->_configureElementRefDeserialization($refConfig, $setterConfig, $defaultName, $namespace); + } + + /** + * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRefs $refsConfig + */ + $refsConfig = $this->getAnnotationReader()->getSingleMethodAnnotation($name, + $this->annotationNamespace . 'XmlElementRefs'); + + if (isset($refsConfig)) { + $element = + $this->_configureElementRefsDeserialization($refsConfig, $setterConfig, $defaultName, $namespace); + } + + /** + * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementWrapper $wrapperConfig + */ + $wrapperConfig = $this->getAnnotationReader()->getSingleMethodAnnotation($name, + $this->annotationNamespace . 'XmlElementWrapper'); + if (isset($element) && isset($wrapperConfig)) { + $wrapper = new Config\Deserialization\ElementWrapper(); + // TODO locate real namespace + $wrapperNamespace = $wrapperConfig->getNamespace(); + if (!isset($wrapperNamespace)) { + $wrapperNamespace = $namespace; + } + $wrapperName = $wrapperConfig->getName(); + if (!isset($wrapperName)) { + $wrapperName = $defaultName; + } + + $wrapperFullName = (!empty($wrapperNamespace) ? $wrapperNamespace . ":" : "") . $wrapperName; + + $wrapper->name = $wrapperName; + $wrapper->namespace = $wrapperNamespace; + $wrapper->nillable = $wrapperConfig->getNillable(); + $wrapper->wraps = $element; + + if ($wrapperConfig->getRequired()) { + $this->config->deserialization->requiredElements[] = $setterConfig->id; + } + $this->config->deserialization->elementWrappers[$wrapperFullName] = $wrapper; + + } elseif (isset($element)) { + $this->config->deserialization->elements[] = $element; + } + + } + + protected function _configureElementRefDeserialization(IAnnotations\IXmlElementRef $annot, + Config\Deserialization\PropertyDeserialization $prop, + $defaultName, $defaultNamespace) + { + $elementConfig = new Config\Deserialization\ElementDeserialization(); + $prop->type = $annot->getType(); + $elementConfig->property = $prop; + + $elementConfig->ref = true; + + return $elementConfig; + } + + protected function _configureElementRefsDeserialization(IAnnotations\IXmlElementRefs $annot, + Config\Deserialization\PropertyDeserialization $prop, + $defaultName, $defaultNamespace) + { + $elementConfig = new Config\Deserialization\ElementDeserialization(); + $prop->type = $annot->getType(); + $elementConfig->property = $prop; + + $elementConfig->ref = true; + + $elementConfig->refNameToTypeMap = array(); + foreach ($annot->getValues() as $value) { + // TODO locate real namespace + $namespace = $value->getNamespace(); + if (!isset($namespace)) { + $namespace = $defaultNamespace; + } + $name = $value->getName(); + if (!isset($name)) { + $name = $defaultName; + } + $fullName = (!empty($namespace) ? $namespace . ":" : "") . $name; + $elementConfig->refNameToTypeMap[$fullName] = $value->getType(); + } + + return $elementConfig; + } + + protected function _configureElementDeserialization(IAnnotations\IXmlElement $annot, + Config\Deserialization\PropertyDeserialization $prop, + $defaultName, $defaultNamespace) + { + $elementConfig = new Config\Deserialization\ElementDeserialization(); + $prop->type = $annot->getType(); + $elementConfig->property = $prop; + $elementConfig->nillable = $annot->getNillable(); + + // TODO locate real namespace + $namespace = $annot->getNamespace(); + if (!isset($namespace)) { + $namespace = $defaultNamespace; + } + $name = $annot->getName(); + if (!isset($name)) { + $name = $defaultName; + } + + $elementConfig->name = $name; + $elementConfig->namespace = $namespace; + + if ($annot->getRequired()) { + $this->config->deserialization->requiredElements[] = $prop->id; + } + + return $elementConfig; + } + + protected function _configureAttributeDeserialization(IAnnotations\IXmlAttribute $annot, + Config\Deserialization\PropertyDeserialization $prop, + $defaultName, $defaultNamespace) + { + $attributeConfig = new Config\Deserialization\AttributeDeserialization(); + $prop->type = $annot->getType(); + $attributeConfig->property = $prop; + + // TODO locate real namespace + $namespace = $annot->getNamespace(); + if (!isset($namespace)) { + $namespace = $defaultNamespace; + } + $name = $annot->getName(); + if (!isset($name)) { + $name = $defaultName; + } + + $fullName = (!empty($namespace) ? $namespace . ":" : "") . $name; + + if ($annot->getRequired()) { + $this->config->deserialization->requiredAttributes[] = $prop->id; + } + + $this->config->deserialization->attributes[$fullName] = $attributeConfig; + } + + protected function _configureMethod(\ReflectionMethod $method, $namespace) + { + $name = $method->getName(); + if ($method->isStatic()) { +// $this->_configureCreator($method, $namespace); +// } elseif ($method->isConstructor()) { +// $this->_configureCreator($method, $namespace); +// } elseif (substr($name, 0, 3) === 'get') { +// $this->_configureGetter($method, $namespace); + } elseif (substr($name, 0, 3) === 'set') { + $this->_configureSetter($method, $namespace); + } + } + + protected function _configureProperty(\ReflectionProperty $property, $namespace) + { + $name = $property->getName(); + + $directConfig = new Deserialization\DirectDeserialization(); + $directConfig->property = $name; + $directConfig->id = '$' . $name; + + /** + * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlAttribute $attributeConfig + */ + $attributeConfig = $this->getAnnotationReader()->getSinglePropertyAnnotation($name, + $this->annotationNamespace . 'XmlAttribute'); + if (isset($attributeConfig)) { + $defaultName = lcfirst($name); + $this->_configureAttributeDeserialization($attributeConfig, $directConfig, $defaultName, $namespace); + return; + } + + $defaultName = ucfirst($name); + + /** + * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElement $elementConfig + */ + $elementConfig = $this->getAnnotationReader()->getSinglePropertyAnnotation($name, + $this->annotationNamespace . 'XmlElement'); + + if (isset($elementConfig)) { + $element = $this->_configureElementDeserialization($elementConfig, $directConfig, $defaultName, $namespace); + } + + /** + * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRef $refConfig + */ + $refConfig = $this->getAnnotationReader()->getSinglePropertyAnnotation($name, + $this->annotationNamespace . 'XmlElementRef'); + + if (isset($refConfig)) { + $element = $this->_configureElementRefDeserialization($refConfig, $directConfig, $defaultName, $namespace); + } + + /** + * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRefs $refsConfig + */ + $refsConfig = $this->getAnnotationReader()->getSinglePropertyAnnotation($name, + $this->annotationNamespace . 'XmlElementRefs'); + + if (isset($refConfig)) { + $element = + $this->_configureElementRefsDeserialization($refsConfig, $directConfig, $defaultName, $namespace); + } + + /** + * @var \Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementWrapper $wrapperConfig + */ + $wrapperConfig = $this->getAnnotationReader()->getSinglePropertyAnnotation($name, + $this->annotationNamespace . 'XmlElementWrapper'); + if (isset($element) && isset($wrapperConfig)) { + $wrapper = new Config\Deserialization\ElementWrapper(); + // TODO locate real namespace + $wrapperNamespace = $wrapperConfig->getNamespace(); + if (!isset($wrapperNamespace)) { + $wrapperNamespace = $namespace; + } + $wrapperName = $wrapperConfig->getName(); + if (!isset($wrapperName)) { + $wrapperName = $defaultName; + } + + $wrapperFullName = (!empty($wrapperNamespace) ? $wrapperNamespace . ":" : "") . $wrapperName; + + $wrapper->name = $wrapperName; + $wrapper->namespace = $wrapperNamespace; + $wrapper->nillable = $wrapperConfig->getNillable(); + $wrapper->wraps = $element; + + if ($wrapperConfig->getRequired()) { + $this->config->deserialization->requiredElements[] = $directConfig->id; + } + $this->config->deserialization->elementWrappers[$wrapperFullName] = $wrapper; + + } elseif (isset($element)) { + $this->config->deserialization->elements[] = $element; + } + + } + + public function getConfig() + { + + $this->config = new ClassMarshaller(); + $this->config->serialization = new Serialization\ClassSerialization(); + $this->config->deserialization = new Deserialization\ClassDeserialization(); + + /** + * @var IAnnotations\IXmlDiscriminatorValue $discrimValueA + */ + $discrimValueA = $this->getAnnotationReader()->getSingleClassAnnotation($this->annotationNamespace . 'XmlDiscriminatorValue'); + if (isset($discrimValueA)) { + $this->config->deserialization->discriminatorValue = $discrimValueA->getValue(); + } + + /** + * @var IAnnotations\IXmlDiscriminator $discrimA + */ + $discrimA = $this->getAnnotationReader()->getSingleClassAnnotation($this->annotationNamespace . 'XmlDiscriminator'); + if (isset($discrimA)) { + $this->config->deserialization->discriminator = $discrimA->getValue(); + } + + $name = $this->rClass->getName(); + $parts = explode('\\', $name); + $name = end($parts); + // TODO default namespace + $namespace = null; + + /** + * @var IAnnotations\IXmlType $xmlTypeA + */ + $xmlTypeA = $this->getAnnotationReader()->getSingleClassAnnotation($this->annotationNamespace . 'XmlType'); + if (isset($xmlTypeA)) { + // TODO work out wtf name and namespace mean. + + $factoryMethod = $xmlTypeA->getFactoryMethod(); + if (isset($factoryMethod)) { + $this->config->deserialization->factoryMethod = $factoryMethod; + $factoryClass = $xmlTypeA->getFactoryMethod(); + if (isset($factoryClass)) { + $this->config->deserialization->factoryClass = $factoryClass; + } + } + } + + /** + * @var IAnnotations\IXmlRootElement $rootA + */ + $rootA = $this->getAnnotationReader()->getSingleClassAnnotation($this->annotationNamespace . 'XmlRootElement'); + if (isset($rootA)) { + $name = ($rootA->getName() !== null) ? $rootA->getName() : $name; + $namespace = ($rootA->getNameSpace() !== null) ? $rootA->getNameSpace() : $namespace; + } + $this->config->deserialization->name = $name; + $this->config->deserialization->namespace = $namespace; + + /** + * @var IAnnotations\IXmlSeeAlso $seeAlsoA + */ + $seeAlsoA = $this->getAnnotationReader()->getSingleClassAnnotation($this->annotationNamespace . 'XmlSeeAlso'); + if (isset($seeAlsoA)) { + $this->config->deserialization->subClasses = $seeAlsoA->getValue(); + } + + $methods = $this->rClass->getMethods(\ReflectionMethod::IS_PUBLIC); + + foreach ($methods as $method) { + $this->_configureMethod($method, $namespace); + } + + $properties = $this->rClass->getProperties(\ReflectionProperty::IS_PUBLIC & ~\ReflectionProperty::IS_STATIC); + foreach ($properties as $property) { + $this->_configureProperty($property, $namespace); + } + + return $this->config; + + } + + /** + * Sets a logger instance on the object + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->annotationReaderFactory->setLogger($logger); + } +} diff --git a/lib/Weasel/XmlMarshaller/Config/ClassMarshaller.php b/lib/Weasel/XmlMarshaller/Config/ClassMarshaller.php new file mode 100644 index 0000000..ba565d4 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/ClassMarshaller.php @@ -0,0 +1,26 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config; + +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class ClassMarshaller +{ + + /** + * @var \Weasel\XmlMarshaller\Config\Serialization\ClassSerialization + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Serialization\ClassSerialization") + */ + public $serialization; + + /** + * @var \Weasel\XmlMarshaller\Config\Deserialization\ClassDeserialization + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\ClassDeserialization") + */ + public $deserialization; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/ConfigProvider.php b/lib/Weasel/XmlMarshaller/Config/ConfigProvider.php new file mode 100644 index 0000000..1e92eb4 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/ConfigProvider.php @@ -0,0 +1,18 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config; + +interface ConfigProvider +{ + + /** + * @param string $class + * @return \Weasel\XmlMarshaller\Config\ClassMarshaller + */ + public function getConfig($class); + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/AttributeDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/AttributeDeserialization.php new file mode 100644 index 0000000..475134d --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Deserialization/AttributeDeserialization.php @@ -0,0 +1,20 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Deserialization; + +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class AttributeDeserialization +{ + + /** + * @var \Weasel\XmlMarshaller\Config\Deserialization\PropertyDeserialization + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\PropertyDeserialization") + */ + public $property; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/ClassDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/ClassDeserialization.php new file mode 100644 index 0000000..6b6018f --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Deserialization/ClassDeserialization.php @@ -0,0 +1,85 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class ClassDeserialization +{ + + /** + * @var \Weasel\XmlMarshaller\Config\Deserialization\ElementDeserialization[] + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\ElementDeserialization[]") + */ + public $elements = array(); + + /** + * @var \Weasel\XmlMarshaller\Config\Deserialization\ElementWrapper[] + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\ElementWrapper[string]") + */ + public $elementWrappers = array(); + + /** + * @var \Weasel\XmlMarshaller\Config\Deserialization\AttributeDeserialization[] + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\AttributeDeserialization[string]") + */ + public $attributes = array(); + + /** + * @var string[] + * @JsonProperty(type="string[]") + */ + public $requiredElements = array(); + + /** + * @var string[] + * @JsonProperty(type="string[]") + */ + public $requiredAttributes = array(); + + /** + * @var string + * @JsonProperty(type="string") + */ + public $name; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $namespace; + + /** + * @var string[] + * @JsonProperty(type="string[]") + */ + public $subClasses; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $discriminator; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $discriminatorValue; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $factoryClass; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $factoryMethod; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/DirectDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/DirectDeserialization.php new file mode 100644 index 0000000..a26973e --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Deserialization/DirectDeserialization.php @@ -0,0 +1,25 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class DirectDeserialization + * @package Weasel\XmlMarshaller\Config\Deserialization + * @JsonTypeName("direct") + */ +class DirectDeserialization extends PropertyDeserialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $property; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementDeserialization.php new file mode 100644 index 0000000..a4e5d6d --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementDeserialization.php @@ -0,0 +1,49 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class ElementDeserialization +{ + + /** + * @var \Weasel\XmlMarshaller\Config\Deserialization\PropertyDeserialization + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\PropertyDeserialization") + */ + public $property; + + /** + * @var bool + * @JsonProperty(type="bool") + */ + public $nillable = false; + + /** + * @var bool + * @JsonProperty(type="bool") + */ + public $ref = false; + + /** + * @var string[] + * @JsonProperty(type="string[string]") + */ + public $refNameToTypeMap = null; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $name; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $namespace; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementWrapper.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementWrapper.php new file mode 100644 index 0000000..bd4b113 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Deserialization/ElementWrapper.php @@ -0,0 +1,38 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class ElementWrapper +{ + + /** + * @var bool + * @JsonProperty(type="bool") + */ + public $nillable = false; + + + /** + * @var \Weasel\XmlMarshaller\Config\Deserialization\ElementDeserialization + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Deserialization\ElementDeserialization") + */ + public $wraps; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $name; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $namespace; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/Param.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/Param.php new file mode 100644 index 0000000..ab80258 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Deserialization/Param.php @@ -0,0 +1,25 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class Param + * @package Weasel\XmlMarshaller\Config\Deserialization + * @JsonTypeName("param") + */ +class Param extends PropertyDeserialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $name; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/PropertyDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/PropertyDeserialization.php new file mode 100644 index 0000000..d7c0106 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Deserialization/PropertyDeserialization.php @@ -0,0 +1,37 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; + +/** + * Class PropertyDeserialization + * @package Weasel\XmlMarshaller\Config\Deserialization + * @JsonSubTypes({ + * @JsonSubTypes\Type("\Weasel\XmlMarshaller\Config\Deserialization\Param"), + * @JsonSubTypes\Type("\Weasel\XmlMarshaller\Config\Deserialization\SetterDeserialization"), + * @JsonSubTypes\Type("\Weasel\XmlMarshaller\Config\Deserialization\DirectDeserialization"), + * }) + * @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="how") + */ +abstract class PropertyDeserialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $id; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $type; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/SetterDeserialization.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/SetterDeserialization.php new file mode 100644 index 0000000..2890c87 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Deserialization/SetterDeserialization.php @@ -0,0 +1,25 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class SetterDeserialization + * @package Weasel\XmlMarshaller\Config\Deserialization + * @JsonTypeName("setter") + */ +class SetterDeserialization extends PropertyDeserialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $method; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Deserialization/TypeInfo.php b/lib/Weasel/XmlMarshaller/Config/Deserialization/TypeInfo.php new file mode 100644 index 0000000..1207c8a --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Deserialization/TypeInfo.php @@ -0,0 +1,58 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Deserialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class TypeInfo +{ + const TI_USE_CLASS = 1; + const TI_USE_CUSTOM = 2; + const TI_USE_MINIMAL_CLASS = 3; + const TI_USE_NAME = 4; + const TI_USE_NONE = 5; + + const TI_AS_PROPERTY = 1; + const TI_AS_WRAPPER_OBJECT = 2; + const TI_AS_WRAPPER_ARRAY = 3; + const TI_AS_EXTERNAL_PROPERTY = 4; + + /** + * @var string[] + * @JsonProperty(type="string[]") + */ + public $subTypes; + + /** + * @var int + * @JsonProperty(type="int") + */ + public $typeInfo = self::TI_USE_NONE; + + /** + * @var int + * @JsonProperty(type="int") + */ + public $typeInfoAs = self::TI_AS_PROPERTY; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $defaultImpl; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $typeInfoProperty; + + /** + * @var bool + * @JsonProperty(type="bool") + */ + public $typeInfoVisible = false; +} diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlAttribute.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlAttribute.php new file mode 100644 index 0000000..85f75e1 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlAttribute.php @@ -0,0 +1,61 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlAttribute; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation + * @Target({"PROPERTY", "METHOD"}) + */ +class XmlAttribute extends NoUndeclaredProperties implements IXmlAttribute +{ + + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $type = "string"; + + /** + * @var string + */ + public $namespace; + + /** + * @var bool + */ + public $required = false; + + public function getName() + { + return $this->name; + } + + public function getType() + { + return $this->type; + } + + public function getNamespace() + { + return $this->namespace; + } + + public function getRequired() + { + return $this->required; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminator.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminator.php new file mode 100644 index 0000000..59f90a6 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminator.php @@ -0,0 +1,35 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlDiscriminator; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation + * @Target({"CLASS"}) + */ +class XmlDiscriminator extends NoUndeclaredProperties implements IXmlDiscriminator +{ + + /** + * @var string + */ + public $value; + + /** + * @return string + */ + public function getValue() + { + return $this->value; + } + + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminatorValue.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminatorValue.php new file mode 100644 index 0000000..b03784d --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlDiscriminatorValue.php @@ -0,0 +1,35 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlDiscriminatorValue; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation + * @Target({"CLASS"}) + */ +class XmlDiscriminatorValue extends NoUndeclaredProperties implements IXmlDiscriminatorValue +{ + + /** + * @var string + */ + public $value; + + /** + * @return string + */ + public function getValue() + { + return $this->value; + } + + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElement.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElement.php new file mode 100644 index 0000000..4a7185f --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElement.php @@ -0,0 +1,71 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElement; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation + * @Target({"PROPERTY", "METHOD"}) + */ +class XmlElement extends NoUndeclaredProperties implements IXmlElement +{ + + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $type = "string"; + + /** + * @var string + */ + public $namespace; + + /** + * @var bool + */ + public $required = false; + + /** + * @var bool + */ + public $nillable = false; + + public function getName() + { + return $this->name; + } + + public function getType() + { + return $this->type; + } + + public function getNamespace() + { + return $this->namespace; + } + + public function getRequired() + { + return $this->required; + } + + public function getNillable() + { + return $this->nillable; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRef.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRef.php new file mode 100644 index 0000000..903e039 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRef.php @@ -0,0 +1,51 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRef; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation + * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) + */ +class XmlElementRef extends NoUndeclaredProperties implements IXmlElementRef +{ + + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $type; + + /** + * @var string + */ + public $namespace; + + public function getName() + { + return $this->name; + } + + public function getType() + { + return $this->type; + } + + public function getNamespace() + { + return $this->namespace; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRefs.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRefs.php new file mode 100644 index 0000000..65b02de --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementRefs.php @@ -0,0 +1,41 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementRefs; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation + * @Target({"PROPERTY", "METHOD"}) + */ +class XmlElementRefs extends NoUndeclaredProperties implements IXmlElementRefs +{ + + /** + * @var array + */ + public $values; + + /** + * @var string + */ + public $type; + + public function getValues() + { + return $this->values; + } + + public function getType() + { + return $this->type; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementWrapper.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementWrapper.php new file mode 100644 index 0000000..1cb2cee --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlElementWrapper.php @@ -0,0 +1,62 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlElementWrapper; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation + * @Target({"PROPERTY", "METHOD"}) + */ +class XmlElementWrapper extends NoUndeclaredProperties implements IXmlElementWrapper +{ + + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $namespace; + + /** + * @var bool + */ + public $required = false; + + /** + * @var bool + */ + public $nillable = false; + + + public function getName() + { + return $this->name; + } + + public function getNamespace() + { + return $this->namespace; + } + + public function getRequired() + { + return $this->required; + } + + public function getNillable() + { + return $this->nillable; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlRootElement.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlRootElement.php new file mode 100644 index 0000000..6d848d4 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlRootElement.php @@ -0,0 +1,41 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlRootElement; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation + * @Target({"CLASS"}) + */ +class XmlRootElement extends NoUndeclaredProperties implements IXmlRootElement +{ + + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $namespace; + + public function getName() + { + return $this->name; + } + + public function getNamespace() + { + return $this->namespace; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlSeeAlso.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlSeeAlso.php new file mode 100644 index 0000000..93e59ad --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlSeeAlso.php @@ -0,0 +1,35 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlSeeAlso; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * The list of subtypes of this base class + * @Annotation + * @Target({"CLASS"}) + */ +class XmlSeeAlso extends NoUndeclaredProperties implements IXmlSeeAlso +{ + + /** + * @var array + */ + public $value; + + /** + * @return string[] + */ + public function getValue() + { + return $this->value; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlType.php b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlType.php new file mode 100644 index 0000000..a30dc1a --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/DoctrineAnnotations/XmlType.php @@ -0,0 +1,83 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\Annotation; +use Weasel\XmlMarshaller\Config\IAnnotations\IXmlType; +use Weasel\Common\Utils\NoUndeclaredProperties; + +/** + * @Annotation + * @Target({"PROPERTY", "METHOD", "CLASS"}) + */ +class XmlType extends NoUndeclaredProperties implements IXmlType +{ + + /** + * @var string + */ + public $factoryClass; + + /** + * @var string + */ + public $factoryMethod; + + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $namespace; + + /** + * @var array + */ + public $propOrder; + + /** + * @return string + */ + public function getFactoryClass() + { + return $this->factoryClass; + } + + /** + * @return string + */ + public function getFactoryMethod() + { + return $this->factoryMethod; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return string + */ + public function getNamespace() + { + return $this->namespace; + } + + public function getPropOrder() + { + return $this->propOrder; + } + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlAttribute.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlAttribute.php new file mode 100644 index 0000000..32f1676 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlAttribute.php @@ -0,0 +1,19 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\IAnnotations; + +interface IXmlAttribute +{ + public function getName(); + + public function getType(); + + public function getNamespace(); + + public function getRequired(); +} + diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminator.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminator.php new file mode 100644 index 0000000..22a78b1 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminator.php @@ -0,0 +1,15 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\IAnnotations; + +interface IXmlDiscriminator +{ + + public function getValue(); + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminatorValue.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminatorValue.php new file mode 100644 index 0000000..0a96840 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlDiscriminatorValue.php @@ -0,0 +1,18 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\IAnnotations; + +interface IXmlDiscriminatorValue +{ + + /** + * @return string + */ + public function getValue(); + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElement.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElement.php new file mode 100644 index 0000000..bfd17d6 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElement.php @@ -0,0 +1,23 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\IAnnotations; + +interface IXmlElement +{ + + public function getName(); + + public function getType(); + + public function getNamespace(); + + public function getRequired(); + + public function getNillable(); + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRef.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRef.php new file mode 100644 index 0000000..f2ca9f8 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRef.php @@ -0,0 +1,19 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\IAnnotations; + +interface IXmlElementRef +{ + + public function getName(); + + public function getType(); + + public function getNamespace(); + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRefs.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRefs.php new file mode 100644 index 0000000..4a3314d --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementRefs.php @@ -0,0 +1,20 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\IAnnotations; + +interface IXmlElementRefs +{ + + /** + * @return IXmlElementRef[] + */ + public function getValues(); + + public function getType(); + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementWrapper.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementWrapper.php new file mode 100644 index 0000000..642f83c --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlElementWrapper.php @@ -0,0 +1,21 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\IAnnotations; + +interface IXmlElementWrapper +{ + + public function getName(); + + public function getNamespace(); + + public function getRequired(); + + public function getNillable(); + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlRootElement.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlRootElement.php new file mode 100644 index 0000000..1bf5696 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlRootElement.php @@ -0,0 +1,17 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\IAnnotations; + +interface IXmlRootElement +{ + + public function getName(); + + public function getNamespace(); + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlSeeAlso.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlSeeAlso.php new file mode 100644 index 0000000..b1791c8 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/IAnnotations/IXmlSeeAlso.php @@ -0,0 +1,18 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\IAnnotations; + +interface IXmlSeeAlso +{ + + /** + * @return string[] + */ + public function getValue(); + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/IAnnotations/XmlType.php b/lib/Weasel/XmlMarshaller/Config/IAnnotations/XmlType.php new file mode 100644 index 0000000..0950a11 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/IAnnotations/XmlType.php @@ -0,0 +1,35 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\IAnnotations; + +interface IXmlType +{ + + /** + * @return string + */ + public function getFactoryClass(); + + /** + * @return string + */ + public function getFactoryMethod(); + + /** + * @return string + */ + public function getName(); + + /** + * @return string + */ + public function getNamespace(); + + public function getPropOrder(); + +} + diff --git a/lib/Weasel/XmlMarshaller/Config/PropertyConfigProvider.php b/lib/Weasel/XmlMarshaller/Config/PropertyConfigProvider.php new file mode 100644 index 0000000..330e66d --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/PropertyConfigProvider.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ + +namespace Weasel\XmlMarshaller\Config; + +/** + * Class PropertyConfigProvider + * A really boring config provider which works off a public property containing a config object structure. + * This might be suitable for building a configuration from some DI framework or something. + * @package Weasel\XmlMarshaller\Config + */ +class PropertyConfigProvider implements ConfigProvider +{ + + /** + * @var ClassMarshaller[] Map of class names to ClassMarshallers + */ + public $config = array(); + + /** + * @param ClassMarshaller[] $config Map of class names to ClassMarshallers + */ + public function __construct(array $config = array()) + { + $this->config = $config; + } + + /** + * Obtain the config for a named class + * @param string $class The class to get the config for + * @return \Weasel\XmlMarshaller\Config\ClassMarshaller The config, or null if not found + */ + public function getConfig($class) + { + $class = ltrim($class, '\\'); + if (isset($this->config[$class])) { + return $this->config[$class]; + } + return null; + } +} \ No newline at end of file diff --git a/lib/Weasel/XmlMarshaller/Config/Serialization/ClassSerialization.php b/lib/Weasel/XmlMarshaller/Config/Serialization/ClassSerialization.php new file mode 100644 index 0000000..70fd48f --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Serialization/ClassSerialization.php @@ -0,0 +1,35 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Serialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class ClassSerialization +{ + + const INCLUDE_ALWAYS = 1; + const INCLUDE_NON_DEFAULT = 2; + const INCLUDE_NON_EMPTY = 3; + const INCLUDE_NON_NULL = 4; + + /** + * @var \Weasel\XmlMarshaller\Config\Serialization\PropertySerialization[] + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Serialization\PropertySerialization[string]") + */ + public $properties = array(); + + /** + * @var int + * @JsonProperty(type="int") + */ + public $include = self::INCLUDE_ALWAYS; + + /** + * @var \Weasel\XmlMarshaller\Config\Serialization\TypeInfo + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Serialization\TypeInfo") + */ + public $typeInfo; +} diff --git a/lib/Weasel/XmlMarshaller/Config/Serialization/DirectSerialization.php b/lib/Weasel/XmlMarshaller/Config/Serialization/DirectSerialization.php new file mode 100644 index 0000000..5fe499a --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Serialization/DirectSerialization.php @@ -0,0 +1,25 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Serialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class DirectSerialization + * @package Weasel\XmlMarshaller\Config\Serialization + * @JsonTypeName("direct") + */ +class DirectSerialization extends PropertySerialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $property; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Serialization/GetterSerialization.php b/lib/Weasel/XmlMarshaller/Config/Serialization/GetterSerialization.php new file mode 100644 index 0000000..6bb6270 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Serialization/GetterSerialization.php @@ -0,0 +1,25 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Serialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeName; + +/** + * Class GetterSerialization + * @package Weasel\XmlMarshaller\Config\Serialization + * @JsonTypeName("getter") + */ +class GetterSerialization extends PropertySerialization +{ + + /** + * @var string + * @JsonProperty(type="string") + */ + public $method; + +} diff --git a/lib/Weasel/XmlMarshaller/Config/Serialization/PropertySerialization.php b/lib/Weasel/XmlMarshaller/Config/Serialization/PropertySerialization.php new file mode 100644 index 0000000..42d7102 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Serialization/PropertySerialization.php @@ -0,0 +1,41 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Serialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes; + +/** + * Class PropertySerialization + * @package Weasel\XmlMarshaller\Config\Serialization + * @JsonSubTypes({ + * @JsonSubTypes\Type("\Weasel\XmlMarshaller\Config\Serialization\GetterSerialization"), + * @JsonSubTypes\Type("\Weasel\XmlMarshaller\Config\Serialization\DirectSerialization"), + * }) + * @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="how") + */ +class PropertySerialization +{ + + /** + * @var integer + * @JsonProperty(type="int") + */ + public $include; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $type; + + /** + * @var \Weasel\XmlMarshaller\Config\Serialization\TypeInfo + * @JsonProperty(type="\Weasel\XmlMarshaller\Config\Serialization\TypeInfo") + */ + public $typeInfo; +} diff --git a/lib/Weasel/XmlMarshaller/Config/Serialization/TypeInfo.php b/lib/Weasel/XmlMarshaller/Config/Serialization/TypeInfo.php new file mode 100644 index 0000000..579c7b9 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/Config/Serialization/TypeInfo.php @@ -0,0 +1,47 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller\Config\Serialization; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty; + +class TypeInfo +{ + const TI_USE_CLASS = 1; + const TI_USE_CUSTOM = 2; + const TI_USE_MINIMAL_CLASS = 3; + const TI_USE_NAME = 4; + const TI_USE_NONE = 5; + + const TI_AS_PROPERTY = 1; + const TI_AS_WRAPPER_OBJECT = 2; + const TI_AS_WRAPPER_ARRAY = 3; + const TI_AS_EXTERNAL_PROPERTY = 4; + + /** + * @var string[] + * @JsonProperty(type="string[]") + */ + public $subTypes; + + /** + * @var int + * @JsonProperty(type="int") + */ + public $typeInfo = self::TI_USE_NONE; + + /** + * @var int + * @JsonProperty(type="int") + */ + public $typeInfoAs = self::TI_AS_PROPERTY; + + /** + * @var string + * @JsonProperty(type="string") + */ + public $typeInfoProperty; + +} diff --git a/lib/Weasel/XmlMarshaller/XmlMapper.php b/lib/Weasel/XmlMarshaller/XmlMapper.php new file mode 100644 index 0000000..90b3126 --- /dev/null +++ b/lib/Weasel/XmlMarshaller/XmlMapper.php @@ -0,0 +1,476 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\XmlMarshaller; + +use Weasel\XmlMarshaller\Config\ConfigProvider; + +class XmlMapper +{ + + /** + * @var \Weasel\XmlMarshaller\Config\ConfigProvider + */ + protected $configProvider; + + public function __construct(ConfigProvider $configProvider) + { + $this->configProvider = $configProvider; + } + + public function readString($string, $class) + { + $reader = new \XMLReader(); +// $reader->setParserProperty(\XMLReader::VALIDATE, true); + $reader->xml($string); + $ret = $this->readXml($reader, $class); + $reader->close(); + return $ret; + } + + public function readXml(\XmlReader $xml, $class) + { + $xml->read(); + + return $this->_readObject($xml, $class, true); + + // TODO check end of file? + } + + protected function _readObject(\XMLReader $xml, $class, $root = false) + { + $deConfig = $this->configProvider->getConfig($class)->deserialization; + if (!isset($deConfig)) { + throw new \Exception("No config count for $class"); + } + // TODO handle simple value objecty things (XmlValue) + + $ignorableAttributes = array(); + + if (!empty($deConfig->subClasses)) { + if (!empty($deConfig->discriminator)) { + if (substr($deConfig->discriminator, 0, 1) !== '@') { + throw new \Exception( + "Unsupported discriminator, currently only attributes (denoted with @) are supported. Found: " . + $deConfig->discriminator); + } + $discrimName = substr($deConfig->discriminator, 1); + $attrNS = ($xml->namespaceURI) ? $xml->namespaceURI . ':' : ''; + $ignorableAttributes[$attrNS . $discrimName] = true; + + $discrimValue = $xml->getAttribute($discrimName); + foreach ($deConfig->subClasses as $subClass) { + $subConfig = $this->configProvider->getConfig($subClass)->deserialization; + if ($subConfig->discriminatorValue == $discrimValue) { + $class = $subClass; + $deConfig = $subConfig; + break; + } + } + } elseif ($root && ($xml->name != $deConfig->name || $xml->namespaceURI != $deConfig->namespace)) { + $matchName = $xml->name; + $matchNS = $xml->namespaceURI; + + foreach ($deConfig->subClasses as $subClass) { + $subConfig = $this->configProvider->getConfig($subClass)->deserialization; + if ($subConfig->name == $matchName && $subConfig->namespace == $matchNS) { + $class = $subClass; + $deConfig = $subConfig; + break; + } + } + } + + } + + $fullName = $xml->namespaceURI . ':' . $xml->name; + + if ($root && ($xml->name != $deConfig->name || $xml->namespaceURI != $deConfig->namespace)) { + throw new \Exception("Unable to resolve root node for {$fullName}"); + } + + $creatorClass = $class; + if (!empty($deConfig->factoryClass)) { + $creatorClass = $deConfig->factoryClass; + } + + if (!empty($deConfig->factoryMethod)) { + $creatorMethod = $deConfig->factoryMethod; + $object = $creatorClass::$creatorMethod(); + } else { + $object = new $class(); + } + + $seenAttributes = array(); + $seenElements = array(); + + $namespace = $xml->namespaceURI; + + if ($xml->hasAttributes) { + while ($xml->moveToNextAttribute()) { + $attrNS = + (($xml->namespaceURI) ? $xml->namespaceURI . ':' : (isset($namespace) ? $namespace . ':' : '')); + $fullName = $attrNS . $xml->name; + if ($xml->name === 'xmlns') { + continue; + } + if (isset($ignorableAttributes[$fullName])) { + continue; + } + if (!isset($deConfig->attributes[$fullName])) { + throw new \Exception("Unknown attribute found in {$class}: {$fullName}"); + } + $val = $this->_readAttribute($xml, $deConfig->attributes[$fullName]); + $this->_setProperty($object, $deConfig->attributes[$fullName]->property, $val); + $seenAttributes[] = $deConfig->attributes[$fullName]->property->id; + } + $xml->moveToElement(); + } + + $knownValues = array(); + + if (!$xml->isEmptyElement) { + while (true) { + if (!$xml->read()) { + throw new \Exception("XML read error"); + } + switch ($xml->nodeType) { + case \XMLReader::ELEMENT: + list($propType, $val) = $this->_readElement($xml, $deConfig); + $seenElements[] = $propType->id; + if (is_array($val)) { + if (!isset($knownValues[$propType->id])) { + $knownValues[$propType->id] = + array($propType, + array() + ); + } + $knownValues[$propType->id][1] = array_merge($knownValues[$propType->id][1], $val); + } else { + $this->_setProperty($object, $propType, $val); + } + break; + case \XMLReader::END_ELEMENT: + break 2; + case \XMLReader::WHITESPACE: + case \XMLReader::COMMENT: + case \XMLReader::SIGNIFICANT_WHITESPACE: + break; + default: + throw new \Exception("XML Parsing error, found unexpected {$xml->nodeType} while parsing for {$class}"); + } + } + } + + $notSeenAtts = array_diff($deConfig->requiredAttributes, $seenAttributes); + $notSeenElements = array_diff($deConfig->requiredElements, $seenElements); + if (!empty($notSeenAtts) || !empty($notSeenElements)) { + // TODO fix. + throw new \Exception("Missing required elements: " . implode(', ', $notSeenElements) . " and attributes: " . + implode(',', $notSeenAtts) . "on $class"); + } + + foreach ($knownValues as $typeval) { + list ($property, $values) = $typeval; + $this->_setProperty($object, $property, $values); + } + + return $object; + + } + + protected function _setProperty($object, Config\Deserialization\PropertyDeserialization $propConfig, $value) + { + if ($propConfig instanceof Config\Deserialization\DirectDeserialization) { + /** + * @var Config\Deserialization\DirectDeserialization $propConfig + */ + + $prop = $propConfig->property; + $object->$prop = $value; + + } elseif ($propConfig instanceof Config\Deserialization\SetterDeserialization) { + /** + * @var Config\Deserialization\SetterDeserialization $propConfig + */ + + $meth = $propConfig->method; + $object->$meth($value); + } + } + + protected function _readElementWrapper(\XMLReader $xml, Config\Deserialization\ElementWrapper $wrapperConfig) + { + + $elementConfig = $wrapperConfig->wraps; + + $collection = array(); + + while (true) { + if (!$xml->read()) { + throw new \Exception("XML Read failure parsing wrapper"); + } + $fullName = $xml->namespaceURI . ':' . $xml->name; + switch ($xml->nodeType) { + case \XMLReader::ELEMENT: + if ($elementConfig->ref) { + $type = $this->_getRef($elementConfig, $fullName); + } else { + $type = $elementConfig->property->type; + } + if (empty($type)) { + throw new \Exception( + "Unable to resolve wrapped type for " . $wrapperConfig->name . " base type " . + $wrapperConfig->wraps->property->type . " looking for " . $fullName); + } + $collection[] = $this->_readElementAsType($xml, $type); + break; + case \XMLReader::END_ELEMENT: + break 2; + case \XMLReader::WHITESPACE: + case \XMLReader::SIGNIFICANT_WHITESPACE: + case \XMLReader::COMMENT: + break; + default: + throw new \Exception("XML Parsing error, found unexpected {$xml->nodeType}"); + + } + } + + return array($elementConfig->property, + $collection + ); + } + + /** + * @param \Weasel\XmlMarshaller\Config\Deserialization\ElementDeserialization $ref + * @param string $fullName + * @return string the type + */ + protected function _getRef(Config\Deserialization\ElementDeserialization $ref, $fullName) + { + if (isset($ref->refNameToTypeMap)) { + if (isset($ref->refNameToTypeMap[$fullName])) { + return $ref->refNameToTypeMap[$fullName]; + } else { + return null; + } + } + $superConfig = $this->configProvider->getConfig($ref->property->type)->deserialization; + $superFullName = (isset($superConfig->namespace) ? $superConfig->namespace . ":" : "") . $superConfig->name; + $ref->refNameToTypeMap[$superFullName] = $ref->property->type; + foreach ($superConfig->subClasses as $subClass) { + $subConfig = $this->configProvider->getConfig($subClass)->deserialization; + $subFullName = (isset($subConfig->namespace) ? $subConfig->namespace . ":" : "") . $subConfig->name; + $ref->refNameToTypeMap[$subFullName] = $subClass; + } + if (isset($ref->refNameToTypeMap[$fullName])) { + return $ref->refNameToTypeMap[$fullName]; + } + return null; + } + + protected function _readElement(\XMLReader $xml, Config\Deserialization\ClassDeserialization $deConfig) + { + $fullName = $xml->namespaceURI . ':' . $xml->name; + if (isset($deConfig->elementWrappers[$fullName])) { + return $this->_readElementWrapper($xml, $deConfig->elementWrappers[$fullName], $deConfig); + } + + $type = null; + $element = null; + + foreach ($deConfig->elements as $el) { + if (!$el->ref && $el->name == $xml->name && $el->namespace == $xml->namespaceURI) { + $element = $el; + $type = $el->property->type; + break; + } + } + if (!isset($element)) { + foreach ($deConfig->elements as $el) { + if ($el->ref) { + if ($type = $this->_getRef($el, $fullName)) { + $element = $el; + break; + } + } + } + } + if (!isset($element)) { + throw new \Exception("Unknown element found in {$deConfig->name}: {$fullName}"); + } + + return array($element->property, + $this->_readElementAsType($xml, $type) + ); + } + + private static $_knownSimpleTypes = array( + "int" => "int", + "integer" => "integer", + "bool" => "bool", + "boolean" => "boolean", + "float" => "float", + "string" => "string" + ); + + /** + * @param \XMLReader $xml + * @param string $type + * @param bool $root + * @throws \Exception + * @return mixed + */ + protected function _readElementAsType($xml, $type, $root = false) + { + if (isset(self::$_knownSimpleTypes[$type])) { + $ret = $this->_decodeSimpleValue($xml->readInnerXml(), $type); + if (!$xml->isEmptyElement) { + $open = 1; + while ($open > 0) { + if (!$xml->read()) { + throw new \Exception("XML Read failure parsing simple value"); + } + if ($xml->nodeType == \XMLReader::ELEMENT && !$xml->isEmptyElement) { + $open++; + } elseif ($xml->nodeType == \XMLReader::END_ELEMENT) { + $open--; + } + } + } + return $ret; + } + + // Assume type strings are well formed: look for the last [ to see if it's an array or map. + // Note that this might be an array of arrays, and we're after the outermost type, so we're after the last [! + $pos = strrpos($type, '['); + if ($pos === false) { + // If there wasn't a [ then this must be an object. + return $this->_readObject($xml, $type, $root); + } + + // Extract the base type, and whatever's between the [...] as the index type. + // Potentially the type string is actually badly formed: + // e.g. this code will accept string[int! as being an array of string with index int. + // Bah. I'll ignore that case for now. This bit of code gets called a lot, I'd rather not add another substr. + $elementType = substr($type, 0, $pos); + $indexType = substr($type, $pos + 1, -1); + + // We return an array of the element(s) we've read. + // This will be merged if necessary by whoever we return it to. + if ($indexType === "") { + // It's an array element, not a map. + return array($this->_readElementAsType($xml, $elementType)); + } else { + return $this->_readMap($xml, $indexType, $elementType); + } + + } + + protected function _readMap(\XMLReader $xml, $indexType, $elementType) + { + + $array = array(); + + $inEntry = false; + + $key = null; + $value = null; + + do { + if (!$xml->read()) { + throw new \Exception("XML Read failure parsing array"); + } + switch ($xml->nodeType) { + case \XMLReader::ELEMENT: + if (!$inEntry && $xml->name !== 'entry') { + throw new \Exception("Expected map entry, got: " . $xml->name); + } + if ($xml->name === 'entry') { + $inEntry = true; + } elseif ($xml->name === 'key') { + if (isset($key)) { + throw new \Exception("Found multiple keys for entry"); + } + $key = $this->_readElementAsType($xml, $indexType); + } elseif ($xml->name === 'value') { + if (isset($key)) { + throw new \Exception("Found multiple values for entry"); + } + $key = $this->_readElementAsType($xml, $elementType); + } else { + throw new \Exception("Found unexpected node {$xml->name} when reading map"); + } + break; + case \XMLReader::END_ELEMENT: + if ($xml->name === 'entry') { + $xml->next(); + $inEntry = false; + } + break; + case \XMLReader::WHITESPACE: + case \XMLReader::COMMENT: + break; + default: + throw new \Exception("XML Parsing error, found unexpected {$xml->nodeType}"); + + } + } while ($xml->nodeType != \XMLReader::END_ELEMENT); + + return $array; + } + + protected function _readAttribute(\XMLReader $xml, Config\Deserialization\AttributeDeserialization $config) + { + return $this->_decodeSimpleValue($xml->value, $config->property->type); + } + + public function writeString($object, $class = null) + { + throw new \Exception("Not implemented yet"); + } + + protected function _decodeSimpleValue($value, $type) + { + switch ($type) { + case "bool": + case "boolean": + if (is_bool($value)) { + return (bool)$value; + } + if ($value === "true" || $value === 1) { + return true; + } + if ($value === "false" || $value === 0) { + return false; + } + throw new \Exception("Type error"); + break; + case "int": + case "integer": + if (!is_numeric($value)) { + throw new \Exception("Type error, expected numeric but got " . $value); + } + return (int)$value; + break; + case "string": + if (!is_string($value)) { + throw new \Exception("Type error, expected string but got " . gettype($value)); + } + return (string)$value; + case "float": + if (!is_numeric($value)) { + throw new \Exception("Type error, expected numeric but got " . $value); + } + return (float)$value; + default: + throw new \Exception("Invalid simple type: " . $type); + } + + } + +} diff --git a/lib/WeaselAutoloader.php b/lib/WeaselAutoloader.php new file mode 100644 index 0000000..404f259 --- /dev/null +++ b/lib/WeaselAutoloader.php @@ -0,0 +1,31 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel; + +/** + * @param string $name Class to load + * @return void + * @deprecated Install the package using composer, and use the composer autoloader! + */ +function autoLoad($name) +{ + if (class_exists($name) || interface_exists($name)) { + return; + } + $exploded = explode("\\", $name); + $vendor = $exploded[0]; + if ($vendor != "Weasel") { + return; + } + $path = implode('/', $exploded); + /** @noinspection PhpIncludeInspection */ + include(__DIR__ . '/' . $path . '.php'); + return; +} + +spl_autoload_register('\Weasel\autoLoad'); + diff --git a/tests/Weasel/Annotation/AnnotationConfiguratorTest.php b/tests/Weasel/Annotation/AnnotationConfiguratorTest.php new file mode 100644 index 0000000..dfd8adf --- /dev/null +++ b/tests/Weasel/Annotation/AnnotationConfiguratorTest.php @@ -0,0 +1,654 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation; + +use Weasel\Annotation\AnnotationReaderFactory; +use Weasel\Annotation\Config\Annotations\Annotation; + +class AnnotationConfiguratorTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + */ + public function testBuiltIns() + { + $mock = $this->createMock(AnnotationReaderFactory::class); + $mock->expects($this->never())->method('getReaderForClass'); + + $instance = new AnnotationConfigurator(null, null, $mock); + + $annotation = $instance->get(Annotation::class); + + $builtins = \Weasel\Annotation\Config\BuiltInsProvider::getConfig(); + $this->assertSame($builtins->getAnnotation(Annotation::class), $annotation); + + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + */ +// public function testBasicAnnotation() +// { +// +// $annotation = new Config\Annotations\Annotation(['class'], 6); +// $classAnnotations = ['\Weasel\Annotation\Config\Annotations\Annotation' => [$annotation]]; +//// $mock = +//// $this->getMock('\Weasel\Annotation\AnnotationReader', +//// ['getClassAnnotations', +//// 'getMethodAnnotations', +//// 'getPropertyAnnotations' +//// ], [], '', false +//// ); +// +// $mock = $this->createMock('\Weasel\Annotation\AnnotationReader'); +// $mock->expects($this->any())->method('getClassAnnotations') +// ->will($this->returnValue($classAnnotations)); +// $mock->expects($this->any()) +// ->method('getMethodAnnotations') +// ->will($this->returnValueMap([ +// ["__construct", []], ["setA", []], ["getA", []], ["creator", []] +// ]) +// ); +// $mock->expects($this->any()) +// ->method('getPropertyAnnotations') +// ->will($this->returnValue([])); +// +// $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); +// +// $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); +// +// $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', ['class'], 6); +// +// $this->assertEquals($expected, $result); +// +// } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * + public function testCreator() + { + + $annotation = new Config\Annotations\Annotation(array('class'), 6); + $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); + + $constructorParams = array(); + $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); + $constructorParams[] = new Config\Annotations\Parameter("bar", "integer", true); + $constructorParams[] = new Config\Annotations\Parameter(null, "boolean", false); + + $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); + + $constructorAnnotations = + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); + + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValueMap(array( + array("__construct", + $constructorAnnotations + ), + array("setA", + array() + ), + array("getA", + array() + ), + array("creator", + array() + ), + ) + ) + ); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValue(array())); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); + + $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); + $expected->setCreatorMethod('__construct'); + $expected->addCreatorParam(new Config\Param("foo", "string", true)); + $expected->addCreatorParam(new Config\Param("bar", "integer", true)); + $expected->addCreatorParam(new Config\Param("c", "boolean", false)); + + $this->assertEquals($expected, $result, "Got " . print_r($result, true)); + + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * + public function testStaticCreator() + { + + $annotation = new Config\Annotations\Annotation(array('class'), 6); + $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); + + $constructorParams = array(); + $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); + + $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); + + $constructorAnnotations = + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); + + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValueMap(array( + array("__construct", + array() + ), + array("setA", + array() + ), + array("getA", + array() + ), + array("creator", + $constructorAnnotations + ), + ) + ) + ); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValue(array())); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); + + $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); + $expected->setCreatorMethod('creator'); + $expected->addCreatorParam(new Config\Param("foo", "string", true)); + + $this->assertEquals($expected, $result); + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * + public function testProperties() + { + + $annotation = new Config\Annotations\Annotation(array('class'), 6); + $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); + + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValue(array())); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValueMap(array( + array("a", + array('\Weasel\Annotation\Config\Annotations\Property' => array(new Config\Annotations\Property("string"))), + ), + array("b", + array('\Weasel\Annotation\Config\Annotations\Property' => array(new Config\Annotations\Property("float"))), + ), + ) + ) + ); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); + + $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); + $expected->addProperty(new Config\Property("a", "string")); + $expected->addProperty(new Config\Property("b", "float")); + + $this->assertEquals($expected, $result, "Got " . print_r($result, true)); + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * + public function testEnum() + { + + $annotation = new Config\Annotations\Annotation(array('class'), 6); + $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); + + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValue(array())); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValueMap(array( + array("a", + array() + ), + array("b", + array() + ), + array("enumTest", + array('\Weasel\Annotation\Config\Annotations\Enum' => array( + new Config\Annotations\Enum("toast") + ) + ) + ) + ) + ) + ); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); + + $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); + $expected->addEnum(new Config\Enum("toast", array("FOO" => 1, + "BAR" => 2 + )) + ); + + $this->assertEquals($expected, $result, "Got " . print_r($result, true)); + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * + public function testEnumDefaultName() + { + + $annotation = new Config\Annotations\Annotation(array('class'), 6); + $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); + + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValue(array())); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValueMap(array( + array("a", + array() + ), + array("b", + array() + ), + array("enumTest", + array('\Weasel\Annotation\Config\Annotations\Enum' => array( + new Config\Annotations\Enum(null) + ) + ) + ) + ) + ) + ); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); + + $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); + $expected->addEnum(new Config\Enum("enumTest", array("FOO" => 1, + "BAR" => 2 + )) + ); + + $this->assertEquals($expected, $result, "Got " . print_r($result, true)); + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * @expectedException \RuntimeException + * @expectedExceptionMessage Enums must be static properties + * + public function testNonStaticEnum() + { + + $annotation = new Config\Annotations\Annotation(array('class'), 6); + $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); + + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValue(array())); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValueMap(array( + array("a", + array('\Weasel\Annotation\Config\Annotations\Enum' => array( + new Config\Annotations\Enum(null) + ) + ) + ), + ) + ) + ); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $instance->get('\Weasel\Annotation\BoringAnnotation'); + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * @expectedException \RuntimeException + * @expectedExceptionMessage Enum must be an array + * + public function testNonArrayEnum() + { + + $annotation = new Config\Annotations\Annotation(array('class'), 6); + $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); + + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValue(array())); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValueMap(array( + array("b", + array('\Weasel\Annotation\Config\Annotations\Enum' => array( + new Config\Annotations\Enum(null) + ) + ) + ), + ) + ) + ); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $instance->get('\Weasel\Annotation\BoringAnnotation'); + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * @expectedException \RuntimeException + * @expectedExceptionMessage Did not find an @Annotation annotation on + * + public function testThatsNoAnnotation() + { + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue(array())); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValueMap(array( + array("__construct", + array() + ), + array("setA", + array() + ), + array("getA", + array() + ), + array("creator", + array() + ), + ) + ) + ); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValue(array())); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $instance->get('\Weasel\Annotation\BoringAnnotation'); + + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * @expectedException \RuntimeException + * @expectedExceptionMessage Non-static methods cannot be configured as creators + * + public function testNonStaticCreatorFail() + { + $annotation = new Config\Annotations\Annotation(array('class'), 6); + $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); + + $constructorParams = array(); + $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); + + $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); + + $constructorAnnotations = + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); + + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValueMap(array( + array("__construct", + array() + ), + array("setA", + $constructorAnnotations + ), + array("getA", + array() + ), + array("creator", + array() + ), + ) + ) + ); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValue(array())); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $instance->get('\Weasel\Annotation\BoringAnnotation'); + + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * @expectedException \RuntimeException + * @expectedExceptionMessage Creator args don't match with method args + * + public function testTooManyCreatorArgs() + { + + $annotation = new Config\Annotations\Annotation(array('class'), 6); + $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); + + $constructorParams = array(); + $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); + $constructorParams[] = new Config\Annotations\Parameter("bar", "string", true); + + $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); + + $constructorAnnotations = + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); + + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValueMap(array( + array("__construct", + array() + ), + array("setA", + array() + ), + array("getA", + array() + ), + array("creator", + $constructorAnnotations + ), + ) + ) + ); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValue(array())); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $instance->get('\Weasel\Annotation\BoringAnnotation'); + } + + /** + * @covers \Weasel\Annotation\AnnotationConfigurator + * @expectedException \RuntimeException + * @expectedExceptionMessage Creator args don't match with method args + * + public function testTooFewCreatorArgs() + { + + $annotation = new Config\Annotations\Annotation(array('class'), 6); + $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); + + $constructorParams = array(); + $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); + $constructorParams[] = new Config\Annotations\Parameter("bar", "string", true); + + $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); + + $constructorAnnotations = + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); + + + $mock = + $this->getMock('\Weasel\Annotation\AnnotationReader', + array('getClassAnnotations', + 'getMethodAnnotations', + 'getPropertyAnnotations' + ), array(), '', false + ); + $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); + $mock->expects($this->any())->method('getMethodAnnotations') + ->will($this->returnValueMap(array( + array("__construct", + $constructorAnnotations + ), + array("setA", + array() + ), + array("getA", + array() + ), + array("creator", + array() + ), + ) + ) + ); + $mock->expects($this->any())->method('getPropertyAnnotations') + ->will($this->returnValue(array())); + $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); + + $instance->get('\Weasel\Annotation\BoringAnnotation'); + } */ +} + +class MockAnnotationReaderFactory extends AnnotationReaderFactory +{ + + public $mock; + + public function __construct($mock = null) + { + $this->mock = $mock; + } + + public function getReaderForClass(\ReflectionClass $class) + { + return $this->mock; + } +} + +class BoringAnnotation +{ + public $a; + + public static $b = 666; + + public static $enumTest = [ + "FOO" => 1, + "BAR" => 2, + ]; + + public function __construct($a = null, $b = null, $c = null) + { + $this->a = [$a, $b, $c]; + } + + public static function creator($a = null) + { + return new BoringAnnotation($a); + } + + public function setA($a) + { + $this->a = $a; + return $this; + } + + public function getA() + { + return $this->a; + } + +} diff --git a/tests/Weasel/Annotation/AnnotationReaderTest.php b/tests/Weasel/Annotation/AnnotationReaderTest.php new file mode 100644 index 0000000..5e80b7b --- /dev/null +++ b/tests/Weasel/Annotation/AnnotationReaderTest.php @@ -0,0 +1,33 @@ +shouldReceive('get')->with('\HelloWorld')->andReturn(new Annotation('\stdClass', array(), 1)); + + require __DIR__ . '/resources/AnnotatedClass.php'; + $reader = new AnnotationReader(new \ReflectionClass('\Weasel_Annotation_TestResources_AnnotatedClass'), $mockConfigProvider); + $read = $reader->getClassAnnotations(); + + // Ordering is important. We need to require the NoDocBlock file immediately to ensure that the last thing + // parsed was the AnnotatedClass + require __DIR__ . '/resources/NoDocBlock.php'; + $this->assertNotEmpty($read); + + $reader = new AnnotationReader(new \ReflectionClass('\Weasel_Annotation_TestResources_NoDocBlock'), $mockConfigProvider); + + $this->assertEmpty($reader->getClassAnnotations()); + + } + +} diff --git a/tests/Weasel/Annotation/DocblockLexerTest.php b/tests/Weasel/Annotation/DocblockLexerTest.php new file mode 100644 index 0000000..80d1b30 --- /dev/null +++ b/tests/Weasel/Annotation/DocblockLexerTest.php @@ -0,0 +1,255 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Tests; + +use Weasel\Annotation\DocblockLexer; + +class DocblockLexerTest extends \PHPUnit_Framework_TestCase +{ + + public function provideSimpleType() + { + return array( + array(' 123 +942 -954 1 0 +0 -0 +5-1 ', + array_fill(0, 9, DocblockLexer::T_INTEGER) + ), + array('123 +942 -954 1 0 +0 -0 +5-1 ', + array_fill(0, 9, DocblockLexer::T_INTEGER) + ), + array(' 12.3+9.42 -95.4 1.0 0.0 +0.0-0.0 5e5 12E75 -23e93 94e-12', + array_fill(0, 11, DocblockLexer::T_FLOAT) + ), + array(' true false + true', + array_fill(0, 3, DocblockLexer::T_BOOLEAN) + ), + array(' @ @ @@', + array_fill(0, 4, DocblockLexer::T_AT) + ), + array(' \\\\ \\\\\\', + array_fill(0, 5, DocblockLexer::T_BACKSLASH) + ), + array(' "foo bar" """w he e" "w @oo""ar gh""me h 123" "hello + world"', + array_fill(0, 4, DocblockLexer::T_QUOTED_STRING) + ), + array(':: :', + array_fill(0, 3, DocblockLexer::T_COLON) + ), + array('} }}', + array_fill(0, 3, DocblockLexer::T_CLOSE_BRACE) + ), + array('{ { {', + array_fill(0, 3, DocblockLexer::T_OPEN_BRACE) + ), + array(') ))', + array_fill(0, 3, DocblockLexer::T_CLOSE_PAREN) + ), + array('(( (', + array_fill(0, 3, DocblockLexer::T_OPEN_PAREN) + ), + array(', ,,', + array_fill(0, 3, DocblockLexer::T_COMMA) + ), + array('.. .', + array_fill(0, 3, DocblockLexer::T_DOT) + ), + array(' = = =', + array_fill(0, 3, DocblockLexer::T_EQUAL) + ), + array(' foo bar baz', + array_fill(0, 3, DocblockLexer::T_IDENTIFIER) + ), + array(' null null null', + array_fill(0, 3, DocblockLexer::T_NULL) + ), + array(' + # ~', + array_fill(0, 3, DocblockLexer::T_MEH) + ), + ); + + } + + /** + * @param $in + * @param $expectedTypes + * @dataProvider provideSimpleType + * @covers \Weasel\Annotation\DocblockLexer + */ + public function testSimpleType($in, $expectedTypes) + { + $lexer = new DocblockLexer($in); + $got = array(); + $toks = array(); + $peeked[] = $lexer->peek(1, true); + $cur = $lexer->skip(); + do { + $this->assertEquals($cur, $lexer->get()); + if ($peek = $lexer->peek(1, true)) { + $peeked[] = $peek; + } + $got[] = $cur['type']; + $toks[] = $cur['token']; + } while ($cur = $lexer->next(true)); + $this->assertEquals($expectedTypes, $got, 'Type failure on array ' . print_r($toks, true)); + $this->assertEquals($expectedTypes, $peeked, 'Type failure on array ' . print_r($toks, true)); + } + + /** + * @covers \Weasel\Annotation\DocblockLexer + */ + public function testWhiteSpace() + { + $lexer = new DocblockLexer(" "); + + $cur = $lexer->get(); + $peek = $lexer->peek(); + $next = $lexer->next(); + + $this->assertEquals(DocblockLexer::T_WHITESPACE, $cur["type"]); + $this->assertNull($peek); + $this->assertNull($next); + + } + + /** + * @covers \Weasel\Annotation\DocblockLexer + */ + public function testEOL() + { + $lexer = new DocblockLexer("\n\n\r\n\n"); + + $cur = $lexer->get(); + $peek = $lexer->peek(); + $next = $lexer->next(); + + $this->assertEquals(DocblockLexer::T_EOL, $cur["type"]); + $this->assertNull($peek); + $this->assertNull($next); + + } + + /** + * @covers \Weasel\Annotation\DocblockLexer + */ + public function testPreamble() + { + $lexer = new DocblockLexer("\n * \r\n *\t"); + + $cur = $lexer->get(); + $peek = $lexer->peek(); + $next = $lexer->next(); + + $this->assertEquals(DocblockLexer::T_PREAMBLE, $cur["type"]); + $this->assertEquals(DocblockLexer::T_PREAMBLE, $peek); + $this->assertEquals(DocblockLexer::T_PREAMBLE, $next["type"]); + + } + + /** + * @covers \Weasel\Annotation\DocblockLexer::peek + * @covers \Weasel\Annotation\DocblockLexer::cur + * @covers \Weasel\Annotation\DocblockLexer::_wsSkippingPeek + */ + public function testPeek() + { + + $testIn = '@ 1 \ true "foo" bar'; + $lexer = new DocblockLexer($testIn); + + $cur = $lexer->cur(); + $this->assertEquals(DocblockLexer::T_AT, $lexer->peek(0)); + $this->assertEquals(DocblockLexer::T_WHITESPACE, $lexer->peek(1)); + $this->assertEquals(DocblockLexer::T_INTEGER, $lexer->peek(2)); + $this->assertEquals(DocblockLexer::T_IDENTIFIER, $lexer->peek(10)); + $this->assertNull($lexer->peek(11)); + + $this->assertEquals(DocblockLexer::T_AT, $lexer->peek(0, true)); + $this->assertEquals(DocblockLexer::T_INTEGER, $lexer->peek(1, true)); + $this->assertEquals(DocblockLexer::T_BACKSLASH, $lexer->peek(2, true)); + $this->assertEquals(DocblockLexer::T_BOOLEAN, $lexer->peek(3, true)); + + $this->assertEquals(DocblockLexer::T_IDENTIFIER, $lexer->peek(5, true)); + $this->assertNull($lexer->peek(6, true)); + $this->assertEquals(DocblockLexer::T_INTEGER, $lexer->peek(1, true)); + $this->assertEquals($cur, $lexer->cur()); + + $lexer->next(); + $this->assertEquals(DocblockLexer::T_INTEGER, $lexer->peek(0, true)); + + } + + /** + * @covers \Weasel\Annotation\DocblockLexer::peek + * @expectedException \InvalidArgumentException + */ + public function testBadPeek() + { + $testIn = '@ 1 \ true "foo" bar'; + $lexer = new DocblockLexer($testIn); + $lexer->peek(-1); + } + + /** + * @covers \Weasel\Annotation\DocblockLexer::seek + * @covers \Weasel\Annotation\DocblockLexer::cur + */ + public function testSeek() + { + $testIn = '@ 1 \ true "foo" bar'; + $lexer = new DocblockLexer($testIn); + + $this->assertEquals(0, $lexer->cur()); + $cur = $lexer->seek(4); + $this->assertEquals(4, $lexer->cur()); + $this->assertEquals(DocblockLexer::T_BACKSLASH, $cur["type"]); + $this->assertEquals($lexer->get(), $cur); + $cur = $lexer->seek(-3); + $this->assertEquals(8, $lexer->cur()); + $this->assertEquals(DocblockLexer::T_QUOTED_STRING, $cur["type"]); + $this->assertEquals($lexer->get(), $cur); + $this->assertNull($lexer->seek(12)); + $this->assertEquals(8, $lexer->cur()); + $cur = $lexer->seek(0); + $this->assertEquals(0, $lexer->cur()); + $this->assertEquals(DocblockLexer::T_AT, $cur["type"]); + $this->assertEquals($lexer->get(), $cur); + } + + /** + * @covers \Weasel\Annotation\DocblockLexer::skipToType + */ + public function testSkipToType() + { + $testIn = '@ 1 \ true "foo" bar'; + $lexer = new DocblockLexer($testIn); + + $cur = $lexer->skipToType(DocblockLexer::T_AT); + $this->assertEquals(DocblockLexer::T_AT, $cur["type"]); + $this->assertEquals($lexer->get(), $cur); + + $cur = $lexer->skipToType(DocblockLexer::T_QUOTED_STRING); + $this->assertEquals(DocblockLexer::T_QUOTED_STRING, $cur["type"]); + $this->assertEquals($lexer->get(), $cur); + + $this->assertNull($lexer->skipToType(DocblockLexer::T_COLON)); + + } + + /** + * @covers \Weasel\Annotation\DocblockLexer::skipToType + */ + public function testSkipToTypeEmpty() + { + $lexer = new DocblockLexer(""); + + $this->assertNull($lexer->skipToType(DocblockLexer::T_AT)); + + } + + +} diff --git a/tests/Weasel/Annotation/DocblockParserTest.php b/tests/Weasel/Annotation/DocblockParserTest.php new file mode 100644 index 0000000..e79d820 --- /dev/null +++ b/tests/Weasel/Annotation/DocblockParserTest.php @@ -0,0 +1,599 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\Annotation\Tests; + +use Weasel\Annotation\DocblockParser; +use Weasel\Annotation\AnnotationConfigurator; +use Weasel\Annotation\Config\AnnotationConfig; + +class DocblockParserTest extends \PHPUnit_Framework_TestCase +{ + + public function provideSimpleClassAnnotation() + { + return [ + ['flibble fish', 'string'], + ['test "some" quotes', 'string'], + [12356, 'integer'], + [5.23, 'float'], + [true, 'boolean'], + [false, 'boolean'], + ]; + } + + protected function _phpTypeToAnnotationType($type, $value) + { + if ($type === 'string') { + return '"' . str_replace('"', '""', $value) . '"'; + } + if ($type === 'boolean') { + return $value ? "true" : "false"; + } + return $value; + } + + + /** + * @param $value + * @param $type + * @dataProvider provideSimpleClassAnnotation + * @covers \Weasel\Annotation\DocblockParser + */ + public function testSimpleClassAnnotation($value, $type) + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', $type)); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $valueQuoted = $this->_phpTypeToAnnotationType($type, $value); + + $parsed = $parser->parse( + '/** + * @Gloop(foo=' . $valueQuoted . ') + *', + "class", + array('Gloop' => 'Weasel\Annotation\Tests\Gloop') + ); + + $gloop = new Gloop(); + $gloop->foo = $value; + + $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); + + } + + /** + * @covers \Weasel\Annotation\DocblockParser + */ + public function testNoArgsAnnotation() + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @Gloop + *', + "class", + array('Gloop' => 'Weasel\Annotation\Tests\Gloop') + ); + + $gloop = new Gloop(); + + $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); + + } + + /** + * @covers \Weasel\Annotation\DocblockParser + */ + public function testTwoAnnotations() + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @Gloop + * @Gloop + *', + "class", + array('Gloop' => 'Weasel\Annotation\Tests\Gloop') + ); + + $gloop = new Gloop(); + + $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop, + $gloop + ) + ), $parsed + ); + + } + + /** + * @covers \Weasel\Annotation\DocblockParser + */ + public function testEmptyArgsAnnotation() + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @Gloop() + *', + "class", + array('Gloop' => 'Weasel\Annotation\Tests\Gloop') + ); + + $gloop = new Gloop(); + + $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); + + } + + /** + * @covers \Weasel\Annotation\DocblockParser + */ + public function testFullyNamespacedAnnotation() + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @\Weasel\Annotation\Tests\Gloop + *', + "class", + array() + ); + + $gloop = new Gloop(); + + $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); + + } + + /** + * @covers \Weasel\Annotation\DocblockParser + */ + public function testMissingWhitespaceNoArgs() + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @\Weasel\Annotation\Tests\Gloop@glarp + *', + "class", + array() + ); + + $this->assertEmpty($parsed); + + } + + /** + * @covers \Weasel\Annotation\DocblockParser + */ + public function testMissingWhitespaceArgs() + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @\Weasel\Annotation\Tests\Gloop()@glarp + *', + "class", + array() + ); + + $this->assertEmpty($parsed); + + } + + /** + * @covers \Weasel\Annotation\DocblockParser + */ + public function testArrayClassAnnotation() + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', 'string[][]')); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @Gloop(foo={{"ab", "cd"}, {"ef"}, {}}) + *', + "class", + array('Gloop' => 'Weasel\Annotation\Tests\Gloop') + ); + + $gloop = new Gloop(); + $gloop->foo = + array(array("ab", + "cd" + ), + array("ef"), + array() + ); + + $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); + + } + + /** + * @covers \Weasel\Annotation\DocblockParser + */ + public function testArraySingleElementClassAnnotation() + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', 'string[]')); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @Gloop(foo="bar") + *', + "class", + array('Gloop' => 'Weasel\Annotation\Tests\Gloop') + ); + + $gloop = new Gloop(); + $gloop->foo = array("bar"); + + $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); + + } + + /** + * @param $value + * @param $type + * @dataProvider provideSimpleClassAnnotation + * @covers \Weasel\Annotation\DocblockParser + */ + public function testNestedClassAnnotation($value, $type) + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', '\Weasel\Annotation\Tests\Glarp')); + $mockConfigurator->addAnnotation($annotation); + $annotation = + new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Glarp', array('\Weasel\Annotation\Tests\Gloop')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('bar', $type)); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $valueQuoted = $this->_phpTypeToAnnotationType($type, $value); + + $parsed = $parser->parse( + '/** + * @Gloop(foo=@Glarp(bar=' . $valueQuoted . ')) + *', + "class", + array( + 'Gloop' => 'Weasel\Annotation\Tests\Gloop', + 'Glarp' => 'Weasel\Annotation\Tests\Glarp' + ) + + ); + + $gloop = new Gloop(); + $gloop->foo = new Glarp(); + $gloop->foo->bar = $value; + + $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); + + } + + /** + * @covers \Weasel\Annotation\DocblockParser + */ + public function testMultiNestedArgs() + { + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Multi', array('class')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('a', '\Weasel\Annotation\Tests\Glarp')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('b', '\Weasel\Annotation\Tests\Glarp')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('c', '\Weasel\Annotation\Tests\Gloop')); + $mockConfigurator->addAnnotation($annotation); + $annotation = + new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Glarp', array('\Weasel\Annotation\Tests\Multi')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('bar', 'string')); + $mockConfigurator->addAnnotation($annotation); + $annotation = + new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('\Weasel\Annotation\Tests\Multi')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', 'string')); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @Multi(a=@Glarp(bar="foo"), b=@Glarp(bar="baa"), c=@Gloop(foo="fnord")) + * @Multi(a=@Glarp(bar="foo") , b=@Glarp(bar="baa") , c=@Gloop(foo="fnord")) + * @Multi(a=@Glarp(bar="foo"),b=@Glarp(bar="baa"),c=@Gloop(foo="fnord")) + *', + "class", + array( + 'Gloop' => 'Weasel\Annotation\Tests\Gloop', + 'Glarp' => 'Weasel\Annotation\Tests\Glarp', + 'Multi' => 'Weasel\Annotation\Tests\Multi' + ) + + ); + + $multi = new Multi(); + $multi->a = new Glarp(); + $multi->a->bar = "foo"; + $multi->b = new Glarp(); + $multi->b->bar = "baa"; + $multi->c = new Gloop(); + $multi->c->foo = "fnord"; + + $results = array_fill(0, 3, $multi); + + $this->assertEquals(array('\Weasel\Annotation\Tests\Multi' => $results), $parsed); + + } + + /** + * @param $value + * @param $type + * @dataProvider provideSimpleClassAnnotation + * @runInSeparateProcess + * @covers \Weasel\Annotation\DocblockParser + */ + public function testSimpleClassAnnotationCreator($value, $type) + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', ['class']); + $annotation->setCreatorMethod('__construct'); + $annotation->addCreatorParam( + new \Weasel\Annotation\Config\Param('foo', $type, false) + ); + $annotation->addCreatorParam( + new \Weasel\Annotation\Config\Param('baz', $type, false) + ); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $valueQuoted = $this->_phpTypeToAnnotationType($type, $value); + + $parsed = $parser->parse( + '/** + * @Gloop(foo=' . $valueQuoted . ') + * @Gloop(' . $valueQuoted . ') + * @Gloop(' . $valueQuoted . ', ' . $valueQuoted . ') + * @Gloop(baz=' . $valueQuoted . ') + */', + "class", + ['Gloop' => 'Weasel\Annotation\Tests\Gloop'] + ); + + $expected = []; + + $gloop = new Gloop(); + $gloop->fromca = $value; + $expected[] = $gloop; + + $gloop = new Gloop(); + $gloop->fromca = $value; + $gloop->fromcb = $value; + $expected[] = $gloop; + + $gloop = new Gloop(); + $gloop->fromcb = $value; + $expected[] = $gloop; + + $this->assertEquals(['\Weasel\Annotation\Tests\Gloop' => $expected], $parsed); + + } + + /** + * @return void + * @covers \Weasel\Annotation\DocblockParser + */ + public function testUnknownAnnotations() + { + + $mockConfigurator = new MockConfigurator(); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @author Jonathan Oddy + * @param string $value Wheeeeee + * @param string[] $type Wobble Kerping Splat + * @returns your mum + */', + "method", + array() + ); + + $this->assertEquals(array(), $parsed); + + } + + /** + * @return void + * @covers \Weasel\Annotation\DocblockParser + */ + public function testEnumAnnotation() + { + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $annotation->addProperty(new \Weasel\Annotation\Config\Property('foo', 'integer')); + $annotation->addEnum(new \Weasel\Annotation\Config\Enum('Snorks', array("FOO" => 1, + "BAR" => 2, + "BAZ" => 3 + )) + ); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @Gloop(foo=Gloop.Snorks.BAR) + */', + "class", + array('Gloop' => 'Weasel\Annotation\Tests\Gloop') + ); + + $gloop = new Gloop(); + $gloop->foo = 2; + + $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); + + } + + /** + * @return void + * @covers \Weasel\Annotation\DocblockParser + */ + public function testEnumAnnotationNoName() + { + $this->markTestSkipped(); + + $mockConfigurator = new MockConfigurator(); + $annotation = new \Weasel\Annotation\Config\Annotation('\Weasel\Annotation\Tests\Gloop', array('class')); + $annotation->setCreatorMethod('__construct'); + $annotation->addCreatorParam(new \Weasel\Annotation\Config\Param('foo', 'integer', false)); + $annotation->addCreatorParam(new \Weasel\Annotation\Config\Param('baz', 'integer', false)); + $annotation->addEnum(new \Weasel\Annotation\Config\Enum('Snorks', array("FOO" => 1, + "BAR" => 2, + "BAZ" => 3 + )) + ); + $mockConfigurator->addAnnotation($annotation); + + $parser = new DocblockParser($mockConfigurator); + + $parsed = $parser->parse( + '/** + * @Gloop(Gloop.Snorks.BAR) + */', + "class", + array('Gloop' => 'Weasel\Annotation\Tests\Gloop') + ); + + $gloop = new Gloop(); + $gloop->fromca = 2; + + $this->assertEquals(array('\Weasel\Annotation\Tests\Gloop' => array($gloop)), $parsed); + + } +} + +class Gloop +{ + + public $foo; + + public $fromca; + public $fromcb; + + public function __construct($foo = null, $baz = null) + { + $this->fromca = $foo; + $this->fromcb = $baz; + } +} + +class Multi +{ + + public $a; + public $b; + public $c; + +} + +class Glarp +{ + + public $bar; + + public $fromca; + public $fromcb; + + public function __construct($bar = null, $baz = null) + { + $this->fromca = $bar; + $this->fromcb = $baz; + } + +} + +class MockConfigurator extends AnnotationConfigurator +{ + + protected $config; + + public function addAnnotation($annotation) + { + $this->config->addAnnotation($annotation); + } + + public function __construct() + { + $this->config = new AnnotationConfig(); + } + + public function get($type) + { + return $this->config->getAnnotation($type); + } + +} + diff --git a/tests/Weasel/Annotation/PHPParserTest.php b/tests/Weasel/Annotation/PHPParserTest.php new file mode 100644 index 0000000..e52685a --- /dev/null +++ b/tests/Weasel/Annotation/PHPParserTest.php @@ -0,0 +1,80 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ + +use ReflectionClass; +use PHPUnit_Framework_TestCase; + +class PHPParserTest extends PHPUnit_Framework_TestCase +{ + + + public function provideClasses() + { + return array( + array('\Weasel\Annotation\TestResources\SimpleNamespaced', 'SimpleNamespaced', array( + '' => 'Weasel\Annotation\TestResources', + 'TestA' => 'Weasel\Annotation\TestResources\TestA', + 'TestB' => 'Weasel\Annotation\TestResources\TestB', + 'Test' => 'Weasel\Annotation\TestResources\BlahFoo', + )), + array('\Weasel\Annotation\TestResources\SimpleNamespacedSibling', 'SimpleNamespaced', array( + '' => 'Weasel\Annotation\TestResources', + 'TestA' => 'Weasel\Annotation\TestResources\TestA', + 'TestB' => 'Weasel\Annotation\TestResources\TestB', + 'Test' => 'Weasel\Annotation\TestResources\BlahFoo', + )), + array('\Weasel\Annotation\TestResources\SimpleNamespacedExtender', 'SimpleNamespacedExtends', array( + '' => 'Weasel\Annotation\TestResources', + 'TestA' => 'Weasel\Annotation\TestResources\TestA', + 'TestB' => 'Weasel\Annotation\TestResources\TestB', + 'Test' => 'Weasel\Annotation\TestResources\BlahFoo', + )), + array('\Weasel\Annotation\TestResources\NamespacedFirst', 'MultipleNamespace', array( + '' => 'Weasel\Annotation\TestResources', + 'TestA' => 'Weasel\Annotation\TestResources\TestA', + 'TestB' => 'Weasel\Annotation\TestResources\TestB', + 'Test' => 'Weasel\Annotation\TestResources\BlahFoo', + )), + array('\Weasel\Annotation\TestResourcesToo\NamespacedSecond', 'MultipleNamespace', array( + '' => 'Weasel\Annotation\TestResourcesToo', + 'TestC' => 'Weasel\Annotation\TestResources\TestC', + )), + array('\Weasel\Annotation\TestResources\NamespacedShorthand', 'NamespacedShorthand', array( + '' => 'Weasel\Annotation\TestResources', + 'TestD' => 'Weasel\Annotation\TestResources\TestD', + 'TestE' => 'Weasel\Annotation\TestResources\TestE', + 'Test' => 'Weasel\Annotation\TestResources\TestF', + )), + array('NoNamespaceTest', 'NoNamespace', array( + 'TestA' => 'Weasel\Annotation\TestResources\TestA', + '' => '', + )), + array('\Weasel\Annotation\TestResources\PHPGolfNamespace', 'PHPGolfNamespace', array( + 'TestA' => 'Weasel\Annotation\TestResources\TestA', + '' => 'Weasel\Annotation\TestResources', + )), + array('\Weasel\Annotation\TestResourcesToo\PHPGolfNamespaceTwo', 'PHPGolfNamespace', array( + 'TestB' => 'Weasel\Annotation\TestResources\TestB', + '' => 'Weasel\Annotation\TestResourcesToo', + )), + ); + } + + /** + * @dataProvider provideClasses + */ + public function testParse($class, $import, $expected) + { + /** @noinspection PhpIncludeInspection */ + require_once(__DIR__ . '/resources/' . $import . '.php'); + $rClass = new ReflectionClass($class); + $parser = new PhpParser(); + $this->assertEquals($expected, $parser->parseClass($rClass)); + } + +} diff --git a/tests/Weasel/Annotation/TestDocblock.txt b/tests/Weasel/Annotation/TestDocblock.txt new file mode 100644 index 0000000..a952ad2 --- /dev/null +++ b/tests/Weasel/Annotation/TestDocblock.txt @@ -0,0 +1,9 @@ +/** + * This is a test to see how badly the lexer works + * 41411 6665 -1 +5 + * 1.511 -12.5 +0.55 -0 +0 14114e-1 123E55 + * "groats" "I really like ""groats""" + * + * + * + */ \ No newline at end of file diff --git a/tests/Weasel/Annotation/resources/AnnotatedClass.php b/tests/Weasel/Annotation/resources/AnnotatedClass.php new file mode 100644 index 0000000..4324e81 --- /dev/null +++ b/tests/Weasel/Annotation/resources/AnnotatedClass.php @@ -0,0 +1,8 @@ +getReaderForClass($rClass); + $reader->getClassAnnotations(); + } + + /** + * Test what the registered annotation autoloading does when faced with a use with a leading \ + * Must be run in a separate process to ensure the annotation hasn't already been loaded. + * @runInSeparateProcess + */ + public function testAutoloaderWithLeadingSlash() + { + $factory = new DoctrineAnnotationReaderFactory(new AnnotationReader()); + + $rClass = new \ReflectionClass('\Weasel\DoctrineAnnotation\DoctrineAnnotationReaderFactoryTestB\Test'); + + $reader = $factory->getReaderForClass($rClass); + $reader->getClassAnnotations(); + } + + + } +} + +namespace Weasel\DoctrineAnnotation\DoctrineAnnotationReaderFactoryTestA { + use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties; + + /** + * Denotes that there was a problem while accessing the builder service. + * + * @JsonIgnoreProperties() + */ + class Test + { + + } +} + +namespace Weasel\DoctrineAnnotation\DoctrineAnnotationReaderFactoryTestB { + use \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties; + + /** + * Denotes that there was a problem while accessing the builder service. + * + * @JsonIgnoreProperties() + */ + class Test + { + + } +} \ No newline at end of file diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php new file mode 100644 index 0000000..b00c14b --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php @@ -0,0 +1,101 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +use Weasel\Annotation\AnnotationReader; +use Weasel\Annotation\AnnotationConfigurator; +use Weasel\Annotation\Config\Annotations\AnnotationCreator; +use Weasel\Annotation\Config\Annotations\Parameter; + +class JsonCreatorTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonCreator + */ + public function testParseClassAnnotations() + { + + $annotationReader = + new AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonCreator'), new AnnotationConfigurator()); + + $expected = array( + '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("method"), 1)), + ); + + $this->assertEquals($expected, $annotationReader->getClassAnnotations()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonCreator + */ + public function testParsePropertyAnnotations() + { + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonCreator'); + $annotationReader = + new AnnotationReader($rClass, new AnnotationConfigurator()); + + + $found = array(); + foreach ($rClass->getProperties() as $property) { + $name = $property->getName(); + $found[$name] = $annotationReader->getPropertyAnnotations($name); + } + + $this->assertEquals(array("params" => array()), $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonCreator + */ + public function testParseMethodAnnotations() + { + $this->markTestSkipped(); + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonCreator'); + $annotationReader = + new AnnotationReader($rClass, new AnnotationConfigurator()); + + $found = array(); + foreach ($rClass->getMethods() as $method) { + /** + * @var \ReflectionMethod $method + */ + $name = $method->getName(); + if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { + continue; + } + $found[$name] = $annotationReader->getMethodAnnotations($name); + } + + $expected = array("__construct" => + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( + new AnnotationCreator( + array( + new Parameter("params", '\Weasel\JsonMarshaller\Config\Annotations\JsonProperty[]', false), + ) + ) + ) + ), + "getParams" => array(), + ); + + $this->assertEquals($expected, $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonCreator + */ + public function testCreate() + { + $test = new JsonCreator(array()); + $this->assertEmpty($test->getParams()); + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php new file mode 100644 index 0000000..6bb136e --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php @@ -0,0 +1,105 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +class JsonIgnorePropertiesTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties + */ + public function testParseClassAnnotations() + { + $this->markTestSkipped(); + $annotationReader = + new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties'), new \Weasel\Annotation\AnnotationConfigurator()); + + $expected = array( + '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("class"), null)), + ); + + $this->assertEquals($expected, $annotationReader->getClassAnnotations()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties + */ + public function testParsePropertyAnnotations() + { + $this->markTestSkipped(); + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + + $found = array(); + foreach ($rClass->getProperties() as $property) { + $name = $property->getName(); + $found[$name] = $annotationReader->getPropertyAnnotations($name); + } + + $this->assertEquals(array("names" => array(), + "ignoreUnknown" => array() + ), + $found + ); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties + */ + public function testParseMethodAnnotations() + { + $this->markTestSkipped(); + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + $found = array(); + foreach ($rClass->getMethods() as $method) { + /** + * @var \ReflectionMethod $method + */ + $name = $method->getName(); + if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { + continue; + } + $found[$name] = $annotationReader->getMethodAnnotations($name); + } + + $expected = array("__construct" => + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( + new \Weasel\Annotation\Config\Annotations\AnnotationCreator( + array( + new \Weasel\Annotation\Config\Annotations\Parameter("names", 'string[]', false), + new \Weasel\Annotation\Config\Annotations\Parameter("ignoreUnknown", 'boolean', false), + ) + ) + ) + ), + "getNames" => array(), + "getIgnoreUnknown" => array(), + ); + + $this->assertEquals($expected, $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonIgnoreProperties + */ + public function testCreate() + { + $test = new JsonIgnoreProperties(array("test"), true); + $this->assertEquals(array("test"), $test->getNames()); + $this->assertTrue($test->getIgnoreUnknown()); + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php new file mode 100644 index 0000000..5a6606c --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php @@ -0,0 +1,108 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +class JsonIncludeTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonInclude + */ + public function testParseClassAnnotations() + { + + $annotationReader = + new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonInclude'), new \Weasel\Annotation\AnnotationConfigurator()); + + $expected = array( + '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("class", + "method", + "property" + ), 1) + ), + ); + + $this->assertEquals($expected, $annotationReader->getClassAnnotations()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonInclude + */ + public function testParsePropertyAnnotations() + { + $this->markTestSkipped(); + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonInclude'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + + $found = array(); + foreach ($rClass->getProperties() as $property) { + $name = $property->getName(); + $found[$name] = $annotationReader->getPropertyAnnotations($name); + } + + $expectedEnumInclude = new \Weasel\Annotation\Config\Annotations\Enum("Include"); + + $this->assertEquals(array("enumInclude" => array('\Weasel\Annotation\Config\Annotations\Enum' => array($expectedEnumInclude)), + "value" => array() + ), + $found + ); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonInclude + */ + public function testParseMethodAnnotations() + { + $this->markTestSkipped(); + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonInclude'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + $found = array(); + foreach ($rClass->getMethods() as $method) { + /** + * @var \ReflectionMethod $method + */ + $name = $method->getName(); + if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { + continue; + } + $found[$name] = $annotationReader->getMethodAnnotations($name); + } + + $expected = array("__construct" => + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( + new \Weasel\Annotation\Config\Annotations\AnnotationCreator( + array( + new \Weasel\Annotation\Config\Annotations\Parameter("value", 'integer', true), + ) + ) + ) + ), + "getValue" => array(), + ); + + $this->assertEquals($expected, $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonInclude + */ + public function testCreate() + { + $test = new JsonInclude(JsonInclude::$enumInclude["NON_NULL"]); + $this->assertEquals(JsonInclude::$enumInclude["NON_NULL"], $test->getValue()); + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php new file mode 100644 index 0000000..cce2e42 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php @@ -0,0 +1,113 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +class JsonPropertyTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonProperty + */ + public function testParseClassAnnotations() + { + + $annotationReader = + new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonProperty'), new \Weasel\Annotation\AnnotationConfigurator()); + + $expected = array( + '\Weasel\Annotation\Config\Annotations\Annotation' => array( + new \Weasel\Annotation\Config\Annotations\Annotation(array("property", + "method", + '\Weasel\JsonMarshaller\Config\Annotations\JsonCreator' + ), null) + ), + ); + + $this->assertEquals($expected, $annotationReader->getClassAnnotations()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonProperty + */ + public function testParsePropertyAnnotations() + { + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonProperty'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + + $found = array(); + foreach ($rClass->getProperties() as $property) { + $name = $property->getName(); + $found[$name] = $annotationReader->getPropertyAnnotations($name); + } + + $this->assertEquals(array("name" => array(), + "type" => array(), + "strict" => array() + ), + $found + ); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonProperty + */ + public function testParseMethodAnnotations() + { + $this->markTestSkipped(); + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonProperty'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + $found = array(); + foreach ($rClass->getMethods() as $method) { + /** + * @var \ReflectionMethod $method + */ + $name = $method->getName(); + if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { + continue; + } + $found[$name] = $annotationReader->getMethodAnnotations($name); + } + + $expected = array("__construct" => + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( + new \Weasel\Annotation\Config\Annotations\AnnotationCreator( + array( + new \Weasel\Annotation\Config\Annotations\Parameter("name", 'string', false), + new \Weasel\Annotation\Config\Annotations\Parameter("type", 'string', false), + new \Weasel\Annotation\Config\Annotations\Parameter("strict", 'bool', false), + ) + ) + ) + ), + 'getName' => array(), + 'getType' => array(), + 'getStrict' => array(), + ); + + $this->assertEquals($expected, $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonProperty + */ + public function testCreate() + { + $test = new JsonProperty("foo", "bar", true); + $this->assertEquals("foo", $test->getName()); + $this->assertEquals("bar", $test->getType()); + $this->assertEquals(true, $test->getStrict()); + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php new file mode 100644 index 0000000..3b9e889 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php @@ -0,0 +1,104 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes; + +class TypeTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type + */ + public function testParseClassAnnotations() + { + + $annotationReader = + new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type'), new \Weasel\Annotation\AnnotationConfigurator()); + + $expected = array( + '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes'), null)), + ); + + $this->assertEquals($expected, $annotationReader->getClassAnnotations()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type + */ + public function testParsePropertyAnnotations() + { + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + + $found = array(); + foreach ($rClass->getProperties() as $property) { + $name = $property->getName(); + $found[$name] = $annotationReader->getPropertyAnnotations($name); + } + + $this->assertEquals(array("value" => array(), + "name" => array() + ), + $found + ); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type + */ + public function testParseMethodAnnotations() + { + $this->markTestSkipped(); + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + $found = array(); + foreach ($rClass->getMethods() as $method) { + /** + * @var \ReflectionMethod $method + */ + $name = $method->getName(); + if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { + continue; + } + $found[$name] = $annotationReader->getMethodAnnotations($name); + } + + $expected = array("__construct" => + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( + new \Weasel\Annotation\Config\Annotations\AnnotationCreator( + array( + new \Weasel\Annotation\Config\Annotations\Parameter("value", 'string', true), + new \Weasel\Annotation\Config\Annotations\Parameter("name", 'string', false), + ) + ) + ) + ), + "getValue" => array(), + "getName" => array(), + ); + + $this->assertEquals($expected, $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type + */ + public function testCreate() + { + $test = new Type("testValue", "testName"); + $this->assertEquals("testValue", $test->getValue()); + $this->assertEquals("testName", $test->getName()); + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php new file mode 100644 index 0000000..517acba --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php @@ -0,0 +1,103 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +class JsonSubTypesTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes + */ + public function testParseClassAnnotations() + { + $this->markTestSkipped(); + + $annotationReader = + new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes'), new \Weasel\Annotation\AnnotationConfigurator()); + + $expected = array( + '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("class", + "method", + "property" + ), null) + ), + ); + + $this->assertEquals($expected, $annotationReader->getClassAnnotations()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes + */ + public function testParsePropertyAnnotations() + { + $this->markTestSkipped(); + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + + $found = array(); + foreach ($rClass->getProperties() as $property) { + $name = $property->getName(); + $found[$name] = $annotationReader->getPropertyAnnotations($name); + } + + $this->assertEquals(array("value" => array()), $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes + */ + public function testParseMethodAnnotations() + { + $this->markTestSkipped(); + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + $found = array(); + foreach ($rClass->getMethods() as $method) { + /** + * @var \ReflectionMethod $method + */ + $name = $method->getName(); + if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { + continue; + } + $found[$name] = $annotationReader->getMethodAnnotations($name); + } + + $expected = array("__construct" => + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( + new \Weasel\Annotation\Config\Annotations\AnnotationCreator( + array( + new \Weasel\Annotation\Config\Annotations\Parameter("value", '\Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes\Type[]', true), + ) + ) + ) + ), + "getValue" => array(), + ); + + $this->assertEquals($expected, $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes + */ + public function testCreate() + { + $test = new JsonSubTypes(array()); + $this->assertEmpty($test->getValue()); + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php new file mode 100644 index 0000000..b12c964 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php @@ -0,0 +1,126 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +class JsonTypeInfoTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo + */ + public function testParseClassAnnotations() + { + + $annotationReader = + new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo'), new \Weasel\Annotation\AnnotationConfigurator()); + + $expected = array( + '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("class", + "method", + "property" + ), null) + ), + ); + + $this->assertEquals($expected, $annotationReader->getClassAnnotations()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo + */ + public function testParsePropertyAnnotations() + { + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + + $found = array(); + foreach ($rClass->getProperties() as $property) { + $name = $property->getName(); + $found[$name] = $annotationReader->getPropertyAnnotations($name); + } + + $expectedEnumId = new \Weasel\Annotation\Config\Annotations\Enum("Id"); + $expectedEnumAs = new \Weasel\Annotation\Config\Annotations\Enum("As"); + + $this->assertEquals(array("enumId" => array('\Weasel\Annotation\Config\Annotations\Enum' => array($expectedEnumId),), + "enumAs" => array('\Weasel\Annotation\Config\Annotations\Enum' => array($expectedEnumAs),), + "use" => array(), + "include" => array(), + "property" => array(), + "visible" => array(), + "defaultImpl" => array() + ), + $found + ); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo + */ + public function testParseMethodAnnotations() + { + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + $found = array(); + foreach ($rClass->getMethods() as $method) { + /** + * @var \ReflectionMethod $method + */ + $name = $method->getName(); + if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { + continue; + } + $found[$name] = $annotationReader->getMethodAnnotations($name); + } + + $expected = array("__construct" => + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( + new \Weasel\Annotation\Config\Annotations\AnnotationCreator( + array( + new \Weasel\Annotation\Config\Annotations\Parameter("use", 'integer', true), + new \Weasel\Annotation\Config\Annotations\Parameter("include", 'integer', false), + new \Weasel\Annotation\Config\Annotations\Parameter("property", 'string', false), + new \Weasel\Annotation\Config\Annotations\Parameter("visible", 'bool', false), + new \Weasel\Annotation\Config\Annotations\Parameter("defaultImpl", 'string', false), + ) + ) + ) + ), + "getUse" => array(), + "getInclude" => array(), + "getProperty" => array(), + "getVisible" => array(), + "getDefaultImpl" => array(), + + ); + + $this->assertEquals($expected, $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo + */ + public function testCreate() + { + $test = + new JsonTypeInfo(JsonTypeInfo::$enumAs["PROPERTY"], JsonTypeInfo::$enumId["NAME"], "testProp", true, "FooBar"); + $this->assertEquals(JsonTypeInfo::$enumAs["PROPERTY"], $test->getUse()); + $this->assertEquals(JsonTypeInfo::$enumId["NAME"], $test->getInclude()); + $this->assertEquals("testProp", $test->getProperty()); + $this->assertEquals(true, $test->getVisible()); + $this->assertEquals("FooBar", $test->getDefaultImpl()); + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php new file mode 100644 index 0000000..74952c5 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php @@ -0,0 +1,96 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\Annotations; + +class JsonTypeNameTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeName + */ + public function testParseClassAnnotations() + { + + $annotationReader = + new \Weasel\Annotation\AnnotationReader(new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeName'), new \Weasel\Annotation\AnnotationConfigurator()); + + $expected = array( + '\Weasel\Annotation\Config\Annotations\Annotation' => array(new \Weasel\Annotation\Config\Annotations\Annotation(array("class"), null)), + ); + + $this->assertEquals($expected, $annotationReader->getClassAnnotations()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeName + */ + public function testParsePropertyAnnotations() + { + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeName'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + + $found = array(); + foreach ($rClass->getProperties() as $property) { + $name = $property->getName(); + $found[$name] = $annotationReader->getPropertyAnnotations($name); + } + + $this->assertEquals(array("name" => array()), $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeName + */ + public function testParseMethodAnnotations() + { + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeName'); + $annotationReader = + new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); + + $found = array(); + foreach ($rClass->getMethods() as $method) { + /** + * @var \ReflectionMethod $method + */ + $name = $method->getName(); + if (substr($name, 0, 2) === '__' && !($method->isStatic() || $method->isConstructor())) { + continue; + } + $found[$name] = $annotationReader->getMethodAnnotations($name); + } + + $expected = array("__construct" => + array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array( + new \Weasel\Annotation\Config\Annotations\AnnotationCreator( + array( + new \Weasel\Annotation\Config\Annotations\Parameter("name", 'string', true), + ) + ) + ) + ), + "getName" => array(), + ); + + $this->assertEquals($expected, $found); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeName + */ + public function testCreate() + { + $test = new JsonTypeName("testName"); + $this->assertEquals("testName", $test->getName()); + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php b/tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php new file mode 100644 index 0000000..3869f0e --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php @@ -0,0 +1,106 @@ +shouldReceive('getSingleClassAnnotation')->withAnyArgs()->andReturnNull(); + $mockReader->shouldReceive('getSingleMethodAnnotation')->with('getStuff', + '\Weasel\JsonMarshaller\Config\Annotations\JsonProperty')->andReturn( + new JsonProperty(null, "string", null) + ); + $mockReader->shouldReceive('getSingleMethodAnnotation')->with('isGood', + '\Weasel\JsonMarshaller\Config\Annotations\JsonProperty')->andReturn( + new JsonProperty(null, "bool", null) + ); + $mockReader->shouldReceive('getSingleMethodAnnotation')->withAnyArgs()->andReturnNull(); + + $mockReaderFactory = m::mock('\Weasel\Annotation\AnnotationReaderFactory'); + $mockReaderFactory->shouldReceive('getReaderForClass')->with($rClass)->andReturn($mockReader); + + /** + * @var \Weasel\Annotation\AnnotationReaderFactory $mockReaderFactory + */ + $driver = new ClassAnnotationDriver($rClass, $mockReaderFactory); + + $config = $driver->getConfig(); + + $eProperties = array( + "stuff" => new GetterSerialization("getStuff", "string", 1), + "good" => new GetterSerialization("isGood", "bool", 1), + ); + + $this->assertEquals($eProperties, $config->serialization->properties); + } + + /** + * @covers \Weasel\JsonMarshaller\Config\ClassAnnotationDriver::_configureGetter + */ + public function testGetterNameIsNoBool() + { + + $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\ClassAnnotationDriverTestClassA'); + + $mockReader = m::mock('\Weasel\Common\Annotation\IAnnotationReader'); + $mockReader->shouldReceive('getSingleClassAnnotation')->withAnyArgs()->andReturnNull(); + $mockReader->shouldReceive('getSingleMethodAnnotation')->with('getStuff', + '\Weasel\JsonMarshaller\Config\Annotations\JsonProperty')->andReturn( + new JsonProperty(null, "string", null) + ); + $mockReader->shouldReceive('getSingleMethodAnnotation')->with('isGood', + '\Weasel\JsonMarshaller\Config\Annotations\JsonProperty')->andReturn( + new JsonProperty(null, "string", null) + ); + $mockReader->shouldReceive('getSingleMethodAnnotation')->withAnyArgs()->andReturnNull(); + + $mockReaderFactory = m::mock('\Weasel\Annotation\AnnotationReaderFactory'); + $mockReaderFactory->shouldReceive('getReaderForClass')->with($rClass)->andReturn($mockReader); + + /** + * @var \Weasel\Annotation\AnnotationReaderFactory $mockReaderFactory + */ + $driver = new ClassAnnotationDriver($rClass, $mockReaderFactory); + + $config = $driver->getConfig(); + + $eProperties = array( + "stuff" => new GetterSerialization("getStuff", "string", 1), + "isGood" => new GetterSerialization("isGood", "string", 1), + ); + + $this->assertEquals($eProperties, $config->serialization->properties); + + } + +} + +class ClassAnnotationDriverTestClassA +{ + + public function getStuff() + { + + } + + public function isGood() + { + + } + +} diff --git a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetterTest.php b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetterTest.php new file mode 100644 index 0000000..ab51669 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetterTest.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\AnnotationReader; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonAnyGetter; +use Doctrine\Common\Annotations\AnnotationRegistry; + +class JsonAnyGetterTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonAnyGetter + */ + public function testBasicClassAnnotations() + { + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnyGetter.php'); + + $annotationReader = new AnnotationReader(); + $got = $annotationReader->getMethodAnnotations(new \ReflectionMethod(__NAMESPACE__ . '\JsonAnyGetterTestVictim', 'basic')); + + $this->assertEquals(array( + new JsonAnyGetter() + ), + $got); + + } + +} + +class JsonAnyGetterTestVictim +{ + + /** + * @JsonAnyGetter + */ + public static function basic() + { + + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetterTest.php b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetterTest.php new file mode 100644 index 0000000..fd9c8d2 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetterTest.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\AnnotationReader; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonAnySetter; +use Doctrine\Common\Annotations\AnnotationRegistry; + +class JsonAnySetterTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonAnySetter + */ + public function testBasicClassAnnotations() + { + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonAnySetter.php'); + + $annotationReader = new AnnotationReader(); + $got = $annotationReader->getMethodAnnotations(new \ReflectionMethod(__NAMESPACE__ . '\JsonAnySetterTestVictim', 'basic')); + + $this->assertEquals(array( + new JsonAnySetter() + ), + $got); + + } + +} + +class JsonAnySetterTestVictim +{ + + /** + * @JsonAnySetter + */ + public static function basic() + { + + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreatorTest.php b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreatorTest.php new file mode 100644 index 0000000..8ea3ca2 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreatorTest.php @@ -0,0 +1,106 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\AnnotationReader; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonCreator; +use Doctrine\Common\Annotations\AnnotationRegistry; + +class JsonCreatorTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonCreator + */ + public function testBasicClassAnnotations() + { + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php'); + + $annotationReader = new AnnotationReader(); + $got = $annotationReader->getMethodAnnotations(new \ReflectionMethod(__NAMESPACE__ . '\JsonCreatorTestVictim', 'basic')); + + $this->assertEquals(array( + new JsonCreator(array()) + ), + $got); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonCreator + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty + */ + public function testComplexClassAnnotations() + { + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php'); + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php'); + + $annotationReader = new AnnotationReader(); + $got = $annotationReader->getMethodAnnotations(new \ReflectionMethod(__NAMESPACE__ . '\JsonCreatorTestVictim', 'complex')); + + $this->assertEquals(array( + new JsonCreator(array("params" => array( + new JsonProperty(array("name" => "foo", "type" => "int")), + new JsonProperty(array("name" => "bar", "type" => "int")), + ))) + ), + $got); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonCreator + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty + */ + public function testConstructorClassAnnotations() + { + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonCreator.php'); + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonProperty.php'); + + $annotationReader = new AnnotationReader(); + $got = $annotationReader->getMethodAnnotations(new \ReflectionMethod(__NAMESPACE__ . '\JsonCreatorTestVictim', '__construct')); + + $this->assertEquals(array( + new JsonCreator(array("params" => array( + new JsonProperty(array("name" => "foo", "type" => "int")), + new JsonProperty(array("name" => "bar", "type" => "int")), + ))) + ), + $got); + + } + +} + +class JsonCreatorTestVictim +{ + + /** + * @JsonCreator + */ + public static function basic() + { + + } + + /** + * @JsonCreator({@JsonProperty(name="foo", type="int"), @JsonProperty(name="bar", type="int")}) + */ + public static function complex() + { + + } + + + /** + * @JsonCreator(params={@JsonProperty(name="foo", type="int"), @JsonProperty(name="bar", type="int")}) + */ + public function __construct() + { + + } +} diff --git a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnorePropertiesTest.php b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnorePropertiesTest.php new file mode 100644 index 0000000..234bd52 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnorePropertiesTest.php @@ -0,0 +1,114 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\AnnotationReader; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties; +use Doctrine\Common\Annotations\AnnotationRegistry; + +class JsonIgnorePropertiesTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties + */ + public function testBasicUsage() + { + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php'); + + $annotationReader = new AnnotationReader(); + $got = $annotationReader->getClassAnnotation(new \ReflectionClass(__NAMESPACE__ . '\JsonIgnorePropertiesTestVictimA'), + __NAMESPACE__ . '\JsonIgnoreProperties'); + + $this->assertInstanceOf(__NAMESPACE__ . '\JsonIgnoreProperties', $got); + $this->assertEquals(array("blork"), $got->getNames()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties + */ + public function testListUsage() + { + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php'); + + $annotationReader = new AnnotationReader(); + $got = $annotationReader->getClassAnnotation(new \ReflectionClass(__NAMESPACE__ . '\JsonIgnorePropertiesTestVictimB'), + __NAMESPACE__ . '\JsonIgnoreProperties'); + + $this->assertInstanceOf(__NAMESPACE__ . '\JsonIgnoreProperties', $got); + $this->assertEquals(array("blork", "blark"), $got->getNames()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties + */ + public function testNamedListUsage() + { + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php'); + + $annotationReader = new AnnotationReader(); + $got = $annotationReader->getClassAnnotation(new \ReflectionClass(__NAMESPACE__ . '\JsonIgnorePropertiesTestVictimC'), + __NAMESPACE__ . '\JsonIgnoreProperties'); + + $this->assertInstanceOf(__NAMESPACE__ . '\JsonIgnoreProperties', $got); + $this->assertEquals(array("blork", "blark"), $got->getNames()); + + } + + /** + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonIgnoreProperties + */ + public function testIgnoreUsage() + { + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIgnoreProperties.php'); + + $annotationReader = new AnnotationReader(); + $got = $annotationReader->getClassAnnotation(new \ReflectionClass(__NAMESPACE__ . '\JsonIgnorePropertiesTestVictimD'), + __NAMESPACE__ . '\JsonIgnoreProperties'); + + $this->assertInstanceOf(__NAMESPACE__ . '\JsonIgnoreProperties', $got); + $this->assertEquals(array(), $got->getNames()); + $this->assertTrue($got->getIgnoreUnknown()); + + } +} + +/** + * @JsonIgnoreProperties("blork") + */ +class JsonIgnorePropertiesTestVictimA +{ + +} + +/** + * @JsonIgnoreProperties({"blork", "blark"}) + */ +class JsonIgnorePropertiesTestVictimB +{ + +} + +/** + * @JsonIgnoreProperties(names={"blork", "blark"}) + */ +class JsonIgnorePropertiesTestVictimC +{ + +} + + +/** + * @JsonIgnoreProperties(ignoreUnknown=true) + */ +class JsonIgnorePropertiesTestVictimD +{ + +} + diff --git a/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIncludeTest.php b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIncludeTest.php new file mode 100644 index 0000000..1530418 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonIncludeTest.php @@ -0,0 +1,38 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Config\DoctrineAnnotations; + +use Doctrine\Common\Annotations\AnnotationReader; +use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude; +use Doctrine\Common\Annotations\AnnotationRegistry; + +class JsonIncludeTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers \Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonInclude + */ + public function testBasic() + { + AnnotationRegistry::registerFile(__DIR__ . '/../../../../../lib/Weasel/JsonMarshaller/Config/DoctrineAnnotations/JsonInclude.php'); + + $annotationReader = new AnnotationReader(); + $got = $annotationReader->getClassAnnotation(new \ReflectionClass(__NAMESPACE__ . '\JsonIncludeTestVictim'), + __NAMESPACE__ . '\JsonInclude'); + + $this->assertInstanceOf(__NAMESPACE__ . '\JsonInclude', $got); + $this->assertEquals(JsonInclude::INCLUDE_ALWAYS, $got->getValue()); + + } +} + +/** + * @JsonInclude(JsonInclude::INCLUDE_ALWAYS) + */ +class JsonIncludeTestVictim +{ + +} diff --git a/tests/Weasel/JsonMarshaller/JsonMapperTest.php b/tests/Weasel/JsonMarshaller/JsonMapperTest.php new file mode 100644 index 0000000..b45864f --- /dev/null +++ b/tests/Weasel/JsonMarshaller/JsonMapperTest.php @@ -0,0 +1,802 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller; + +use Weasel\JsonMarshaller\Config\JsonConfigProvider; + +class JsonMapperTest extends \PHPUnit_Framework_TestCase +{ + + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testReadStringBasicObject() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->readString(json_encode(array( + "blah" => "foo" + ) + ), + $mtc + ); + + $this->assertInstanceOf($mtc, $result); + $this->assertEquals(new MockTestClass("foo"), $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testChangeStrictDefault() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider, false); + + $result = $mapper->readString(json_encode(array( + "blah" => 1.0 + ) + ), + $mtc + ); + + $this->assertInstanceOf($mtc, $result); + $this->assertEquals(new MockTestClass("1"), $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testReadStringNull() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->readString(json_encode(null), + $mtc + ); + $this->assertEquals(null, $result); + + $result = $mapper->readString("", + $mtc + ); + + $this->assertEquals(null, $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testReadStringPrimitive() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->readString(json_encode("foo"), "string"); + + $this->assertInternalType("string", $result); + $this->assertEquals("foo", $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testReadStringArrayPrimitive() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->readString(json_encode(array("foo", "bar", "baz")), "string[]"); + + $this->assertInternalType("array", $result); + $this->assertEquals(array("foo", "bar", "baz"), $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testReadStringMapPrimitive() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->readString(json_encode(array("a" => 123, "b" => 34, "c" => 99)), "int[string]"); + + $this->assertInternalType("array", $result); + $this->assertEquals(array("a" => 123, "b" => 34, "c" => 99), $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testReadStringMapIntKeys() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->readString('{"77": 123, "33": 34, "22": 99}', "int[int]"); + + $this->assertInternalType("array", $result); + $this->assertEquals(array(77 => 123, 33 => 34, 22 => 99), $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testReadStringArrayOfBasicObject() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->readString(json_encode( + array( + array( + "blah" => "foo" + ), + array( + "blah" => "bar" + ), + array( + "blah" => "baz" + ), + ) + ), + $mtc . '[]' + ); + + $this->assertInternalType("array", $result); + $this->assertEquals(array(new MockTestClass("foo"), new MockTestClass("bar"), new MockTestClass("baz")), + $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testWriteStringBasicObject() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->writeArray(new MockTestClass("foo")); + + $this->assertEquals(array("blah" => "foo"), $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testWriteStringPrimitive() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->writeArray("blah"); + + $this->assertEquals("blah", $result); + } + + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testWriteStringArrayPrimitive() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->writeString(array("foo", "bar", "baz"), 'string[]'); + + $this->assertEquals('["foo", "bar", "baz"]', $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testWriteStringMapPrimitive() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->writeArray(array("a" => 123, "b" => 34, "c" => 99), 'int[string]'); + + $this->assertInternalType("array", $result); + $this->assertEquals(array("a" => 123, "b" => 34, "c" => 99), $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testWriteStringMapIntKeys() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->writeString(array(77 => 123, 42 => 34, 99 => 99), 'int[int]'); + + $expected = '{"77": 123, "42": 34, "99": 99}'; + + $this->assertEquals($expected, $result); + } + + /** + * Test to show that something that PHP would normally think is an "array" gets encoded as a map when we ask for that. + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testWriteStringMapIntKeysLooksLikeArray() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->writeString(array(123, 34, 99), 'int[int]'); + + $expected = '{"0": 123, "1": 34, "2": 99}'; + + $this->assertEquals($expected, $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testWriteStringArrayOfBasicObject() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->writeArray( + array( + new MockTestClass("foo"), + new MockTestClass("bar"), + new MockTestClass("baz"), + ), + $mtc . '[]' + ); + + $this->assertEquals(array(array("blah" => "foo"), array("blah" => "bar"), array("blah" => "baz")), $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testReadArrayOfBasicObject() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "blah", "string"); + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->readArray(json_encode( + array( + array( + "blah" => "foo" + ), + array( + "blah" => "bar" + ), + array( + "blah" => "baz" + ), + ) + ), + $mtc + ); + + $this->assertInternalType("array", $result); + $this->assertEquals(array(new MockTestClass("foo"), new MockTestClass("bar"), new MockTestClass("baz")), + $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testAnySetter() + { + + + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $config->deserialization = new Config\Deserialization\ClassDeserialization(); + $config->deserialization->anySetter = "anySetter"; + + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $result = $mapper->readString(json_encode(array( + "cows" => "blork", + ) + ), + $mtc + ); + + $this->assertInstanceOf($mtc, $result); + $this->assertEquals(array("cows" => "blork"), $result->any); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testAnyGetter() + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + + $config = new Config\ClassMarshaller(); + $config->serialization = new Config\Serialization\ClassSerialization(); + $config->serialization->anyGetter = "anyGetter"; + + $configProvider->fakeConfig[$mtc] = $config; + + $mapper = new JsonMapper($configProvider); + + $object = new MockTestClass(); + $object->any = array("cows" => "blork"); + + $result = $mapper->writeArray($object); + $this->assertInternalType("array", $result); + $this->assertEquals(array("cows" => "blork"), $result); + } + + protected function addPropConfig(Config\ClassMarshaller $config, $name, $type) + { + $prop = new Config\Serialization\DirectSerialization(); + $prop->type = $type; + $prop->property = $name; + $config->serialization->properties[$name] = $prop; + + $prop = new Config\Deserialization\DirectDeserialization(); + $prop->type = $type; + $prop->property = $name; + $config->deserialization->properties[$name] = $prop; + + return $config; + } + + /** + * Build a handy configuration for testing object inheritance using TypeInfo. + * + * @param string $typeInfoAs A string containing the name of one of the TypeInfo TI_AS_ constants. + * @param string $typeInfoUse A string containing the name of one of the TypeInfo TI_USE_ constants. + * @return MockedConfigProvider A config provider with a useful config for testing TypeInfo. + */ + protected function buildTypeInfoTestConfig($typeInfoAs, $typeInfoUse = "TI_USE_CLASS") + { + $configProvider = new MockedConfigProvider(); + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + $mtcb = 'Weasel\JsonMarshaller\MockTestClassB'; + $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; + $mtcd = 'Weasel\JsonMarshaller\MockTestClassD'; + + $config = new Config\ClassMarshaller(); + $config->serialization->typeInfo = new Config\Serialization\TypeInfo(); + $config->serialization->typeInfo->typeInfoAs = constant('\Weasel\JsonMarshaller\Config\Serialization\TypeInfo::' . $typeInfoAs); + $config->serialization->typeInfo->typeInfo = constant('\Weasel\JsonMarshaller\Config\Serialization\TypeInfo::' . $typeInfoUse); + $config->serialization->typeInfo->typeInfoProperty = "type"; + $config->serialization->typeInfo->subTypes[$mtcc] = $mtcc; + $config->serialization->typeInfo->subTypes[$mtcd] = $mtcd; + $config->deserialization->typeInfo = new Config\Deserialization\TypeInfo(); + $config->deserialization->typeInfo->typeInfoAs = constant('\Weasel\JsonMarshaller\Config\Deserialization\TypeInfo::' . $typeInfoAs); + $config->deserialization->typeInfo->typeInfo = constant('\Weasel\JsonMarshaller\Config\Deserialization\TypeInfo::' . $typeInfoUse); + $config->deserialization->typeInfo->typeInfoProperty = "type"; + $config->deserialization->typeInfo->subTypes[$mtcc] = $mtcc; + $config->deserialization->typeInfo->subTypes[$mtcd] = $mtcd; + $configProvider->fakeConfig[$mtcb] = $config; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "hi", "string"); + $configProvider->fakeConfig[$mtcc] = $config; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, "bi", "string"); + $configProvider->fakeConfig[$mtcd] = $config; + + $config = new Config\ClassMarshaller(); + $this->addPropConfig($config, 'blah', $mtcb); + $configProvider->fakeConfig[$mtc] = $config; + + return $configProvider; + + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testEncodeWrapperObject() + { + $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; + + $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_WRAPPER_OBJECT')); + + $object = new MockTestClass(); + $object->blah = new MockTestClassC("dog"); + + $expected = array( + "blah" => + array($mtcc => array("hi" => "dog")) + ); + $result = $mapper->writeArray($object); + $this->assertInternalType("array", $result); + $this->assertEquals($expected, $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testEncodeWrapperArray() + { + $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; + + $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_WRAPPER_ARRAY')); + + $object = new MockTestClass(); + $object->blah = new MockTestClassC("dog"); + + $expected = array( + "blah" => array( + $mtcc, + array("hi" => "dog") + ) + ); + $result = $mapper->writeArray($object); + $this->assertInternalType("array", $result); + $this->assertEquals($expected, $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testEncodeTypeinfoAsPropertyInArray() + { + $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; + $mtcd = 'Weasel\JsonMarshaller\MockTestClassD'; + + $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_PROPERTY')); + + $input = array(); + $arr = array(); + $object = new MockTestClass(); + $object->blah = new MockTestClassC("dog"); + $arr[] = $object; + $object = new MockTestClass(); + $object->blah = new MockTestClassD("car"); + $arr[] = $object; + $input[] = $arr; + $arr = array(); + $object = new MockTestClass(); + $object->blah = new MockTestClassD("wobble"); + $arr[] = $object; + $input[] = $arr; + $input[] = array(); + + $expected = array( + array( + array( + "blah" => array( + "hi" => "dog", + "type" => $mtcc, + ) + ), + array( + "blah" => array( + "bi" => "car", + "type" => $mtcd, + ) + ) + ), + array( + array( + "blah" => array( + "bi" => "wobble", + "type" => $mtcd, + ) + ), + ), + array() + ); + $result = $mapper->writeArray($input, $mtcc . '[][]'); + $this->assertEquals($expected, $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testEncodeTypeinfoAsProperty() + { + $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; + + $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_PROPERTY')); + + $object = new MockTestClass(); + $object->blah = new MockTestClassC("dog"); + + $expected = array( + "blah" => array( + "type" => $mtcc, + "hi" => "dog" + ) + ); + $result = $mapper->writeArray($object); + $this->assertInternalType("array", $result); + $this->assertEquals($expected, $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testDecodeTypeinfoAsProperty() + { + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; + + $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_PROPERTY')); + + $json = json_encode(array( + "blah" => array( + "type" => $mtcc, + "hi" => "dog" + ) + )); + + $expected = new MockTestClass(); + $expected->blah = new MockTestClassC("dog"); + + $result = $mapper->readString($json, $mtc); + $this->assertEquals($expected, $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testDecodeTypeinfoAsWrapperObject() + { + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; + + $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_WRAPPER_OBJECT')); + + $json = json_encode(array( + "blah" => array( + "$mtcc" => array("hi" => "dog") + ) + )); + + $expected = new MockTestClass(); + $expected->blah = new MockTestClassC("dog"); + + $result = $mapper->readString($json, $mtc); + $this->assertEquals($expected, $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + */ + public function testDecodeTypeinfoAsWrapperArray() + { + $mtc = 'Weasel\JsonMarshaller\MockTestClass'; + $mtcc = 'Weasel\JsonMarshaller\MockTestClassC'; + + $mapper = new JsonMapper($this->buildTypeInfoTestConfig('TI_AS_WRAPPER_ARRAY')); + + $json = json_encode(array( + "blah" => array( + $mtcc, + array("hi" => "dog") + ) + )); + + $expected = new MockTestClass(); + $expected->blah = new MockTestClassC("dog"); + + $result = $mapper->readString($json, $mtc); + $this->assertEquals($expected, $result); + } + + /** + * @covers \Weasel\JsonMarshaller\JsonMapper + * @expectedException \Weasel\JsonMarshaller\Exception\BadConfigurationException + * @expectedExceptionMessage is not an instantiable class + */ + public function testBadSubtypeOfInterface() + { + $configProvider = new MockedConfigProvider(); + $mti = 'Weasel\JsonMarshaller\MockTestInterface'; + + $config = new Config\ClassMarshaller(); + + $configProvider->fakeConfig[$mti] = $config; + + $mapper = new JsonMapper($configProvider); + + $mapper->readString(json_encode(array( + "blah" => "foo" + ) + ), + $mti + ); + + } + +} + +interface MockTestInterface +{ + +} + +class MockTestClass implements MockTestInterface +{ + public $any = array(); + + public $blah; + + public function anyGetter() + { + return $this->any; + } + + public function anySetter($key, $value) + { + $this->any[$key] = $value; + } + + public function __construct($blah = null) + { + $this->blah = $blah; + } +} + +class MockTestClassB +{ +} + +class MockTestClassC extends MockTestClassB +{ + public $hi; + + public function __construct($hi = "cat") + { + $this->hi = $hi; + } + +} + +class MockTestClassD extends MockTestClassB +{ + public $bi; + + public function __construct($bi = "stoat") + { + $this->bi = $bi; + } + +} + +class MockedConfigProvider implements JsonConfigProvider +{ + + /** + * @var Config\ClassMarshaller[] + */ + public $fakeConfig = array(); + + /** + * Obtain the config for a named class + * @param string $class The class to get the config for + * @throws \ReflectionException + * @return \Weasel\JsonMarshaller\Config\ClassMarshaller The config, or null if not found + */ + public function getConfig($class) + { + if (isset($this->fakeConfig[$class])) { + return $this->fakeConfig[$class]; + } + return null; + + } + + public function setCache($cache) + { + // TODO: Implement setCache() method. + } +} \ No newline at end of file diff --git a/tests/Weasel/JsonMarshaller/Types/BoolTypeTest.php b/tests/Weasel/JsonMarshaller/Types/BoolTypeTest.php new file mode 100644 index 0000000..e38530e --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Types/BoolTypeTest.php @@ -0,0 +1,139 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; + +use Weasel\JsonMarshaller\Exception\InvalidTypeException; +use Weasel\WeaselDefaultAnnotationDrivenFactory; + +class BoolTypeTest extends \PHPUnit_Framework_TestCase +{ + + + public function provideDataForEncode() + { + return array( + array(true, "true"), + array(false, "false") + ); + } + + protected $_mapper; + + protected function setUp() + { + parent::setUp(); + $factory = new WeaselDefaultAnnotationDrivenFactory(); + $this->_mapper = $factory->getJsonMapperInstance(); + } + + + /** + * @dataProvider provideDataForEncode + * @covers \Weasel\JsonMarshaller\Types\BoolType + */ + public function testEncodeBool($value, $expected) + { + + $handler = new BoolType(); + + $encoded = + $handler->encodeValue($value, + $this->_mapper + ); + + $this->assertInternalType("string", $encoded); + $this->assertEquals($expected, $encoded); + + } + + public function provideDataForDecode() + { + return array( + array(true, + true + ), + array(false, + false + ), + array("true", + true + ), + array("false", + false + ), + array(1, + true + ), + array(0, + false + ) + ); + } + + /** + * @dataProvider provideDataForDecode + * @covers \Weasel\JsonMarshaller\Types\BoolType + */ + public function testDecodeBool($value, $expected) + { + $handler = new BoolType(); + + $encoded = + $handler->decodeValue($value, + $this->_mapper, + true + ); + + $this->assertInternalType("bool", $encoded); + $this->assertEquals($expected, $encoded); + } + + public function provideBrokenDataForEncode() + { + return array_map(function ($a) { + return array($a); + }, + array( + "hi mum!", + "f00ff0f0abc", + "0xzz", + 7, + null + ) + ); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\BoolType + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotABoolEncode($value) + { + $handler = new BoolType(); + $handler->encodeValue($value, + $this->_mapper + ); + $this->fail("Should not get here"); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\BoolType + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotABoolDecode($value) + { + $handler = new BoolType(); + $handler->decodeValue($value, + $this->_mapper, + true + ); + $this->fail("Should not get here"); + } + +} diff --git a/tests/Weasel/JsonMarshaller/Types/DateTimeTypeTest.php b/tests/Weasel/JsonMarshaller/Types/DateTimeTypeTest.php new file mode 100644 index 0000000..f96a2db --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Types/DateTimeTypeTest.php @@ -0,0 +1,138 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; + +use Weasel\JsonMarshaller\Exception\InvalidTypeException; +use Weasel\WeaselDefaultAnnotationDrivenFactory; + +class DateTimeTypeTest extends \PHPUnit_Framework_TestCase +{ + + public function provideDataForEncode() + { + return array( + array(new \DateTime("2012-11-12 12:12:12", new \DateTimeZone("UTC")), + '"2012-11-12T12:12:12+0000"' + ), + ); + } + + protected $_mapper; + + protected function setUp() + { + parent::setUp(); + $factory = new WeaselDefaultAnnotationDrivenFactory(); + $this->_mapper = $factory->getJsonMapperInstance(); + } + + /** + * @dataProvider provideDataForEncode + * @covers \Weasel\JsonMarshaller\Types\DateTimeType + */ + public function testEncodeDateTime($value, $expected) + { + + $handler = new DateTimeType(); + + $encoded = + $handler->encodeValue($value, + $this->_mapper + ); + + $this->assertInternalType("string", $encoded); + $this->assertEquals($expected, $encoded); + + } + + public function provideDataForDecode() + { + return array( + array("2012-11-12T12:12:12+0000", + new \DateTime("2012-11-12 12:12:12", new \DateTimeZone("UTC")) + ), + ); + } + + /** + * @dataProvider provideDataForDecode + * @covers \Weasel\JsonMarshaller\Types\DateTimeType + * @param string $value + * @param \DateTime $expected + * @return void + */ + public function testDecodeDateTime($value, \DateTime $expected) + { + $handler = new DateTimeType(); + + $encoded = + $handler->decodeValue($value, + $this->_mapper, + true + ); + + $this->assertInstanceOf('\DateTime', $encoded); + $this->assertEquals($expected->format("U"), $encoded->format("U")); + } + + public function provideBrokenDataForEncode() + { + return array_map(function ($a) { + return array($a); + }, + array( + null, + 1, + "foo" + ) + ); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\DateTimeType + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotADateTimeEncode($value) + { + $handler = new DateTimeType(); + $handler->encodeValue($value, + $this->_mapper + ); + $this->fail("Should not get here"); + } + + public function provideBrokenDataForDecode() + { + return array_map(function ($a) { + return array($a); + }, + array( + null, + 1, + "foo", + "2012-01-02 11:11:11" + ) + ); + } + + /** + * @dataProvider provideBrokenDataForDecode + * @covers \Weasel\JsonMarshaller\Types\DateTimeType + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotADateTimeDecode($value) + { + $handler = new DateTimeType(); + $handler->decodeValue($value, + $this->_mapper, + true + ); + $this->fail("Should not get here"); + } + +} diff --git a/tests/Weasel/JsonMarshaller/Types/FloatTypeTest.php b/tests/Weasel/JsonMarshaller/Types/FloatTypeTest.php new file mode 100644 index 0000000..a66a0b1 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Types/FloatTypeTest.php @@ -0,0 +1,133 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; + +use Weasel\JsonMarshaller\Exception\InvalidTypeException; +use Weasel\WeaselDefaultAnnotationDrivenFactory; + +class FloatTypeTest extends \PHPUnit_Framework_TestCase +{ + + public function provideDataForEncode() + { + return array( + array(2, '2', true), + array(1.2123123123, '1.2123123123', true), + array(3, '3', true), + array(1e8, '100000000', true), + array(123, '123', false), + array(0xaa, '170', false), + array(1e8, '100000000', false), + ); + } + + protected $_mapper; + + protected function setUp() + { + parent::setUp(); + $factory = new WeaselDefaultAnnotationDrivenFactory(); + $this->_mapper = $factory->getJsonMapperInstance(); + } + + /** + * @dataProvider provideDataForEncode + * @covers \Weasel\JsonMarshaller\Types\FloatType + */ + public function testEncodeFloat($value, $expected) + { + + $handler = new FloatType(); + + $encoded = + $handler->encodeValue($value, + $this->_mapper + ); + + $this->assertInternalType("string", $encoded); + $this->assertEquals($expected, $encoded); + + } + + /** + * @dataProvider provideDataForEncode + * @covers \Weasel\JsonMarshaller\Types\FloatType + */ + public function testDecodeFloat($value, $unused, $strict) + { + $this->markTestSkipped(); + $handler = new FloatType(); + + $encoded = + $handler->decodeValue($value, + $this->_mapper, + false + ); + + $this->assertInternalType("float", $encoded); + $this->assertEquals($value, $encoded); + + try { + $handler->decodeValue($value, + $this->_mapper, + true + ); + if (!$strict) { + $this->fail("This should not have parsed with strict mode on"); + } + $this->assertInternalType("float", $encoded); + $this->assertEquals($value, $encoded); + } catch (InvalidTypeException $e) { + if ($strict) { + $this->fail("This should have parsed with strict mode on"); + } + } + } + + public function provideBrokenDataForEncode() + { + return array_map(function ($a) { + return array($a); + }, + array( + "hi mum!", + "f00ff0f0abc", + "0xzz" + ) + ); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\FloatType + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotAFloatEncode($value) + { + $handler = new FloatType(); + $handler->encodeValue($value, + $this->_mapper + ); + $this->fail("Should not get here"); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\FloatType + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotAFloatDecode($value) + { + $handler = new FloatType(); + $handler->decodeValue($value, + $this->_mapper, + true + ); + $this->fail("Should not get here"); + } + +} diff --git a/tests/Weasel/JsonMarshaller/Types/IntTypeTest.php b/tests/Weasel/JsonMarshaller/Types/IntTypeTest.php new file mode 100644 index 0000000..b5b6967 --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Types/IntTypeTest.php @@ -0,0 +1,138 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; + +use Weasel\JsonMarshaller\Exception\InvalidTypeException; +use Weasel\WeaselDefaultAnnotationDrivenFactory; + +class IntTypeTest extends \PHPUnit_Framework_TestCase +{ + + public function provideDataForEncode() + { + return array( + array(2, '2'), + array(3, '3'), + array("123", '123'), + ); + } + + protected $_mapper; + + protected function setUp() + { + parent::setUp(); + $factory = new WeaselDefaultAnnotationDrivenFactory(); + $this->_mapper = $factory->getJsonMapperInstance(); + } + + /** + * @dataProvider provideDataForEncode + * @covers \Weasel\JsonMarshaller\Types\IntType + */ + public function testEncodeInt($value, $expected) + { + + $handler = new IntType(); + + $encoded = + $handler->encodeValue($value, + $this->_mapper + ); + + $this->assertInternalType("string", $encoded); + $this->assertEquals($expected, $encoded); + + } + + public function provideDataForDecode() + { + return array( + array(2, true), + array(3, true), + array("123", false), + ); + } + + /** + * @dataProvider provideDataForDecode + * @covers \Weasel\JsonMarshaller\Types\IntType + */ + public function testDecodeInt($value, $strict) + { + $handler = new IntType(); + + $encoded = + $handler->decodeValue($value, + $this->_mapper, + false + ); + + $this->assertInternalType("int", $encoded); + $this->assertEquals($value, $encoded); + + try { + $handler->decodeValue($value, + $this->_mapper, + true + ); + if (!$strict) { + $this->fail("This should not have parsed with strict mode on"); + } + $this->assertInternalType("int", $encoded); + $this->assertEquals($value, $encoded); + } catch (InvalidTypeException $e) { + if ($strict) { + $this->fail("This should have parsed with strict mode on"); + } + } + } + + public function provideBrokenDataForEncode() + { + return array_map(function ($a) { + return array($a); + }, + array( + "hi mum!", + "f00ff0f0abc", + "0xzz", + 1.2 + ) + ); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\IntType + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotAIntEncode($value) + { + $handler = new IntType(); + $handler->encodeValue($value, + $this->_mapper + ); + $this->fail("Should not get here"); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\IntType + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotAIntDecode($value) + { + $handler = new IntType(); + $handler->decodeValue($value, + $this->_mapper, + true + ); + $this->fail("Should not get here"); + } + +} diff --git a/tests/Weasel/JsonMarshaller/Types/OldTypeWrapperTest.php b/tests/Weasel/JsonMarshaller/Types/OldTypeWrapperTest.php new file mode 100644 index 0000000..c315f3a --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Types/OldTypeWrapperTest.php @@ -0,0 +1,150 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; + +use Weasel\JsonMarshaller\Exception\InvalidTypeException; +use Weasel\JsonMarshaller\JsonMapper; +use Weasel\WeaselDefaultAnnotationDrivenFactory; + +class OldTypeWrapperTest extends \PHPUnit_Framework_TestCase +{ + + public function provideDataForEncode() + { + return array( + array(2, '2'), + array(3, '3'), + array("123", '123'), + ); + } + + protected $_mapper; + + protected function setUp() + { + parent::setUp(); + $factory = new WeaselDefaultAnnotationDrivenFactory(); + $this->_mapper = $factory->getJsonMapperInstance(); + } + + /** + * @dataProvider provideDataForEncode + * @covers \Weasel\JsonMarshaller\Types\OldTypeWrapper + */ + public function testEncodeInt($value, $expected) + { + + $handler = new OldTypeWrapper(new OldIntType()); + + $encoded = + $handler->encodeValue($value, + $this->_mapper + ); + + $this->assertInternalType("string", $encoded); + $this->assertEquals($expected, $encoded); + + } + + public function provideDataForDecode() + { + return array_map(function ($a) { + return array($a); + }, + array( + 2, + 3, + "123", + ) + ); + } + + /** + * @dataProvider provideDataForDecode + * @covers \Weasel\JsonMarshaller\Types\OldTypeWrapper + */ + public function testDecodeInt($value) + { + $handler = new OldTypeWrapper(new OldIntType()); + + $encoded = + $handler->decodeValue($value, + $this->_mapper, + true + ); + + $this->assertInternalType("int", $encoded); + $this->assertEquals($value, $encoded); + } + + public function provideBrokenDataForEncode() + { + return array_map(function ($a) { + return array($a); + }, + array( + "hi mum!", + "f00ff0f0abc", + "0xzz", + 1.2 + ) + ); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\OldTypeWrapper + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotAIntEncode($value) + { + $handler = new OldTypeWrapper(new OldIntType()); + $handler->encodeValue($value, + $this->_mapper + ); + $this->fail("Should not get here"); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\OldTypeWrapper + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotAIntDecode($value) + { + $handler = new OldTypeWrapper(new OldIntType()); + $handler->decodeValue($value, + $this->_mapper, + true + ); + $this->fail("Should not get here"); + } + +} + +class OldIntType implements Type +{ + + protected function checkAndCastValue($value) + { + if (!is_int($value) && !ctype_digit($value)) { + throw new InvalidTypeException("integer", $value); + } + return (int)$value; + } + + public function decodeValue($value, JsonMapper $mapper) + { + return $this->checkAndCastValue($value); + } + + public function encodeValue($value, JsonMapper $mapper) + { + return $this->checkAndCastValue($value); + } + +} diff --git a/tests/Weasel/JsonMarshaller/Types/StringTypeTest.php b/tests/Weasel/JsonMarshaller/Types/StringTypeTest.php new file mode 100644 index 0000000..690a45c --- /dev/null +++ b/tests/Weasel/JsonMarshaller/Types/StringTypeTest.php @@ -0,0 +1,110 @@ + + * @copyright Copyright (c) 2012, Moo Print Ltd. + * @license ISC + */ +namespace Weasel\JsonMarshaller\Types; + +use Weasel\JsonMarshaller\Exception\InvalidTypeException; +use Weasel\WeaselDefaultAnnotationDrivenFactory; + +class StringTypeTest extends \PHPUnit_Framework_TestCase +{ + + public function provideDataForEncode() + { + return array( + array("foo", '"foo"'), + array("fubar", '"fubar"'), + array('flibble"flobble', '"flibble\"flobble"') + ); + } + + protected $_mapper; + + protected function setUp() + { + parent::setUp(); + $factory = new WeaselDefaultAnnotationDrivenFactory(); + $this->_mapper = $factory->getJsonMapperInstance(); + } + + /** + * @dataProvider provideDataForEncode + * @covers \Weasel\JsonMarshaller\Types\StringType + */ + public function testEncodeString($value, $expected) + { + + $handler = new StringType(); + + $encoded = + $handler->encodeValue($value, + $this->_mapper + ); + + $this->assertInternalType("string", $encoded); + $this->assertEquals($expected, $encoded); + + } + + /** + * @dataProvider provideDataForEncode + * @covers \Weasel\JsonMarshaller\Types\StringType + */ + public function testDecodeString($value) + { + $handler = new StringType(); + + $encoded = + $handler->decodeValue($value, + $this->_mapper, + true + ); + + $this->assertInternalType("string", $encoded); + $this->assertEquals($value, $encoded); + } + + public function provideBrokenDataForEncode() + { + return array( + array(1.2, '"1.2"'), + array(7, '"7"'), + array(false, '""'), + array(true, '"1"'), + array(null, '""') + ); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\StringType + */ + public function testNotAStringEncode($value, $expected) + { + $handler = new StringType(); + $encoded = $handler->encodeValue($value, + $this->_mapper + ); + $this->assertInternalType("string", $encoded); + $this->assertEquals($expected, $encoded); + } + + /** + * @dataProvider provideBrokenDataForEncode + * @covers \Weasel\JsonMarshaller\Types\StringType + * @expectedException \Weasel\JsonMarshaller\Exception\InvalidTypeException + */ + public function testNotAStringDecode($value) + { + $handler = new StringType(); + $handler->decodeValue($value, + $this->_mapper, + true + ); + $this->fail("Should not get here"); + } + +} diff --git a/tests/benchmark.php b/tests/benchmark.php new file mode 100644 index 0000000..bb5cb5a --- /dev/null +++ b/tests/benchmark.php @@ -0,0 +1,21 @@ +getJsonMapperInstance(); +$testString = $weasel->writeString($testData, '\Weasel\JsonMarshaller\Config\ClassMarshaller[string]'); + +$st = microtime(true); +for ($i = 0; $i < 100; $i++) { + $weasel->writeString($testData, '\Weasel\JsonMarshaller\Config\ClassMarshaller[string]'); +} +print "Writes took: " . (microtime(true) - $st) . "ms\n"; + +$st = microtime(true); +for ($i = 0; $i < 100; $i++) { + $weasel->readString($testString, '\Weasel\JsonMarshaller\Config\ClassMarshaller[string]'); +} +print "Reads took: " . (microtime(true) - $st) . "ms\n"; diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..897cde1 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,12 @@ + Date: Mon, 8 Apr 2019 11:23:03 +0100 Subject: [PATCH 3/7] removing old tests --- .../Annotation/AnnotationConfiguratorTest.php | 572 ------------------ 1 file changed, 572 deletions(-) diff --git a/tests/Weasel/Annotation/AnnotationConfiguratorTest.php b/tests/Weasel/Annotation/AnnotationConfiguratorTest.php index dfd8adf..3a84c62 100644 --- a/tests/Weasel/Annotation/AnnotationConfiguratorTest.php +++ b/tests/Weasel/Annotation/AnnotationConfiguratorTest.php @@ -29,578 +29,6 @@ public function testBuiltIns() } - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - */ -// public function testBasicAnnotation() -// { -// -// $annotation = new Config\Annotations\Annotation(['class'], 6); -// $classAnnotations = ['\Weasel\Annotation\Config\Annotations\Annotation' => [$annotation]]; -//// $mock = -//// $this->getMock('\Weasel\Annotation\AnnotationReader', -//// ['getClassAnnotations', -//// 'getMethodAnnotations', -//// 'getPropertyAnnotations' -//// ], [], '', false -//// ); -// -// $mock = $this->createMock('\Weasel\Annotation\AnnotationReader'); -// $mock->expects($this->any())->method('getClassAnnotations') -// ->will($this->returnValue($classAnnotations)); -// $mock->expects($this->any()) -// ->method('getMethodAnnotations') -// ->will($this->returnValueMap([ -// ["__construct", []], ["setA", []], ["getA", []], ["creator", []] -// ]) -// ); -// $mock->expects($this->any()) -// ->method('getPropertyAnnotations') -// ->will($this->returnValue([])); -// -// $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); -// -// $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); -// -// $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', ['class'], 6); -// -// $this->assertEquals($expected, $result); -// -// } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * - public function testCreator() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $constructorParams = array(); - $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); - $constructorParams[] = new Config\Annotations\Parameter("bar", "integer", true); - $constructorParams[] = new Config\Annotations\Parameter(null, "boolean", false); - - $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); - - $constructorAnnotations = - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - $constructorAnnotations - ), - array("setA", - array() - ), - array("getA", - array() - ), - array("creator", - array() - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - $expected->setCreatorMethod('__construct'); - $expected->addCreatorParam(new Config\Param("foo", "string", true)); - $expected->addCreatorParam(new Config\Param("bar", "integer", true)); - $expected->addCreatorParam(new Config\Param("c", "boolean", false)); - - $this->assertEquals($expected, $result, "Got " . print_r($result, true)); - - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * - public function testStaticCreator() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $constructorParams = array(); - $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); - - $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); - - $constructorAnnotations = - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - array() - ), - array("setA", - array() - ), - array("getA", - array() - ), - array("creator", - $constructorAnnotations - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - $expected->setCreatorMethod('creator'); - $expected->addCreatorParam(new Config\Param("foo", "string", true)); - - $this->assertEquals($expected, $result); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * - public function testProperties() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValue(array())); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValueMap(array( - array("a", - array('\Weasel\Annotation\Config\Annotations\Property' => array(new Config\Annotations\Property("string"))), - ), - array("b", - array('\Weasel\Annotation\Config\Annotations\Property' => array(new Config\Annotations\Property("float"))), - ), - ) - ) - ); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - $expected->addProperty(new Config\Property("a", "string")); - $expected->addProperty(new Config\Property("b", "float")); - - $this->assertEquals($expected, $result, "Got " . print_r($result, true)); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * - public function testEnum() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValue(array())); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValueMap(array( - array("a", - array() - ), - array("b", - array() - ), - array("enumTest", - array('\Weasel\Annotation\Config\Annotations\Enum' => array( - new Config\Annotations\Enum("toast") - ) - ) - ) - ) - ) - ); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - $expected->addEnum(new Config\Enum("toast", array("FOO" => 1, - "BAR" => 2 - )) - ); - - $this->assertEquals($expected, $result, "Got " . print_r($result, true)); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * - public function testEnumDefaultName() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValue(array())); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValueMap(array( - array("a", - array() - ), - array("b", - array() - ), - array("enumTest", - array('\Weasel\Annotation\Config\Annotations\Enum' => array( - new Config\Annotations\Enum(null) - ) - ) - ) - ) - ) - ); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $result = $instance->get('\Weasel\Annotation\BoringAnnotation'); - - $expected = new Config\Annotation('\Weasel\Annotation\BoringAnnotation', array('class'), 6); - $expected->addEnum(new Config\Enum("enumTest", array("FOO" => 1, - "BAR" => 2 - )) - ); - - $this->assertEquals($expected, $result, "Got " . print_r($result, true)); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Enums must be static properties - * - public function testNonStaticEnum() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValue(array())); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValueMap(array( - array("a", - array('\Weasel\Annotation\Config\Annotations\Enum' => array( - new Config\Annotations\Enum(null) - ) - ) - ), - ) - ) - ); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Enum must be an array - * - public function testNonArrayEnum() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValue(array())); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValueMap(array( - array("b", - array('\Weasel\Annotation\Config\Annotations\Enum' => array( - new Config\Annotations\Enum(null) - ) - ) - ), - ) - ) - ); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Did not find an @Annotation annotation on - * - public function testThatsNoAnnotation() - { - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue(array())); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - array() - ), - array("setA", - array() - ), - array("getA", - array() - ), - array("creator", - array() - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Non-static methods cannot be configured as creators - * - public function testNonStaticCreatorFail() - { - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $constructorParams = array(); - $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); - - $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); - - $constructorAnnotations = - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - array() - ), - array("setA", - $constructorAnnotations - ), - array("getA", - array() - ), - array("creator", - array() - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Creator args don't match with method args - * - public function testTooManyCreatorArgs() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $constructorParams = array(); - $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); - $constructorParams[] = new Config\Annotations\Parameter("bar", "string", true); - - $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); - - $constructorAnnotations = - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - array() - ), - array("setA", - array() - ), - array("getA", - array() - ), - array("creator", - $constructorAnnotations - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - } - - /** - * @covers \Weasel\Annotation\AnnotationConfigurator - * @expectedException \RuntimeException - * @expectedExceptionMessage Creator args don't match with method args - * - public function testTooFewCreatorArgs() - { - - $annotation = new Config\Annotations\Annotation(array('class'), 6); - $classAnnotations = array('\Weasel\Annotation\Config\Annotations\Annotation' => array($annotation)); - - $constructorParams = array(); - $constructorParams[] = new Config\Annotations\Parameter("foo", "string", true); - $constructorParams[] = new Config\Annotations\Parameter("bar", "string", true); - - $constructorAnnotation = new Config\Annotations\AnnotationCreator($constructorParams); - - $constructorAnnotations = - array('\Weasel\Annotation\Config\Annotations\AnnotationCreator' => array($constructorAnnotation)); - - - $mock = - $this->getMock('\Weasel\Annotation\AnnotationReader', - array('getClassAnnotations', - 'getMethodAnnotations', - 'getPropertyAnnotations' - ), array(), '', false - ); - $mock->expects($this->any())->method('getClassAnnotations')->will($this->returnValue($classAnnotations)); - $mock->expects($this->any())->method('getMethodAnnotations') - ->will($this->returnValueMap(array( - array("__construct", - $constructorAnnotations - ), - array("setA", - array() - ), - array("getA", - array() - ), - array("creator", - array() - ), - ) - ) - ); - $mock->expects($this->any())->method('getPropertyAnnotations') - ->will($this->returnValue(array())); - $instance = new AnnotationConfigurator(null, null, new MockAnnotationReaderFactory($mock)); - - $instance->get('\Weasel\Annotation\BoringAnnotation'); - } */ } class MockAnnotationReaderFactory extends AnnotationReaderFactory From 6ed73752b2f96d07cf0aaeebe61d86e58db80693 Mon Sep 17 00:00:00 2001 From: Rob Aiken Date: Mon, 8 Apr 2019 11:24:46 +0100 Subject: [PATCH 4/7] added back slash --- .../Weasel/Annotation/DocblockParserTest.php | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/Weasel/Annotation/DocblockParserTest.php b/tests/Weasel/Annotation/DocblockParserTest.php index e79d820..ea22cc8 100644 --- a/tests/Weasel/Annotation/DocblockParserTest.php +++ b/tests/Weasel/Annotation/DocblockParserTest.php @@ -58,7 +58,7 @@ public function testSimpleClassAnnotation($value, $type) $parsed = $parser->parse( '/** * @Gloop(foo=' . $valueQuoted . ') - *', + */', "class", array('Gloop' => 'Weasel\Annotation\Tests\Gloop') ); @@ -85,7 +85,7 @@ public function testNoArgsAnnotation() $parsed = $parser->parse( '/** * @Gloop - *', + */', "class", array('Gloop' => 'Weasel\Annotation\Tests\Gloop') ); @@ -112,7 +112,7 @@ public function testTwoAnnotations() '/** * @Gloop * @Gloop - *', + */', "class", array('Gloop' => 'Weasel\Annotation\Tests\Gloop') ); @@ -142,7 +142,7 @@ public function testEmptyArgsAnnotation() $parsed = $parser->parse( '/** * @Gloop() - *', + */', "class", array('Gloop' => 'Weasel\Annotation\Tests\Gloop') ); @@ -168,7 +168,7 @@ public function testFullyNamespacedAnnotation() $parsed = $parser->parse( '/** * @\Weasel\Annotation\Tests\Gloop - *', + */', "class", array() ); @@ -194,7 +194,7 @@ public function testMissingWhitespaceNoArgs() $parsed = $parser->parse( '/** * @\Weasel\Annotation\Tests\Gloop@glarp - *', + */', "class", array() ); @@ -218,7 +218,7 @@ public function testMissingWhitespaceArgs() $parsed = $parser->parse( '/** * @\Weasel\Annotation\Tests\Gloop()@glarp - *', + */', "class", array() ); @@ -243,7 +243,7 @@ public function testArrayClassAnnotation() $parsed = $parser->parse( '/** * @Gloop(foo={{"ab", "cd"}, {"ef"}, {}}) - *', + */', "class", array('Gloop' => 'Weasel\Annotation\Tests\Gloop') ); @@ -277,7 +277,7 @@ public function testArraySingleElementClassAnnotation() $parsed = $parser->parse( '/** * @Gloop(foo="bar") - *', + */', "class", array('Gloop' => 'Weasel\Annotation\Tests\Gloop') ); @@ -314,7 +314,7 @@ public function testNestedClassAnnotation($value, $type) $parsed = $parser->parse( '/** * @Gloop(foo=@Glarp(bar=' . $valueQuoted . ')) - *', + */', "class", array( 'Gloop' => 'Weasel\Annotation\Tests\Gloop', @@ -358,7 +358,7 @@ public function testMultiNestedArgs() * @Multi(a=@Glarp(bar="foo"), b=@Glarp(bar="baa"), c=@Gloop(foo="fnord")) * @Multi(a=@Glarp(bar="foo") , b=@Glarp(bar="baa") , c=@Gloop(foo="fnord")) * @Multi(a=@Glarp(bar="foo"),b=@Glarp(bar="baa"),c=@Gloop(foo="fnord")) - *', + */', "class", array( 'Gloop' => 'Weasel\Annotation\Tests\Gloop', From 64df034873be53cba71906c63311136b1771e2f7 Mon Sep 17 00:00:00 2001 From: Rob Aiken Date: Mon, 8 Apr 2019 11:29:05 +0100 Subject: [PATCH 5/7] fixing composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index fca0bc8..0b7d62a 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "psr/log": "~1.1", "doctrine/annotations": "~1.4", "doctrine/cache": "~1.6", - "symfony/Console": "~3.4|~4.0" + "symfony/console": "~3.4|~4.0" }, "require-dev": { "mockery/mockery": "~1.2", From 7963d7ac34929a42198ddb613408b93531474d86 Mon Sep 17 00:00:00 2001 From: Rob Aiken Date: Mon, 8 Apr 2019 11:44:14 +0100 Subject: [PATCH 6/7] fixing travis script --- .travis.yml | 2 +- .../Config/Annotations/JsonTypeInfoTest.php | 33 ------------------- 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/.travis.yml b/.travis.yml index 09d7bfe..e422c14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,4 @@ php: - "7.0" - "5.6" before_script: composer install -n --dev -script: "phpunit --coverage-text --bootstrap ./tests/bootstrap.php tests" +script: "./vendor/bin/phpunit --coverage-text --bootstrap ./tests/bootstrap.php tests/" diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php index b12c964..cbdb47f 100644 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php @@ -30,39 +30,6 @@ public function testParseClassAnnotations() } - /** - * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo - */ - public function testParsePropertyAnnotations() - { - - $rClass = new \ReflectionClass('\Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo'); - $annotationReader = - new \Weasel\Annotation\AnnotationReader($rClass, new \Weasel\Annotation\AnnotationConfigurator()); - - - $found = array(); - foreach ($rClass->getProperties() as $property) { - $name = $property->getName(); - $found[$name] = $annotationReader->getPropertyAnnotations($name); - } - - $expectedEnumId = new \Weasel\Annotation\Config\Annotations\Enum("Id"); - $expectedEnumAs = new \Weasel\Annotation\Config\Annotations\Enum("As"); - - $this->assertEquals(array("enumId" => array('\Weasel\Annotation\Config\Annotations\Enum' => array($expectedEnumId),), - "enumAs" => array('\Weasel\Annotation\Config\Annotations\Enum' => array($expectedEnumAs),), - "use" => array(), - "include" => array(), - "property" => array(), - "visible" => array(), - "defaultImpl" => array() - ), - $found - ); - - } - /** * @covers \Weasel\JsonMarshaller\Config\Annotations\JsonTypeInfo */ From 1026d31fac042dca22711a68601aaf01c772e96d Mon Sep 17 00:00:00 2001 From: Rob Aiken Date: Mon, 8 Apr 2019 15:28:34 +0100 Subject: [PATCH 7/7] update testcase --- composer.json | 4 ++-- tests/Weasel/Annotation/AnnotationConfiguratorTest.php | 3 ++- tests/Weasel/Annotation/AnnotationReaderTest.php | 3 ++- tests/Weasel/Annotation/DocblockLexerTest.php | 3 ++- tests/Weasel/Annotation/DocblockParserTest.php | 3 ++- tests/Weasel/Annotation/PHPParserTest.php | 4 ++-- .../DoctrineAnnotationReaderFactoryTest.php | 3 ++- .../JsonMarshaller/Config/Annotations/JsonCreatorTest.php | 3 ++- .../Config/Annotations/JsonIgnorePropertiesTest.php | 4 +++- .../JsonMarshaller/Config/Annotations/JsonIncludeTest.php | 4 +++- .../JsonMarshaller/Config/Annotations/JsonPropertyTest.php | 4 +++- .../Config/Annotations/JsonSubTypes/TypeTest.php | 4 +++- .../JsonMarshaller/Config/Annotations/JsonSubTypesTest.php | 4 +++- .../JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php | 4 +++- .../JsonMarshaller/Config/Annotations/JsonTypeNameTest.php | 4 +++- .../JsonMarshaller/Config/ClassAnnotationDriverTest.php | 3 ++- .../Config/DoctrineAnnotations/JsonAnyGetterTest.php | 3 ++- .../Config/DoctrineAnnotations/JsonAnySetterTest.php | 3 ++- .../Config/DoctrineAnnotations/JsonCreatorTest.php | 3 ++- .../Config/DoctrineAnnotations/JsonIgnorePropertiesTest.php | 3 ++- .../Config/DoctrineAnnotations/JsonIncludeTest.php | 3 ++- tests/Weasel/JsonMarshaller/JsonMapperTest.php | 3 ++- tests/Weasel/JsonMarshaller/Types/BoolTypeTest.php | 3 ++- tests/Weasel/JsonMarshaller/Types/DateTimeTypeTest.php | 3 ++- tests/Weasel/JsonMarshaller/Types/FloatTypeTest.php | 3 ++- tests/Weasel/JsonMarshaller/Types/IntTypeTest.php | 3 ++- tests/Weasel/JsonMarshaller/Types/OldTypeWrapperTest.php | 3 ++- tests/Weasel/JsonMarshaller/Types/StringTypeTest.php | 3 ++- 28 files changed, 63 insertions(+), 30 deletions(-) diff --git a/composer.json b/composer.json index 0b7d62a..40e4a6b 100644 --- a/composer.json +++ b/composer.json @@ -10,11 +10,11 @@ "psr/log": "~1.1", "doctrine/annotations": "~1.4", "doctrine/cache": "~1.6", - "symfony/console": "~3.4|~4.0" + "symfony/console": "~3.4" }, "require-dev": { "mockery/mockery": "~1.2", - "phpunit/phpunit": "~5." + "phpunit/phpunit": "~5.7|^6.0|^7.0" }, "suggest": { "monolog/monolog": "A logging framework that implements PSR 3" diff --git a/tests/Weasel/Annotation/AnnotationConfiguratorTest.php b/tests/Weasel/Annotation/AnnotationConfiguratorTest.php index 3a84c62..e64f565 100644 --- a/tests/Weasel/Annotation/AnnotationConfiguratorTest.php +++ b/tests/Weasel/Annotation/AnnotationConfiguratorTest.php @@ -6,10 +6,11 @@ */ namespace Weasel\Annotation; +use PHPUnit\Framework\TestCase; use Weasel\Annotation\AnnotationReaderFactory; use Weasel\Annotation\Config\Annotations\Annotation; -class AnnotationConfiguratorTest extends \PHPUnit_Framework_TestCase +class AnnotationConfiguratorTest extends TestCase { /** diff --git a/tests/Weasel/Annotation/AnnotationReaderTest.php b/tests/Weasel/Annotation/AnnotationReaderTest.php index 5e80b7b..d795999 100644 --- a/tests/Weasel/Annotation/AnnotationReaderTest.php +++ b/tests/Weasel/Annotation/AnnotationReaderTest.php @@ -2,9 +2,10 @@ namespace Weasel\Annotation; use Mockery as m; +use PHPUnit\Framework\TestCase; use Weasel\Annotation\Config\Annotation; -class AnnotationReaderTest extends \PHPUnit_Framework_TestCase { +class AnnotationReaderTest extends TestCase { /** diff --git a/tests/Weasel/Annotation/DocblockLexerTest.php b/tests/Weasel/Annotation/DocblockLexerTest.php index 80d1b30..8ec13f0 100644 --- a/tests/Weasel/Annotation/DocblockLexerTest.php +++ b/tests/Weasel/Annotation/DocblockLexerTest.php @@ -6,9 +6,10 @@ */ namespace Weasel\Annotation\Tests; +use PHPUnit\Framework\TestCase; use Weasel\Annotation\DocblockLexer; -class DocblockLexerTest extends \PHPUnit_Framework_TestCase +class DocblockLexerTest extends TestCase { public function provideSimpleType() diff --git a/tests/Weasel/Annotation/DocblockParserTest.php b/tests/Weasel/Annotation/DocblockParserTest.php index ea22cc8..c50858f 100644 --- a/tests/Weasel/Annotation/DocblockParserTest.php +++ b/tests/Weasel/Annotation/DocblockParserTest.php @@ -6,11 +6,12 @@ */ namespace Weasel\Annotation\Tests; +use PHPUnit\Framework\TestCase; use Weasel\Annotation\DocblockParser; use Weasel\Annotation\AnnotationConfigurator; use Weasel\Annotation\Config\AnnotationConfig; -class DocblockParserTest extends \PHPUnit_Framework_TestCase +class DocblockParserTest extends TestCase { public function provideSimpleClassAnnotation() diff --git a/tests/Weasel/Annotation/PHPParserTest.php b/tests/Weasel/Annotation/PHPParserTest.php index e52685a..9d76b00 100644 --- a/tests/Weasel/Annotation/PHPParserTest.php +++ b/tests/Weasel/Annotation/PHPParserTest.php @@ -6,10 +6,10 @@ * @license ISC */ +use PHPUnit\Framework\TestCase; use ReflectionClass; -use PHPUnit_Framework_TestCase; -class PHPParserTest extends PHPUnit_Framework_TestCase +class PHPParserTest extends TestCase { diff --git a/tests/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactoryTest.php b/tests/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactoryTest.php index 19d46e4..232197c 100644 --- a/tests/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactoryTest.php +++ b/tests/Weasel/DoctrineAnnotation/DoctrineAnnotationReaderFactoryTest.php @@ -9,8 +9,9 @@ namespace Weasel\DoctrineAnnotation { use Doctrine\Common\Annotations\AnnotationReader; + use PHPUnit\Framework\TestCase; - class DoctrineAnnotationReaderFactoryTest extends \PHPUnit_Framework_TestCase + class DoctrineAnnotationReaderFactoryTest extends TestCase { /** diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php index b00c14b..1fea6b2 100644 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonCreatorTest.php @@ -6,12 +6,13 @@ */ namespace Weasel\JsonMarshaller\Config\Annotations; +use PHPUnit\Framework\TestCase; use Weasel\Annotation\AnnotationReader; use Weasel\Annotation\AnnotationConfigurator; use Weasel\Annotation\Config\Annotations\AnnotationCreator; use Weasel\Annotation\Config\Annotations\Parameter; -class JsonCreatorTest extends \PHPUnit_Framework_TestCase +class JsonCreatorTest extends TestCase { /** diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php index 6bb136e..6764469 100644 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIgnorePropertiesTest.php @@ -6,7 +6,9 @@ */ namespace Weasel\JsonMarshaller\Config\Annotations; -class JsonIgnorePropertiesTest extends \PHPUnit_Framework_TestCase +use PHPUnit\Framework\TestCase; + +class JsonIgnorePropertiesTest extends TestCase { /** diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php index 5a6606c..9ef60c7 100644 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonIncludeTest.php @@ -6,7 +6,9 @@ */ namespace Weasel\JsonMarshaller\Config\Annotations; -class JsonIncludeTest extends \PHPUnit_Framework_TestCase +use PHPUnit\Framework\TestCase; + +class JsonIncludeTest extends TestCase { /** diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php index cce2e42..598d3fd 100644 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonPropertyTest.php @@ -6,7 +6,9 @@ */ namespace Weasel\JsonMarshaller\Config\Annotations; -class JsonPropertyTest extends \PHPUnit_Framework_TestCase +use PHPUnit\Framework\TestCase; + +class JsonPropertyTest extends TestCase { /** diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php index 3b9e889..806afae 100644 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypes/TypeTest.php @@ -6,7 +6,9 @@ */ namespace Weasel\JsonMarshaller\Config\Annotations\JsonSubTypes; -class TypeTest extends \PHPUnit_Framework_TestCase +use PHPUnit\Framework\TestCase; + +class TypeTest extends TestCase { /** diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php index 517acba..1af92e4 100644 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonSubTypesTest.php @@ -6,7 +6,9 @@ */ namespace Weasel\JsonMarshaller\Config\Annotations; -class JsonSubTypesTest extends \PHPUnit_Framework_TestCase +use PHPUnit\Framework\TestCase; + +class JsonSubTypesTest extends TestCase { /** diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php index cbdb47f..12c48fc 100644 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeInfoTest.php @@ -6,7 +6,9 @@ */ namespace Weasel\JsonMarshaller\Config\Annotations; -class JsonTypeInfoTest extends \PHPUnit_Framework_TestCase +use PHPUnit\Framework\TestCase; + +class JsonTypeInfoTest extends TestCase { /** diff --git a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php index 74952c5..a439f37 100644 --- a/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php +++ b/tests/Weasel/JsonMarshaller/Config/Annotations/JsonTypeNameTest.php @@ -6,7 +6,9 @@ */ namespace Weasel\JsonMarshaller\Config\Annotations; -class JsonTypeNameTest extends \PHPUnit_Framework_TestCase +use PHPUnit\Framework\TestCase; + +class JsonTypeNameTest extends TestCase { /** diff --git a/tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php b/tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php index 3869f0e..13963b4 100644 --- a/tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php +++ b/tests/Weasel/JsonMarshaller/Config/ClassAnnotationDriverTest.php @@ -1,6 +1,7 @@